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() // 等待所有请求完成
}

使用技巧

  1. 限制抓取范围:使用AllowedDomains限制只抓取特定域名的内容
  2. 并发控制:使用LimitRule控制请求频率和并发数
  3. 异步模式:启用异步模式提高抓取效率
  4. 错误处理:实现OnError回调处理抓取错误
  5. 数据存储:可以在回调函数中将抓取的数据存入数据库或文件

注意事项

  • 尊重网站的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)
	}
}

最佳实践

  1. 遵守robots.txt:Colly默认会检查robots.txt,建议保持这一行为
  2. 设置合理的延迟:避免对目标网站造成过大压力
  3. 错误处理:完善错误处理逻辑,记录失败请求
  4. 限制并发:根据目标网站情况设置合适的并发数
  5. 使用缓存:对于大规模爬取,考虑使用缓存避免重复请求

Colly是一个功能强大但使用简单的爬虫框架,通过合理配置可以满足大多数网页抓取需求,同时保持代码的简洁和可维护性。

回到顶部