百度一下爬虫抓取豆瓣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构造剖析的过程。代码编写只是整个抓取过程的实现局部,并不会消耗很多的工夫。

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

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

欢送留言交换~