iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 23
5
Software Development

Go繁不及備載系列 第 23

# Day23 Golang 爬蟲框架 colly 摳哩

Day23 Golang 爬蟲框架 colly 摳哩

爬蟲是什麼

網路爬蟲(Web rawler)或叫 網路蜘蛛(Spider),是一套能搜集、解析網路上的訊息、資料,自動獲取該網域網站的摘要、重點甚至內容 的機器人。

看不太懂對不對?

沒關係,google一下就有了。
有沒有想過為什麼打開google搜尋引擎,鍵入關鍵字、按一下Enter,就能搜尋相關的資料?

因為這就是Google這外星科技公司厲害的地方啊
因為Google就是個世界上最大之一的網路爬蟲啊

簡單地說,爬蟲是擷取網頁的重點內容,擷取並剖析
而Google搜尋引擎就是到各個IP、各個網站擷取、解析資料並存進他們的資料庫,而使用者在下關鍵字時等同是進Google的引擎資料庫搜尋相關資料、跑出搜尋結果,點擊結果時會再導到該網站去。

其實我們所寫的爬蟲程式並不完全地叫作爬蟲,畢竟個人所寫的程式只能解析特定網站的格式,充其量只能叫做網頁剖析而已,很難做到公司規模等級的自動網路爬蟲。

寫爬蟲通常會用一套已經有完整工具的框架,
而這裡介紹的colly是golang中爬蟲的主流框架。

安裝 colly

Colly為什麼叫摳哩,因為就是要摳東西啊!
Colly這個套件 使用到 GoQuery selector來做html parser剖析網頁的語法。

以下路徑最末端要加上v2才會指到最新版本(2.x.x):github.com/gocolly/colly/v2

go get 全域安裝

go get -u github.com/gocolly/colly

glide 區域安裝

package: .
import:
  - package: github.com/gocolly/colly  
    version: ~2.1.0

在專案底下 放colly1.go程式

package main

import (
	"github.com/gocolly/colly"
)

func main() {

}

【colly OnResponse】

僅用到以下短短三行程式碼,就能看到我在 iT邦幫忙鐵人賽 文章列表的網頁原始碼哩。

package main

import (
	"fmt"

	"github.com/gocolly/colly"
)

func main() {
	c := colly.NewCollector() // 在colly中使用 Collector 這類物件 來做事情

	c.OnResponse(func(r *colly.Response) { // 當Visit訪問網頁後,網頁響應(Response)時候執行的事情
		fmt.Println(string(r.Body)) // 返回的Response物件r.Body 是[]Byte格式,要再轉成字串
	})

	c.OnRequest(func(r *colly.Request) { // iT邦幫忙需要寫這一段 User-Agent才給爬
		r.Headers.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36")
	})

	c.Visit("https://ithelp.ithome.com.tw/users/20125192/ironman/3155") // Visit 要放最後
}

來,摳好哩!

原始碼有了,距離所謂的自製爬蟲 就只差網頁剖析了,
也就是要解析在原始碼中出現的標籤html tag

【colly OnHTML 小坑注意】

搜尋qa-list__title-link這個class就能找到列表中第一頁的文章標題了。

透過count這個變數來讓我們更了解colly.OnHTML的運作。

var count = 0

func main() {

	c := colly.NewCollector()

	// 當Visit訪問網頁後,在網頁響應(Response)之後、發現這是HTML格式 執行的事情
	c.OnHTML(".qa-list__title-link", func(e *colly.HTMLElement) { // 每找到一個符合 goquerySelector字樣的結果,便會進這個OnHTML一次
		fmt.Println(e.Text)
		count++
	})

	c.OnRequest(func(r *colly.Request) { // iT邦幫忙需要寫這一段 User-Agent才給爬
		r.Headers.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36")
	})

	c.Visit("https://ithelp.ithome.com.tw/users/20125192/ironman/3155")

	fmt.Println(count) // count值為10,代表原始碼中 有10個符合規則的結果,總共進了OnHTML func 10次
}


爬蟲選取器 query Selector

colly OnHTML 的參數goquerySelector 中可以用條件來篩選所要的HTML內容。

可以依照tagattrclass當作搜尋的條件來選取。

會依照以下網頁中的其中這些元素來做範例。

<title>...</title>
<meta name="..." content="...">
<h3 class="qa-list__title qa-list__title--ironman">Go繁不及備載<span> 系列</span></h3>
<a href="/users/20125192" id="account" data-account="gjlmotea">我的主頁</a>

【Tag 標籤】

我想抓 文章標題 title的tag
直接在OnHTML中輸入tag名稱

c.OnHTML("title", func(e *colly.HTMLElement) {
	fmt.Println(e.Text)
})

抓Title

【Attr 屬性】

我想抓 meta tag中,有 name 這個屬性的相關訊息

c.OnHTML("meta[name]", func(e *colly.HTMLElement) {
	fmt.Println(e)
})

【AttrVal 屬性值】

我想抓圖片中的文字,name="description"這串屬性的content

c.OnHTML("meta[name='description']", func(e *colly.HTMLElement) {
	fmt.Println(e.Attr("content")) // 抓此Tag中的name屬性 來找出此Tag,再印此Tag中的content屬性
})

抓meta name

【CSS Class 名稱】

我想以 CSS來抓該 class底下的字

c.OnHTML(".qa-list__title--ironman", func(e *colly.HTMLElement) {
	fmt.Println(e.Text)
})

抓CSS class

【CSS ID 唯一識別】

我想以 CSS來抓該 id底下的字

c.OnHTML("#read_more", func(e *colly.HTMLElement) {
	fmt.Println(e.Text)
})

抓CSS ID


完整程式碼

package main

import (
	"fmt"

	"github.com/gocolly/colly"
)

func main() {

	c := colly.NewCollector()

	// 抓標籤Tag
	c.OnHTML("title", func(e *colly.HTMLElement) {
		fmt.Println(e.Text)
	})

	// 抓屬性值 AttrVal
	c.OnHTML("meta[name='description']", func(e *colly.HTMLElement) {
		fmt.Println(e.Attr("content")) // 抓此Tag中的name屬性 來找出此Tag,再印此Tag中的content屬性
	})

	// 抓類別Class 名稱
	c.OnHTML(".qa-list__title--ironman", func(e *colly.HTMLElement) {
		fmt.Println(e.Text)
	})

	// 抓唯一識別 ID
	c.OnHTML("#read_more", func(e *colly.HTMLElement) {
		fmt.Println(e.Text)
	})

	c.OnRequest(func(r *colly.Request) { // iT邦幫忙需要寫這一段 User-Agent才給爬
		r.Headers.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36")
	})

	c.Visit("https://ithelp.ithome.com.tw/users/20125192/ironman/3155")
}

上一篇
# Day22 Golang 網頁框架 gin 實作小專案 (RESTful API)
下一篇
# Day24 Golang 爬蟲框架 colly 來爬鐵人賽文吧
系列文
Go繁不及備載35

尚未有邦友留言

立即登入留言