使用go chromedp爬蟲 (新)


title: 使用go chromedp爬蟲
tags: go,chromedp
author: Clown95


背景

最近小伙伴通過某些手段獲取到了別人網(wǎng)站上的會員信息,所以他想讓我把會員賬號爬取下來。

image

其實網(wǎng)站的內(nèi)容很簡單,但是難就難在不知道怎能控制翻頁,它既不是通過url參數(shù)進行翻頁,也不是通過ajax參數(shù)翻頁。最終我選擇chromedp這個庫模擬瀏覽器操作,進行數(shù)據(jù)爬取。

其實這個頁面的爬取方式我之前已經(jīng)寫過一篇文章,但是進行代碼復(fù)用的時候,發(fā)現(xiàn)chromedp庫更新了原來的代碼已經(jīng)不兼容了,因此重新寫一篇記錄下以防以后還需使用。

這篇文章和之前文章,爬取的內(nèi)容都是一樣,所以我不在詳細(xì)的說明。

具體實現(xiàn)

設(shè)置Cookie

首先我需要使用chromedp設(shè)置瀏覽器Cookie來模擬登錄狀態(tài)

// 任務(wù) 主要用來設(shè)置cookie ,獲取登錄賬號后的頁面
func VisitWeb(url string, cookies ...string) chromedp.Tasks {
    //創(chuàng)建一個chrome任務(wù)
    return chromedp.Tasks{
        //ActionFunc是一個適配器,允許使用普通函數(shù)作為操作。
        chromedp.ActionFunc(func(ctx context.Context) error {
            // 設(shè)置Cookie存活時間
            expr := cdp.TimeSinceEpoch(time.Now().Add(180 * 24 * time.Hour))
            // 添加Cookie到chrome
            for i := 0; i < len(cookies); i += 2 {
                //SetCookie使用給定的cookie數(shù)據(jù)設(shè)置一個cookie; 如果存在,可能會覆蓋等效的cookie。
                success, err := network.SetCookie(cookies[i], cookies[i+1]).
                    // 設(shè)置cookie到期時間
                    WithExpires(&expr).
                    // 設(shè)置cookie作用的站點
                    WithDomain("dl.xzg01.com:83"). //訪問網(wǎng)站主體
                    // 設(shè)置httponly,防止XSS攻擊
                    WithHTTPOnly(true).
                    //Do根據(jù)提供的上下文執(zhí)行Network.setCookie。
                    Do(ctx)
                if err != nil {
                    return err
                }
                if !success {
                    return fmt.Errorf("could not set cookie %q to %q", cookies[i], cookies[i+1])
                }
            }
            return nil
        }),
        // 跳轉(zhuǎn)指定的url地址 
        chromedp.Navigate(url),
    }
}

獲取內(nèi)容

設(shè)置好Cookie后,接下來就是獲取網(wǎng)站內(nèi)容,一般獲取內(nèi)容我們使用的是chromedp.Text,這樣我們可以直接獲取的文本內(nèi)容。但是這個頁面比較坑的地方是它的標(biāo)簽是<tbody></tbody>,我之前獲取這個標(biāo)簽的內(nèi)容怎么都獲取不到,所以我折中一下獲取<tbody>標(biāo)簽的Html內(nèi)容。

翻頁的實現(xiàn),我是通過模擬點擊 > 標(biāo)簽來實現(xiàn)的。

image

// 任務(wù) 主要執(zhí)行翻頁功能和或者h(yuǎn)tml
func DoCrawler(res *string) chromedp.Tasks {
    return chromedp.Tasks{
        //下面注釋掉的 Navigate 不要隨便添加,如果添加上每次執(zhí)行都相當(dāng)于刷新,這樣就永遠(yuǎn)翻不了頁
        //chromedp.Navigate("http://dl.xzg01.com:83/OpRoot/MemberScoreList.aspx?uid=0&op=0&uname=003008"),
        chromedp.Sleep(1000),                // 等待
        chromedp.WaitVisible(`#form1`, chromedp.ByQuery), //等待id=from1頁面可見  ByQuery是使用DOM選擇器查找
        chromedp.Sleep(2*time.Second),
        // Click 是元素查詢操作,它將鼠標(biāo)單擊事件發(fā)送到與選擇器匹配的第一個元素節(jié)點。
        chromedp.Click(`.pagination li:nth-last-child(4) a`, chromedp.ByQuery), //點擊翻頁
        chromedp.OuterHTML(`tbody`, res, chromedp.ByQuery),        //獲取tbody標(biāo)簽的html
    }
}

數(shù)據(jù)處理

現(xiàn)在我們已經(jīng)獲取到html的內(nèi)容了,但是我們只需要會員賬號,所以我們需要對數(shù)據(jù)進行處理。

因為tbody標(biāo)簽,goquery無法獲取到它的內(nèi)容,所以我們把tbody替換成table。

func ReplaceStr(text string) string {
    return strings.Replace(text, "tbody", "table", -1)
}

可能有用戶會使用手機來注冊賬號,所以我們使用一個函數(shù)驗證賬號是否是手機號碼

func IsMobile(text string) bool {
    match,_:=regexp.MatchString(`^((\+86)|(86))?(1(([35][0-9])|[8][0-9]|[7][01356789]|[4][579]|[6][2567]))\d{8}$`,text)
    return  match
}

我們還需要把數(shù)據(jù)保存成文本

func WirteText(savefile string,txt string) {
    f, err := os.OpenFile(savefile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0777)
    if err != nil {
        fmt.Println("os Create error: ", err)
        return
    }
    defer f.Close()
    bw := bufio.NewWriter(f)
    bw.WriteString(txt + "\n")
    bw.Flush()
}

接下來我們就使用goquery來進行數(shù)據(jù)篩選

func GetAccount(text string) {

    dom, err := goquery.NewDocumentFromReader(strings.NewReader(ReplaceStr(text)))
    if err != nil {
        log.Fatalln(err)
    }
    dom.Find("tr").Each(func(i int, selection *goquery.Selection) {
        s:= selection.Find("td").Eq(6).Text()
        fmt.Println(s)
        WirteText("Acount.txt",s)
        if IsMobile(s) {
            WirteText("Mobile.txt",s)
        }
    })
}

執(zhí)行

package main

import (
    "chromedp/crawler"
    "chromedp/filtrate"
    "context"
    "github.com/chromedp/chromedp"
    "log"
)

func main() {

    ctx, cancel := chromedp.NewContext(
        context.Background(),
        chromedp.WithLogf(log.Printf),
    )
    defer cancel()

    //執(zhí)行任務(wù)
    url := "http://dl.xzg01.com:83/OpRoot/MemberScoreList.aspx?uid=0&op=0&uname=003008"
    err:= chromedp.Run(ctx, crawler.VisitWeb(url,
        "ASP.NET_SessionId", "zkamxkic4oiuwyc5obzgl2oj",
        "__cfduid", "d04d769b567cbe9e6f24369423b440f0d1575981989",
        "security_session_verify", "af027d69fbfbf4c925819043a50740b5",
    ))
    if err != nil {
        log.Fatal(err)
    }
    var res string
    for i := 1; i < 27170; i++ {
        //執(zhí)行
        err = chromedp.Run(ctx, crawler.DoCrawler(&res)) //執(zhí)行爬蟲任務(wù)
        if err != nil {
            log.Fatal(err)
        }
        filtrate.GetAccount(res)
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容