Golang+chromedp+goquery 簡單爬取動態資料

阿兵雲原生發表於2021-03-05
[TOC]

兵長:

胖sir,最近一段時間正在使用golang來進行開發專案,慢慢的對golang有了一些瞭解,突然有一天,我想用golang來實現爬取網站上的資料,例如天氣預報每日一句等等
發現這些網站的資料都是javascript動態生成,苦惱呀,不知道如何才能把網站上的動態資料獲取下來,為我所用呀,例如我抓取到動態資料之後發郵件給我喲

胖sir撩撩了自己的長髮,溫和的對兵長說,小夥子,golang做應用開發效率很快的,當然爬取網站上的資料也是不在話下的喲,動態的也有動態的方法,來我給你娓娓道來

Golang的安裝

此步驟主要是為了照顧沒有在linux上安裝過golang的童鞋們,若自己做過安裝過golang的童鞋可以直接跳過golang簡單安裝步驟

下載golang軟體

  • 【國內網站】https://studygolang.com/dlgo語言中文網下載 go最新的安裝包,根據不同的系統,可以選擇 windows,linux,mac
  • 【可以上外網的話】訪問go語言英文網站https://docs.studygolang.com/doc/install

解壓golang

tar -C /usr/local -xzf go1.16.linux-amd64.tar.gz

配置golang

  • 將go的二進位制目錄新增到PATH環境變數

    vim /etc/profile
    export GOROOT=/usr/local/go
    export PATH=$PATH:$GOROOT/bin

重新匯入配置

source /etc/profile

chromedp框架的使用

chromedp框架github開源的,童鞋們可以放心食用,若是有想法,可以在github上為此添磚加瓦,為開源做出自己的一份貢獻

可以透過如下命令來進行下載

github.com/chromedp/chromedp

實際的程式碼編寫

兵長,你想爬取每日一句的網站,我給你找一個例子,如爬取這個網站http://news.iciba.com/,我們將網站上每天都會更新的一句話爬取出來

image-20210303224355228

開始編碼

//獲取網站上爬取的資料
func GetHttpHtmlContent(url string, selector string, sel interface{}) (string, error) {
    options := []chromedp.ExecAllocatorOption{
        chromedp.Flag("headless", true), // debug使用
        chromedp.Flag("blink-settings", "imagesEnabled=false"),
        chromedp.UserAgent(`Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36`),
    }
    //初始化引數,先傳一個空的資料    
    options = append(chromedp.DefaultExecAllocatorOptions[:], options...)

    c, _ := chromedp.NewExecAllocator(context.Background(), options...)

    // create context
    chromeCtx, cancel := chromedp.NewContext(c, chromedp.WithLogf(log.Printf))
    // 執行一個空task, 用提前建立Chrome例項
    chromedp.Run(chromeCtx, make([]chromedp.Action, 0, 1)...)

    //建立一個上下文,超時時間為40s
    timeoutCtx, cancel := context.WithTimeout(chromeCtx, 40*time.Second)
    defer cancel()

    var htmlContent string
    err := chromedp.Run(timeoutCtx,
        chromedp.Navigate(url),
        chromedp.WaitVisible(selector),
        chromedp.OuterHTML(sel, &htmlContent, chromedp.ByJSPath),
    )
    if err != nil {
        logger.Info("Run err : %v\n", err)
        return "", err
    }
    //log.Println(htmlContent)

    return htmlContent, nil
}
  • GetHttpHtmlContent做為一個爬取網站動態資料的介面,主要功能是爬取js生成的動態資料(當然靜態資料更是不在話下)

  • 第一個引數 url即為我們需要傳入的要爬取的網站地址,頁面如上

  • 第二個引數 selector即為我們爬取的資料對應的選html擇器, 透過谷歌瀏覽器進入網站,按F12 -> 點選左上角的滑鼠 -> 再點選我們需要爬取的資料 -> 就可以看到實際的html原始碼(目前看到的是透過javascript動態生成資料後的)

    image-20210303230303671

    右鍵點選item-bottom -> Copy-> Copy selector 即可得到如下結果

    image-20210303230803415

    body > div.screen > div.banner > div.swiper-container-place > div > div.swiper-slide.swiper-slide-0.swiper-slide-visible.swiper-slide-active > a.item.item-big > div.item-bottom

    此字串即為GetHttpHtmlContent 函式的第二個引數selector

  • 第三個引數 我們暫時先寫

    document.querySelector("body") //從body裡面獲取資料
  • 返回值 即為 爬取到的資料,是字串格式的,內容是 html

