如果想用 GO 实现爬虫能力,该如何做呢?抽时间研究了 Go 的一款爬虫框架 colly。
colly 是 Go 实现的比较有名的一款爬虫框架,而且 Go 在高并发和分布式场景的优势也正是爬虫技术所需要的。它的主要特点是轻量、快速,设计非常优雅,并且分布式的支持也非常简单,易于扩展。
爬虫最有名的框架应该就是 Python 的 scrapy,很多人最早接触的爬虫框架就是它,我也不例外。它的文档非常齐全,扩展组件也很丰富。当我们要设计一款爬虫框架时,常会参考它的设计。之前看到一些文章介绍 Go 中也有类似 scrapy 的实现。
相比而言,colly 的学习资料就少的可怜了。刚看到它的时候,我总会情不自禁想借鉴我的 scrapy 使用经验,但结果发现这种生搬硬套并不可行。
到此,我们自然地想到去找些文章阅读,但结果是 colly 相关文章确实有点少,能找到的基本都是官方提供的,而且看起来似乎不是那么完善。没办法,慢慢啃吧!官方的学习资料通常都会有三处,分别是文档、案例和源码。
今天,暂时先从官方文档角度吧!正文开始。
官方文档介绍着重使用方法,如果是有爬虫经验的朋友,扫完一遍文档很快。我花了点时间将官网文档的按自己的思路整理了一版。
主体内容不多,涉及安装、快速开始、如何配置、调试、分布式爬虫、存储、运用多收集器、配置优化、扩展。
其中的每篇文档都很短小,甚至是少的基本都不用翻页滚动。
colly 的安装和其他的 Go 库安装一样简单。如下:
go get -u github.com/gocolly/colly
一行命令搞定。So easy!
我们来通过一个 hello word 案例快速体验下 colly 的使用。步骤如下:
第一步,导入 colly。
import "github.com/gocolly/colly"
第二步,创建 collector。
c := colly.NewCollector()
第三步,事件监听,通过 callback 执行事件处理。
// Find and visit all links
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))
})
c.OnRequest(func(r *colly.Request) {
fmt.Println("Visiting", r.URL)
})
我们顺便列举一下 colly 支持的事件类型,如下:
最后一步,c.Visit() 正式启动网页访问。
c.Visit("http://go-colly.org/")
案例的完成代码在 colly 源码的 _example 目录下 basic 中提供。
colly 是一款配置灵活的框架,提供了大量的可供开发人员配置的选项。默认情况下,每个选项都提供了较优的默认值。
如下是采用默认创建的 collector。
c := colly.NewCollector()
配置创建的 collector,比如设置 useragent 和允许重复访问。代码如下:
c2 := colly.NewCollector(
colly.UserAgent("xy"),
colly.AllowURLRevisit(),
)
我们也可以创建后再改变配置。
c2 := colly.NewCollector()
c2.UserAgent = "xy"
c2.AllowURLRevisit = true
collector 的配置可以在爬虫执行到任何阶段改变。一个经典的例子,通过随机改变 user-agent,可以帮助我们实现简单的反爬。
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
func RandomString() string {
b := make([]byte, rand.Intn(10