乐趣区

关于golang:Go-Colly抓取豆瓣电影Top250

百度一下 爬虫抓取豆瓣 top250, 后果竟有 70 多页。

一、起因

为何豆瓣 Top250 如此受欢迎?因为它切实是太适宜做爬虫入门练习了。

简直没有任何反爬限度,要抓取的电影相干内容也全副都在源码中(没有异步加载,JS 动静批改 DOM 等状况)。

原本打算抓取掘金热门文章来着,然而发现数据根本都是 Ajax 申请接口获取,所以还是以豆瓣为例吧。

二、爬虫

因为第一份工作就是 Python 爬虫,所以对其余语言的爬虫框架也是比拟感兴趣的。

爬虫说简略也简略,会收回 Http 申请、理解一些 Html 基本知识、可能将数据保留下来,就算是爬虫入门了。但爬虫说难也难,如何高效的编写爬虫、如何保证数据的精确和实效、如何应答各种反爬机制、以及如何在合规非法的状况上来获取数据。

在 GitHub 上搜了一圈 Go 语言相干的框架,发现 Colly 一枝独秀,竟有11.6k✨

三、Colly

重要的事件只说一遍:肯定要去看官网文档,这个如同不是官网的 go-colly.org,然而也要浏览一遍才能够的。

挂一下官网 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,获取下一页 (列表页) 地址
  • ④反复②、③,直到没有下一页为止

4.1 下一页 URL 的获取

如图能够看到,当咱们处于第 1 页 (非最初一页) 时,span.next元素上面是有 a 元素的,外面的地址即为下一页。

当咱们翻到最初一页时,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 文件。

五、代码及后果展现

源码已上传至 GitHub, Gitee。

抓取数据后果如下:

六、后记

其实编写爬虫时,最耗时的是页面 Dom 构造剖析的过程。代码编写只是整个抓取过程的实现局部,并不会消耗很多的工夫。

如果消耗的很多的工夫(伪装在说他人????),那么你须要去看文档和官网示例了。

当你的才华和能力,不足以撑持你的幻想的时候,请静下心来学习。

欢送留言交换~

退出移动版