百度一下
爬蟲抓取豆瓣top250
,結果竟有70多頁。
爲什麼豆瓣Top250如此受歡迎?由於它實在是太適合作爬蟲入門練習了。git
幾乎沒有任何反爬限制,要抓取的電影相關內容也所有都在源碼中(沒有異步加載,JS動態修改DOM等狀況)。github
原本計劃抓取掘金熱門文章來着,可是發現數據基本都是Ajax請求接口獲取,因此仍是以豆瓣爲例吧。api
由於第一份工做就是Python爬蟲,因此對其餘語言的爬蟲框架也是比較感興趣的。框架
爬蟲說簡單也簡單,會發出Http請求、瞭解一些Html基本知識、可以將數據保存下來,就算是爬蟲入門了。但爬蟲說難也難,如何高效的編寫爬蟲、如何保證數據的準確和實效、如何應對各類反爬機制、以及如何在合規合法的狀況下去獲取數據。dom
在GitHub上搜了一圈Go語言相關的框架,發現Colly一枝獨秀,竟有11.6k✨
。異步
重要的事情只說一遍: 必定要去看官方文檔,這個好像不是官方的go-colly.org,可是也要瀏覽一遍才能夠的。ide
掛一下官方example
裏面的basic
示例吧。註釋很詳細,因此官方示例必定要看!!!學習
func main() { // Instantiate default collector c := colly.NewCollector( // Visit only domains: hackerspaces.org, wiki.hackerspaces.org colly.AllowedDomains("hackerspaces.org", "wiki.hackerspaces.org"), ) // On every a element which has href attribute call callback c.OnHTML("a[href]", func(e *colly.HTMLElement) { link := e.Attr("href") // Print link fmt.Printf("Link found: %q -> %s\n", e.Text, link) // Visit link found on page // Only those links are visited which are in AllowedDomains c.Visit(e.Request.AbsoluteURL(link)) }) // Before making a request print "Visiting ..." c.OnRequest(func(r *colly.Request) { fmt.Println("Visiting", r.URL.String()) }) // Start scraping on https://hackerspaces.org c.Visit("https://hackerspaces.org/") }
如圖,咱們要作的就是:url
如圖能夠看到,當咱們處於第1頁(非最後一頁)時,span.next
元素下面是有a
元素的,裏面的地址即爲下一頁。spa
當咱們翻到最後一頁時,a
元素不見了。所以咱們能夠根據是否有a
元素來判斷是否是已經抓取徹底部數據了。
Colly中使用goquerySelector
來選擇元素,也可使用XPath來作選擇
,有興趣的能夠了解一下。這裏咱們使用goquerySelector
。
下一頁URL獲取代碼以下:
collector.OnHTML("div.paginator > span.next", func(element *colly.HTMLElement) { href, found := element.DOM.Find("a").Attr("href") // 若是有下一頁,則繼續訪問 if found { element.Request.Visit(element.Request.AbsoluteURL(href)) } })
如圖,咱們只須要查找到div.article > ol.grid_view
就找到了li
列表的直接父元素。而後再依次遍歷li
節點便可。咱們所需的a
元素,在li
節點下面div.hd > a
的href
屬性。
具體代碼以下:
collector.OnHTML("ol.grid_view", func(element *colly.HTMLElement) { // 依次遍歷全部的li節點 element.DOM.Find("li").Each(func(i int, selection *goquery.Selection) { href, found := selection.Find("div.hd > a").Attr("href") // 若是找到了詳情頁,則繼續下一步的處理 if found { parseDetail(collector, href, writer) log.Println(href) } }) })
咱們要獲取的內容:排名Idx,標題title,年份year,基本信息info,評分rating,地址url。
分析完頁面Dom結構以後,整個抓取代碼的編寫就變得簡單了起來。
具體信息獲取代碼以下:
collector.OnHTML("body", func(element *colly.HTMLElement) { selection := element.DOM.Find("div#content") idx := selection.Find("div.top250 > span.top250-no").Text() title := selection.Find("h1 > span").First().Text() year := selection.Find("h1 > span.year").Text() info := selection.Find("div#info").Text() info = strings.ReplaceAll(info, " ", "") info = strings.ReplaceAll(info, "\n", "; ") rating := selection.Find("strong.rating_num").Text() ...
可對抓取到的數據進行清洗、整理,而後入庫等操做。本例僅將數據存儲至csv文件。
抓取數據結果以下:
其實編寫爬蟲時,最耗時的是頁面Dom結構分析的過程。代碼編寫只是整個抓取過程的實現部分,並不會耗費不少的時間。
若是耗費的不少的時間(僞裝在說別人😄),那麼你須要去看文檔和官方示例了。
當你的才華和能力,不足以支撐你的夢想的時候,請靜下心來學習。
歡迎留言交流~