Go Colly抓取豆瓣電影Top250

百度一下 爬蟲抓取豆瓣top250,結果竟有70多頁。

1、原由

爲什麼豆瓣Top250如此受歡迎?由於它實在是太適合作爬蟲入門練習了。git

幾乎沒有任何反爬限制,要抓取的電影相關內容也所有都在源碼中(沒有異步加載,JS動態修改DOM等狀況)。github

原本計劃抓取掘金熱門文章來着,可是發現數據基本都是Ajax請求接口獲取,因此仍是以豆瓣爲例吧。api

2、爬蟲

由於第一份工做就是Python爬蟲,因此對其餘語言的爬蟲框架也是比較感興趣的。框架

爬蟲說簡單也簡單,會發出Http請求、瞭解一些Html基本知識、可以將數據保存下來,就算是爬蟲入門了。但爬蟲說難也難,如何高效的編寫爬蟲、如何保證數據的準確和實效、如何應對各類反爬機制、以及如何在合規合法的狀況下去獲取數據。dom

在GitHub上搜了一圈Go語言相關的框架,發現Colly一枝獨秀,竟有11.6k✨異步

3、Colly

重要的事情只說一遍: 必定要去看官方文檔,這個好像不是官方的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/")
}

4、豆瓣頁面分析及代碼摘要

如圖,咱們要作的就是:url

  • ①打開首頁,獲取列表頁地址
  • ②進入列表頁
  • ③遍歷列表獲取詳情頁URL,獲取下一頁(列表頁)地址
  • ④重複②、③,直到沒有下一頁爲止

4.1 下一頁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))
    }
})

4.2 詳情頁列表URL的獲取

如圖,咱們只須要查找到div.article > ol.grid_view就找到了li列表的直接父元素。而後再依次遍歷li節點便可。咱們所需的a元素,在li節點下面div.hd > ahref屬性。

具體代碼以下:

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)
        }
    })
})

4.3 詳情頁內容獲取

咱們要獲取的內容:排名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()
    ...

4.4 後續處理

可對抓取到的數據進行清洗、整理,而後入庫等操做。本例僅將數據存儲至csv文件。

5、代碼及結果展現

源碼已上傳至GitHub, Gitee

抓取數據結果以下:

6、後記

其實編寫爬蟲時,最耗時的是頁面Dom結構分析的過程。代碼編寫只是整個抓取過程的實現部分,並不會耗費不少的時間。

若是耗費的不少的時間(僞裝在說別人😄),那麼你須要去看文檔和官方示例了。

當你的才華和能力,不足以支撐你的夢想的時候,請靜下心來學習。

歡迎留言交流~

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息