Golang爬蟲+正規表示式

小紫蘇發表於2021-12-22

最近學習go,爬取網站資料用到正規表示式,做個總結;

Go中正規表示式採用RE2語法(具體是啥我們也不清楚);

字元

. ——匹配任意字元 e.g: abc. 結果: abcd,abcx,abc9;

[] ——匹配括號中任意一個字元 e.g: [abc]d 結果:ad,cd,1d;

- ——[-]中表示範圍 e.g: [A-Za-z0-9];

^ ——[^]中表示除括號中的任意字元 e.g:[^xy]a 結果:aa,da,不能為xa,ya;

數量限定

? ——前面單元匹配0或1次;

+ ——前面單元匹配1或多次;

* ——前面單元匹配0或多次;

{,} ——顯示個數上下線;e.g : ip地址——[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3};

其他

\ ——轉義字元;

| ——條件或;

() ——組成單元 如果字串本身有括號"[(] aaa. [)]" ;

方法

//引數正則字串,返回值*Regexp
str := regexp.MustCompile(string)	
//引數要查詢的資料,查詢次數-1為全域性,返回值二維陣列,查詢出的字串+正則字串
var result [][]string = str.FindAllStringSubmatch(data, -1)

爬蟲

爬取部落格園所有文章閱讀量,評論,推薦;

package main

import (
	"fmt"
	"io"
	"net/http"
	"regexp"
	"strconv"
)

var readCount int = 0
var commentCount int = 0
var diggCount int = 0

//http讀取網頁資料寫入result返回
func HttpGet(url string) (result string, err error) {
	resp, err1 := http.Get(url)
	if err1 != nil {
		err = err1
		return
	}
	defer resp.Body.Close()

	buf := make([]byte, 4096)

	for {
		n, err2 := resp.Body.Read(buf)
		//fmt.Println(url)
		if n == 0 {
			break
		}
		if err2 != nil && err2 != io.EOF {
			err = err2
			return
		}
		result += string(buf[:n])
	}
	return result, err
}

//橫向縱向爬取文章標題資料,並累計數值
func SpiderPageDB(index int, page chan int) {
	url := "https://www.cnblogs.com/littleperilla/default.html?page=" + strconv.Itoa(index)
    
	result, err := HttpGet(url)

	if err != nil {
		fmt.Println("HttpGet err:", err)
		return
	}

	str := regexp.MustCompile("post-view-count\">閱讀[(](?s:(.*?))[)]</span>")
	alls := str.FindAllStringSubmatch(result, -1)
	for _, j := range alls {
		temp, err := strconv.Atoi(j[1])
		if err != nil {
			fmt.Println("string2int err:", err)
		}
		readCount += temp
	}

	str = regexp.MustCompile("post-comment-count\">評論[(](?s:(.*?))[)]</span>")
	alls = str.FindAllStringSubmatch(result, -1)
	for _, j := range alls {
		temp, err := strconv.Atoi(j[1])
		if err != nil {
			fmt.Println("string2int err:", err)
		}
		commentCount += temp
	}

	str = regexp.MustCompile("post-digg-count\">推薦[(](?s:(.*?))[)]</span>")
	alls = str.FindAllStringSubmatch(result, -1)
	for _, j := range alls {
		temp, err := strconv.Atoi(j[1])
		if err != nil {
			fmt.Println("string2int err:", err)
		}
		diggCount += temp
	}

	page <- index
}

//主要工作方法
func working(start, end int) {
	fmt.Printf("正在從%d到%d爬取中...\n", start, end)

	//channel通知主執行緒是否所有go都結束
	page := make(chan int)

	//多執行緒go程同時爬取
	for i := start; i <= end; i++ {
		go SpiderPageDB(i, page)
	}

	for i := start; i <= end; i++ {
		fmt.Printf("拉取到%d頁\n", <-page)
	}
}

//入口函式
func main() {
	//輸入爬取的起始頁
	var start, end int
	fmt.Print("startPos:")
	fmt.Scan(&start)
	fmt.Print("endPos:")
	fmt.Scan(&end)

	working(start, end)

	fmt.Println("閱讀:", readCount)
	fmt.Println("評論:", commentCount)
	fmt.Println("推薦:", diggCount)
}

相關文章