百度一下爬虫抓取豆瓣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 > 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) } })})
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构造剖析的过程。代码编写只是整个抓取过程的实现局部,并不会消耗很多的工夫。
如果消耗的很多的工夫(伪装在说他人????),那么你须要去看文档和官网示例了。
当你的才华和能力,不足以撑持你的幻想的时候,请静下心来学习。
欢送留言交换~