Golang+chromedp+goquery 簡單爬取動態數據


Golang+chromedp+goquery 簡單爬取動態數據

兵長:

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

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

Golang的安裝

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

下載golang軟件

  • 【國內網站】https://studygolang.com/dl go語言中文網下載 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

作者:小魔童哪吒


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM