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