如下是擴充和解釋上述程式碼的內容

  • chromedp.Flagchromedp設定引數,設定為 無頭模式 headless,無頭模式即Chrome瀏覽器的無GUI的命令列版瀏覽器,但功能上和我們平常使用的chrome沒有區別,若該引數不設定為true,則在程式執行的時候,chromedp會拉取我們環境中的chrome瀏覽器,顯示頁面

  • chromedp.Flag("blink-settings", "imagesEnabled=false")設定為不顯示圖片

  • htmlContent用於接收爬取的結果,是一個字串格式,具體內容是html

  • chromedp.ByJSPath 是隻以什麼方式進行解析,這是一個回撥函式,這個引數還可以填下面幾個,按需索取

    • chromedp.ByNodeID
    • chromedp.BySearch
    • chromedp.ByID
    • chromedp.ByQueryAll
    • chromedp.ByQuery
    • chromedp.ByFunc
  • 關於chromedp涉及的介面如下給兵長介紹幾個

    名字 說明
    Navigate 進入某個頁面
    Run 執行各類操作
    Screenshot 截圖
    Click 模擬滑鼠點選
    WaitVisible 等候某元素出現
    ActionFunc 執行自定義函式
    SendKeys 模擬鍵盤輸入

兵長: 使用這個框架我得到的是一串html的字串,我也不會解析他呀,我要如何才能找到剛才在頁面上看到的每日一句

胖sir:別擔心,我一步一步給你說,直播教學呢,看好了, 現在我們已經完成了最核心的一步了,現在資料已經獲取到了,咯,我給你介紹一個神奇,goquery就可以解決下面這一串html的解析問題了

image-20210303232139506

goquery第三方庫的使用

我之前寫過一個小介面,可以給你看看,兵長

goquery也是github開源的,童鞋們可以放心食用哦,透過如下命令在下載goquery第三方庫

go get github.com/PuerkitoBio/goquery

開始編碼

//得到具體的資料
func GetSpecialData(htmlContent string, selector string) (string, error) {
    dom, err := goquery.NewDocumentFromReader(strings.NewReader(htmlContent))
    if err != nil {
        logger.Error(err)
        return "", err
    }

    var str string
    dom.Find(selector).Each(func(i int, selection *goquery.Selection) {
        str = selection.Text()
    })
    return str, nil
}
  • 第一個引數 htmlContent 就是 上面 chromedp爬取到的資料,是字串,內容是html

  • 第二個引數即是html的選擇器 ,對於這個網站,這個引數可以填 .chinese,如

    GetSpecialData(htmlContent, ".chinese")
  • 返回值就是我們要抓取的結果了 當你是在為夢想成真努力時,就不會有壓力。

如下是關於goquery一些用法

主要是關於html各種選擇器的寫法使用方式,下面簡單介紹一下種類,如果需要詳細瞭解,可以給我留言喲

  • 基於HTML Element 元素的選擇器
  • ID 選擇器
  • Class選擇器
  • 屬性選擇器
  • parent > child選擇器
  • element + next 相鄰選擇器
  • element~next 兄弟選擇器

胖sir:兵長,我說的這些還算清楚吧,你知道怎麼用了嗎?

兵長:明~明白了,我還要多加練習,多多爬取一下不同的站資料看看效果

胖sir:誒,兵長剛才你說你想將資料處理完畢後,發郵件給你自己嗎?

兵長:對呀,誒呀,這又是個問題。我不知道把程式放在那裡呢,放在我自己電腦裡面的話,我電腦每天是要關機的,我休息了,我的電腦也要跟著我休息,誒,咋辦呀

胖sir:好辦,這個我可以推薦你用一下 阿里雲伺服器

如何將自己的程式部署到阿里雲伺服器上

自己買一個雲伺服器就可以很方便的將自己的監控程式或者需要一直執行的程式放在上面,這就可以7*24小時不間斷的跑了,我最近感受了一下,確實好用。具體的阿里雲購買方式可以嘗試掃描下面的二維碼或者點選連結進行購買,親測真的好用,如何使用和簡單配置,可以給我留言獲取資料。

當然,需要上述整個小案例原始碼的,也可以給我留言哦,讓我們一起實踐我們的每一個想法,一步一步往上爬。

胖sir:兵長,我需要提醒一點哦,阿里雲伺服器會自動把你的執行程式關閉掉了的

兵長:啊?那麼你還讓我買伺服器,你這不是坑我嗎

胖sir:別急,我推薦的肯定是好東西啦,還附帶解決方案喲

screen工具

screen工具可以幫助我們將可執行程式部署到阿里雲伺服器上面,且能夠一直不間斷的執行

原理:

screen是在伺服器上單獨開一個程式,讓他專門來執行後臺任務。

具體操作:

  • 安裝

    //ubuntu安裝
    sudo apt-get install screen
    //centos
    yum install screen
  • 建立screen視窗

    screen -S  name
    例如:
    screen -S  ssh
  • 檢視程式

    screen -ls

    image-20210303234906943

  • 進入自己的manager

    screen -r -d 自己的id
    如:
    screen -r -d 5295
  • 關閉screen程式

    screen -S 程式名 -X quit

大家如果有需要,可以透過此連結購買阿里雲伺服器,目前萌新有優惠,親測很可,別問我是誰,我是小魔童哪吒。

https://www.aliyun.com/activity?taskCode=messenger2101&recordId=337686&usercode=&share_source=copy_link

作者:小魔童哪吒

本作品採用《CC 協議》,轉載必須註明作者和本文連結
關注微信公眾號:阿兵雲原生

相關文章