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 -> %sn", 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文件。
五、代码及结果展示
抓取数据结果如下:
六、后记
其实编写爬虫时,最耗时的是页面Dom结构分析的过程。代码编写只是整个抓取过程的实现部分,并不会耗费很多的时间。
如果耗费的很多的时间(假装在说别人?),那么你需要去看文档和官方示例了。
当你的才华和能力,不足以支撑你的梦想的时候,请静下心来学习。
欢迎留言交流~
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Linux C 后台服务程序单进程控制的实现
- Linux下SSH免密码登录配置详解
- SSH端口转发实现内网穿透的实现
- 在linux中用同一个版本的R 同时安装 Seurat2 和 Seurat3的教程
- AUCell:在单细胞转录组中识别细胞对“基因集”的响应
- linux查看硬件配置命令的方法示例
- Ubuntu环境编译安装PHP和Nginx的方法
- Ubuntu环境源码编译安装xdebug的方法
- CNS图表复现07—原来这篇文章有两个单细胞表达矩阵
- CentOS 7.x 安装 ZSH 终端的配置方法
- centos7 安装mysql和mysqlclient遇到的坑总结
- iOS音视频接入- TRTC计费及套餐介绍
- Linux简介及最常用命令(简单易学,但能解决95%以上的问题)
- Linux一行命令处理批量文件详解
- Linux中jar包启动和jar包后台运行的实现方式