jinzh notes
jinzh notes

go爬虫学习(一)

go爬虫学习(一)
内容纲要

前言

目前需求是想用go写出来一个可以直接爬取网站上的代理ip的爬虫出来,采取的架构为:后端go实现,前端由vue实现,go爬取到的ip使用sqlite数据库存储!

先实现后端的爬取ip代理网站的功能,然后再实现存储到数据库中的功能,最后实现前端的构建

框架选取

colly是go使用最为广泛的框架,对其进行学习并使用!

特点

  • 简洁的API
  • 快速 (单核上>1k请求/秒)
  • 管理每个域的请求延时和最大并发性
  • Cookie和Session的自动处理
  • 同步/异步/并行 抓取
  • 分布式抓取
  • 缓存
  • 自动编码非Unicode响应
  • Robots.txt支持
  • 谷歌应用引擎支持

学习

colly包的官方文档地址:Scraping Framework for Golang (go-colly.org)

go包的官方地址:colly package – github.com/gocolly/colly – pkg.go.dev

colly的安装

#官方指令
go get -u github.com/gocolly/colly/...

包导入

import "github.com/gocolly/colly"

初次使用

Colly的主入口为一个Collector结构体(对象),一切操作均以它展开,我们以下称之为收集器

Collector manages the network communication and responsible for the execution of the attached callbacks while a collector job is running.

收集器管理网络通信并且负责在任务执行时执行附加的回调函数。

首先,创建一个收集器对象,使用包自带的NewCollector()函数,该函数返回一个Collector类型指针,随后的一系列操作都是围绕这个指针进行!

c := colly.NewCollector()

然后就是官方所附带的一系列回调(Callback)函数

You can attach different type of callback functions to a Collector to control a collecting job or retrieve information.

可以使用不同的回调函数来控制一个任务或者重写相关信息(配置)

回调函数(方法)列表:

#在请求前调用
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.OnResponseHeaders(func(r *colly.Response) {
    fmt.Println("Visited", r.Request.URL)
})

#在请求主体(body)返回后调用
c.OnResponse(func(r *colly.Response) {
    fmt.Println("Visited", r.Request.URL)
})

#在请求主体返回后,并且主体内容为HTML时立即调用
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)
})

#当请求主体返回后,并且请求内容为HTML或者XML时立即调用,该函数优先级应小于OnHTML()(不过并未经过测试,仅推测)
c.OnXML("//h1", func(e *colly.XMLElement) {
    fmt.Println(e.Text)
})

#当以上函数执行结束后执行该函数
c.OnScraped(func(r *colly.Response) {
    fmt.Println("Finished", r.Request.URL)
})

上面可以看出来,方法的调用优先级应该是从上到下

回调函数配置完成后,使用Visit()方法开始进行爬取,

#指定要爬取的URL
c.Visit("http://go-colly.org/")

以下是一个简单示例,会爬取http://go-colly.org/中的<a>标签并且打印它的元素值(text)和href属性的值,同时会对爬取出的链接依次进行深度优先遍历爬取!

package main

import (
    "fmt"

    "github.com/gocolly/colly"
)

func main() {
    c := colly.NewCollector()
    // 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)
    })
    c.Visit("http://go-colly.org/")
}

自定义配置

可在Selector对象创建时对其进行相关的自定义初始化操作,官方示例:

c2 := colly.NewCollector(
    colly.UserAgent("xy"),
    colly.AllowURLRevisit(),
)

该配置改变了用户代理即UA以及设置可以重新访问

不仅仅可以在对象创建时进行初始化操作,也可以在创建后进行覆写(修改)操作,官方示例:

c2 := colly.NewCollector()
c2.UserAgent = "xy"
c2.AllowURLRevisit = true

还可以通过环境变量的配置进行初始化时自动修改:

  • COLLY_ALLOWED_DOMAINS (逗号分割的域列表)
  • COLLY_CACHE_DIR (string)
  • COLLY_DETECT_CHARSET (y/n)
  • COLLY_DISABLE_COOKIES (y/n)
  • COLLY_DISALLOWED_DOMAINS (逗号分割的域列表)
  • COLLY_IGNORE_ROBOTSTXT (y/n)
  • COLLY_FOLLOW_REDIRECTS (y/n)
  • COLLY_MAX_BODY_SIZE (int)
  • COLLY_MAX_DEPTH (0代表无限)
  • COLLY_PARSE_HTTP_ERROR_RESPONSE (y/n)
  • COLLY_USER_AGENT (string)

网络配置

colly使用的go默认的http作为网络层,可以通过更改默认的 HTTP roundtripper来对HTTP进行相关配置,官方示例:

c := colly.NewCollector()
c.WithTransport(&http.Transport{
    Proxy: http.ProxyFromEnvironment,
    DialContext: (&net.Dialer{
        Timeout:   30 * time.Second,
        KeepAlive: 30 * time.Second,
        DualStack: true,
    }).DialContext,
    MaxIdleConns:          100,
    IdleConnTimeout:       90 * time.Second,
    TLSHandshakeTimeout:   10 * time.Second,
    ExpectContinueTimeout: 1 * time.Second,
}

影翼

文章作者

发表回复

textsms
account_circle
email

jinzh notes

go爬虫学习(一)
前言 目前需求是想用go写出来一个可以直接爬取网站上的代理ip的爬虫出来,采取的架构为:后端go实现,前端由vue实现,go爬取到的ip使用sqlite数据库存储! 先实现后端的爬取ip代理网站的…
扫描二维码继续阅读
2022-01-01