網路爬蟲(Web rawler)
或叫 網路蜘蛛(Spider)
,是一套能搜集、解析網路上的訊息、資料,自動獲取該網域網站的摘要、重點甚至內容 的機器人。
看不太懂對不對?
沒關係,google一下就有了。
有沒有想過為什麼打開google搜尋引擎
,鍵入關鍵字、按一下Enter,就能搜尋相關的資料?
因為這就是Google這外星科技公司厲害的地方啊
因為Google就是個世界上最大之一的網路爬蟲啊
簡單地說,爬蟲是擷取網頁的重點內容,擷取並剖析。
而Google搜尋引擎就是到各個IP、各個網站擷取、解析資料並存進他們的資料庫,而使用者在下關鍵字時等同是進Google的引擎資料庫搜尋相關資料、跑出搜尋結果,點擊結果時會再導到該網站去。
其實我們所寫的爬蟲程式並不完全地叫作爬蟲,畢竟個人所寫的程式只能解析特定網站的格式,充其量只能叫做網頁剖析而已,很難做到公司規模等級的自動網路爬蟲。
寫爬蟲通常會用一套已經有完整工具的框架,
而這裡介紹的colly
是golang中爬蟲的主流框架。
Colly
為什麼叫摳哩,因為就是要摳東西啊!
Colly這個套件 使用到 GoQuery selector來做html parser
剖析網頁的語法。
以下路徑最末端要加上v2
才會指到最新版本(2.x.x):github.com/gocolly/colly/v2
go get -u github.com/gocolly/colly
package: .
import:
- package: github.com/gocolly/colly
version: ~2.1.0
在專案底下 放colly1.go程式
package main
import (
"github.com/gocolly/colly"
)
func main() {
}
僅用到以下短短三行程式碼,就能看到我在 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
。
搜尋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次
}
在 colly OnHTML 的參數goquerySelector
中可以用條件來篩選所要的HTML內容。
可以依照tag
、attr
、class
當作搜尋的條件來選取。
會依照以下網頁中的其中這些元素來做範例。
<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>
我想抓 文章標題 title
的tag
直接在OnHTML
中輸入tag名稱
c.OnHTML("title", func(e *colly.HTMLElement) {
fmt.Println(e.Text)
})
我想抓 meta
tag中,有 name
這個屬性的相關訊息
c.OnHTML("meta[name]", func(e *colly.HTMLElement) {
fmt.Println(e)
})
我想抓圖片中的文字,name="description"
這串屬性的content
c.OnHTML("meta[name='description']", func(e *colly.HTMLElement) {
fmt.Println(e.Attr("content")) // 抓此Tag中的name屬性 來找出此Tag,再印此Tag中的content屬性
})
我想以 CSS
來抓該 class
底下的字
c.OnHTML(".qa-list__title--ironman", func(e *colly.HTMLElement) {
fmt.Println(e.Text)
})
我想以 CSS
來抓該 id
底下的字
c.OnHTML("#read_more", func(e *colly.HTMLElement) {
fmt.Println(e.Text)
})
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")
}