一、简介
随着互联网的快速发展,数据已经成为了一种非常重要的资源,各类用户都需要通过爬虫来获取所需的数据。在众多的编程语言中,Go语言以其高效、简洁、并发等特性,成为越来越优选的编程语言,并且在爬虫领域也有着广泛应用。
在爬虫框架领域,各流行编程语言都有自己热门框架,如Python中的selenium、Scrapy、PySpider等,Java中的Nutch、Crawler4j、WebMagic、WebCollector等。colly 是一款基于 Go 语言开发的网络爬虫框架,由于其出色的性能表现和易用性,colly 爬虫已经成为了很多开发者首选的爬虫框架之一。
归纳起来,colly 爬虫具有如下特征:
- 简洁API
- 快速(单核请求速率>1k/秒)
- 管理请求延迟和每个域的最大并发性
- 自动cookie和会话处理
- 同步/异步/分布式并行抓取
- 缓存
- 非unicode响应的自动编码
- Robots.txt网站地图支持
- 谷歌应用引擎支持
- 易于扩展和定制
二、colly爬虫生命周期与基本举例
(一)生命周期
使用colly的第一步:下载colly包
go get -u github.com/gocolly/colly/v2
第二步,在代码中导入包:
import "github.com/gocolly/colly/v2"
colly的主体是Collector对象,它管理网络通信和负责在作业运行时执行附加的回调函数。使用colly需要的第一步是必须先初始化Collector:
c := colly.NewCollector()
然后,可以向colly附加各种不同类型的回调函数,来控制收集作业或获取信息。增加回调函数:
c.OnRequest(func(r *colly.Request) {
fmt.Println("Visiting", r.URL)
})
c.OnError(func(_ *colly.Response, err error) {
log.Println("Something went wrong:", err)
})
c.OnResponse(func(r *colly.Response) {
fmt.Println("Visited", r.URL)
})
c.OnHTML("a[href]", func(e *colly.HTMLElement) {
e.Request.Visit(e.Attr("href"))
})
c.OnHTML("tr td:nth-of-type(1)", func(e *colly.HTMLElement) {
fmt.Println("First column of a table row:", e.Text)
})
c.OnScraped(func(r *colly.Response) {
fmt.Println("Finished", r.URL)
})
回调函数(可以理解为colly的生命周期函数)的调用顺序如下:
1. OnRequest
在发起请求前被调用
2. OnError
请求过程中如果发生错误被调用
3. OnResponse
收到回复后被调用
4. OnHTML
在OnResponse之后被调用,如果收到的内容是HTML
5. OnScraped
在OnHTML之后被调用。
归纳一下,colly 支持的生命周期事件函数(及类型),如下:
生命周期函数(事件) | 作用 |
NewCollector | 创建收集器对象 |
Visit | 开始访问 |
OnRequest | 请求执行之前调用,一般用来设置请求头等 |
OnResponse | 响应返回之后调用 |
OnHTML | 监听执行 selector,匹配指定元素后回调 |
OnXML | 监听执行 selector。和OnHTML类似,用于匹配xpath解析 |
OnHTMLDetach | 取消监听,参数为 selector 字符串 |
OnXMLDetach | 取消监听,参数为 selector 字符串 |
OnScraped | 完成抓取后执行,即在所有OnHTML之后执行,可以用来做一些回收操作 |
OnError | 请求发生错误回调,比如404错误 |
最后一步,c.Visit() 正式启动网页访问。
c.Visit("http://go-colly.org/")
(二)基础示例
官方提供的简单示例代码:
package main
import (
"fmt"
"github.com/gocolly/colly/v2"
)
func main() {
// Instantiate default collector
c := colly.NewCollector()
// Visit only domains: hackerspaces.org, wiki.hackerspaces.org
c.AllowedDomains = []string{"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/")
}
该实例程序仅访问hackerspaces.org域内的链接,OnHTML回掉函数的选择器为a[href],选择页面内具有href属性的a类型元素,找到链接后继续抓取。 运行的部分结果如下:
PS E:\mygo\src\github.com\gocolly\colly\_examples\basic> .\basic.exe
Visiting https://hackerspaces.org/
Link found: "navigation" -> #column-one
Link found: "search" -> #searchInput
Link found: "" -> /File:Cbase07.jpg
Visiting https://hackerspaces.org/File:Cbase07.jpg
Link found: "navigation" -> #column-one
Link found: "search" -> #searchInput
Link found: "File" -> #file
Link found: "File history" -> #filehistory
Link found: "File usage" -> #filelinks
Link found: "" -> /images/e/ec/Cbase07.jpg
Visiting https://hackerspaces.org/images/e/ec/Cbase07.jpg
Link found: "800 × 600 pixels" -> /images/thumb/e/ec/Cbase07.jpg/800px-Cbase07.jpg
Visiting https://hackerspaces.org/images/thumb/e/ec/Cbase07.jpg/800px-Cbase07.jpg
引用
- https://blog.csdn.net/small_to_large/article/details/130791204
- https://six.club/article/2654
- https://zhuanlan.zhihu.com/p/100155477
- https://cloud.tencent.com/developer/article/1429378
- https://pkg.go.dev/github.com/gocolly/colly/v2#pkg-types
- https://go-colly.org/docs/
- https://blog.51cto.com/u_15289640/5840410