golang快速优雅的网页抓取框架插件colly的使用
Golang快速优雅的网页抓取框架插件Colly的使用
Colly是一个为Gopher设计的闪电般快速且优雅的爬虫框架,它提供了清晰的接口来编写任何类型的爬虫/抓取器/蜘蛛程序。
特性
- 简洁的API
- 快速(单核每秒可处理>1000个请求)
- 管理每个域的请求延迟和最大并发数
- 自动处理cookie和会话
- 支持同步/异步/并行抓取
- 缓存功能
- 自动编码非unicode响应
- 支持Robots.txt
- 分布式抓取
- 通过环境变量配置
- 扩展功能
安装
在go.mod
文件中添加colly依赖:
module github.com/x/y
go 1.14
require (
github.com/gocolly/colly/v2 latest
)
基础示例
下面是一个简单的Colly使用示例,它会抓取指定网站的所有链接:
package main
import (
"fmt"
"github.com/gocolly/colly/v2"
)
func main() {
// 创建一个新的Collector实例
c := colly.NewCollector()
// 查找并访问所有链接
c.OnHTML("a[href]", func(e *colly.HTMLElement) {
// 提取href属性并访问链接
e.Request.Visit(e.Attr("href"))
})
// 在请求前打印URL
c.OnRequest(func(r *colly.Request) {
fmt.Println("Visiting", r.URL)
})
// 开始抓取
c.Visit("http://go-colly.org/")
}
进阶示例
下面是一个更完整的示例,展示如何抓取并提取结构化数据:
package main
import (
"fmt"
"github.com/gocolly/colly/v2"
)
func main() {
// 创建Collector实例
c := colly.NewCollector(
// 限制域名
colly.AllowedDomains("example.com"),
// 启用异步
colly.Async(true),
)
// 限制并发数为2
c.Limit(&colly.LimitRule{
DomainGlob: "*example.*",
Parallelism: 2,
Delay: 1 * time.Second,
})
// 提取文章标题
c.OnHTML("article h1", func(e *colly.HTMLElement) {
fmt.Println("文章标题:", e.Text)
})
// 提取文章内容
c.OnHTML(".article-content", func(e *colly.HTMLElement) {
fmt.Println("文章内容:", e.Text)
})
// 错误处理
c.OnError(func(r *colly.Response, err error) {
fmt.Println("请求URL:", r.Request.URL, "失败:", err)
})
// 开始抓取
c.Visit("https://example.com/articles")
c.Wait() // 等待所有请求完成
}
使用技巧
- 限制抓取范围:使用
AllowedDomains
限制只抓取特定域名的内容 - 并发控制:使用
LimitRule
控制请求频率和并发数 - 异步模式:启用异步模式提高抓取效率
- 错误处理:实现
OnError
回调处理抓取错误 - 数据存储:可以在回调函数中将抓取的数据存入数据库或文件
注意事项
- 尊重网站的robots.txt规则
- 控制请求频率,避免给目标网站造成过大负担
- 处理可能出现的各种网络错误
- 对于需要登录的网站,可以使用
c.SetCookies()
设置cookie
Colly是一个功能强大但使用简单的网页抓取框架,非常适合在Golang项目中实现各种网页抓取需求。
更多关于golang快速优雅的网页抓取框架插件colly的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang快速优雅的网页抓取框架插件colly的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用Colly进行优雅高效的网页抓取
Colly是Go语言中一个快速优雅的网页抓取框架,它提供了简洁的API和强大的功能,使得爬虫开发变得简单高效。下面我将详细介绍Colly的使用方法。
安装Colly
首先安装Colly包:
go get -u github.com/gocolly/colly/v2
基本使用示例
package main
import (
"fmt"
"github.com/gocolly/colly/v2"
)
func main() {
// 创建Collector实例
c := colly.NewCollector(
// 限制域名,只爬取example.com下的链接
colly.AllowedDomains("example.com"),
// 启用异步请求
colly.Async(true),
)
// 限制并发数为2
c.Limit(&colly.LimitRule{
DomainGlob: "*",
Parallelism: 2,
Delay: 1 * time.Second, // 请求间延迟
})
// 当发现有链接时的回调
c.OnHTML("a[href]", func(e *colly.HTMLElement) {
link := e.Attr("href")
fmt.Printf("发现链接: %s\n", e.Request.AbsoluteURL(link))
// 访问发现的链接
e.Request.Visit(link)
})
// 请求前的回调
c.OnRequest(func(r *colly.Request) {
fmt.Println("正在访问:", r.URL)
})
// 请求完成后的回调
c.OnResponse(func(r *colly.Response) {
fmt.Printf("访问完成: %s 状态码: %d\n", r.Request.URL, r.StatusCode)
})
// 错误处理
c.OnError(func(r *colly.Response, err error) {
fmt.Printf("请求URL: %s 失败: %v\n", r.Request.URL, err)
})
// 开始爬取
c.Visit("http://example.com/")
// 等待所有异步请求完成
c.Wait()
}
高级功能
1. 提取页面数据
c.OnHTML("article", func(e *colly.HTMLElement) {
title := e.ChildText("h1")
content := e.ChildText("div.content")
date := e.ChildAttr("time", "datetime")
fmt.Printf("文章标题: %s\n发布时间: %s\n内容: %s\n",
title, date, content)
})
2. 处理分页
c.OnHTML("a.next-page", func(e *colly.HTMLElement) {
nextPage := e.Request.AbsoluteURL(e.Attr("href"))
c.Visit(nextPage)
})
3. 使用代理
c.SetProxy("http://proxy.example.com:8080")
4. 随机User-Agent
c.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
5. 处理JavaScript渲染的页面
Colly本身不支持JS渲染,但可以结合chromedp使用:
import "github.com/chromedp/chromedp"
// 先用chromedp获取渲染后的HTML
var htmlContent string
err := chromedp.Run(ctx,
chromedp.Navigate("http://example.com"),
chromedp.OuterHTML("html", &htmlContent),
)
// 然后用colly解析
c.OnResponse(func(r *colly.Response) {
r.Ctx.Put("html", htmlContent)
})
c.OnScraped(func(r *colly.Response) {
html := r.Ctx.Get("html")
// 解析html...
})
实际案例:抓取新闻标题和链接
package main
import (
"fmt"
"log"
"time"
"github.com/gocolly/colly/v2"
)
type News struct {
Title string
URL string
Time string
}
func main() {
newsList := make([]News, 0)
c := colly.NewCollector(
colly.AllowedDomains("news.example.com"),
colly.Async(true),
colly.UserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64)"),
)
c.Limit(&colly.LimitRule{
DomainGlob: "*",
Parallelism: 2,
Delay: 1 * time.Second,
RandomDelay: 1 * time.Second,
})
// 提取新闻条目
c.OnHTML(".news-item", func(e *colly.HTMLElement) {
news := News{
Title: e.ChildText("h2"),
URL: e.Request.AbsoluteURL(e.ChildAttr("a", "href")),
Time: e.ChildText(".time"),
}
newsList = append(newsList, news)
})
// 处理分页
c.OnHTML("a.next", func(e *colly.HTMLElement) {
nextPage := e.Request.AbsoluteURL(e.Attr("href"))
c.Visit(nextPage)
})
c.OnRequest(func(r *colly.Request) {
fmt.Println("Visiting", r.URL)
})
c.OnError(func(r *colly.Response, err error) {
log.Println("Request URL:", r.Request.URL, "failed with response:", r, "\nError:", err)
})
c.Visit("http://news.example.com/latest")
c.Wait()
// 输出结果
for i, news := range newsList {
fmt.Printf("%d. %s (%s)\n链接: %s\n\n", i+1, news.Title, news.Time, news.URL)
}
}
最佳实践
- 遵守robots.txt:Colly默认会检查robots.txt,建议保持这一行为
- 设置合理的延迟:避免对目标网站造成过大压力
- 错误处理:完善错误处理逻辑,记录失败请求
- 限制并发:根据目标网站情况设置合适的并发数
- 使用缓存:对于大规模爬取,考虑使用缓存避免重复请求
Colly是一个功能强大但使用简单的爬虫框架,通过合理配置可以满足大多数网页抓取需求,同时保持代码的简洁和可维护性。