Golang+chromedp+goquery 簡單爬取動態數據
兵長:
胖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/,我們將網站上每天都會更新的一句話爬取出來
開始編碼
//獲取網站上爬取的數據
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動態生成數據后的)
右鍵點擊
item-bottom->Copy->Copy selector即可得到如下結果
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.Flag給chromedp設置參數,設置為無頭模式 headless,無頭模式即Chrome瀏覽器的無GUI的命令行版瀏覽器,但功能上和我們平常使用的chrome沒有區別,若該參數不設置為true,則在程序運行的時候,chromedp會拉取我們環境中的chrome瀏覽器,顯示頁面 -
chromedp.Flag("blink-settings", "imagesEnabled=false")設置為不顯示圖片 -
htmlContent用於接收爬取的結果,是一個字符串格式,具體內容是html -
chromedp.ByJSPath是只以什么方式進行解析,這是一個回調函數,這個參數還可以填下面幾個,按需索取chromedp.ByNodeIDchromedp.BySearchchromedp.ByIDchromedp.ByQueryAllchromedp.ByQuerychromedp.ByFunc
-
關於
chromedp涉及的接口如下給兵長介紹幾個名字 說明 Navigate 進入某個頁面 Run 運行各類操作 Screenshot 截屏 Click 模擬鼠標點擊 WaitVisible 等候某元素出現 ActionFunc 執行自定義函數 SendKeys 模擬鍵盤輸入
兵長: 使用這個框架我得到的是一串html的字符串,我也不會解析他呀,我要如何才能找到剛才在頁面上看到的每日一句?
胖sir:別擔心,我一步一步給你說,直播教學呢,看好了, 現在我們已經完成了最核心的一步了,現在數據已經獲取到了,咯,我給你介紹一個神奇,goquery就可以解決下面這一串html的解析問題了

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
-
進入自己的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
作者:小魔童哪吒
