最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go語言colly框架的快速入門

 更新時(shí)間:2023年07月26日 10:38:34   作者:涼涼的知識(shí)庫  
Python?中非常知名的爬蟲框架有Scrapy,Go?中也有一些?star?數(shù)較高的爬蟲框架,colly就是其中的佼佼者,它?API?簡潔,性能優(yōu)良,開箱即用,今天就來快速學(xué)習(xí)一下吧

有些人可能認(rèn)為爬蟲框架和 http client 庫的功能一樣,用 http client 庫也可以寫爬蟲。當(dāng)然,無論用第三方的 http client 庫還是官方的http庫,都可以寫爬蟲。但術(shù)業(yè)有專攻,爬蟲框架專門為批量爬取設(shè)計(jì),往往擁有并發(fā)控制、隊(duì)列、緩存、HTML 解析等一系列開箱即用的 API,能大幅簡化在爬蟲實(shí)現(xiàn)過程中的負(fù)擔(dān)

Python 中非常知名的爬蟲框架有Scrapy,Go 中也有一些 star 數(shù)較高的爬蟲框架。colly就是其中的佼佼者,它 API 簡潔,性能優(yōu)良,開箱即用。今天就來快速學(xué)習(xí)一下吧!

基本使用

首先引入依賴

go get -u github.com/gocolly/colly/...

之后就可以使用colly,通過Visit函數(shù)來告知colly 采集器要訪問的 URL

package main
import (
	"fmt"
	"github.com/gocolly/colly/v2"
)
func main() {
	c := colly.NewCollector()
	c.Visit("http://go-colly.org/")
}

這樣就行了么?運(yùn)行下試試,沒有任何輸出。

$ go run main.go

原因在于代碼要求 colly 采集器訪問http://go-colly.org/,但沒有設(shè)定訪問 URL 成功或者失敗后要執(zhí)行的動(dòng)作。colly提供了一系列的回調(diào)函數(shù),用于 URL 訪問和響應(yīng)過程中各種情況的處理

例如,可以設(shè)定訪問 URL 前、響應(yīng)成功、響應(yīng)失敗時(shí)不同邏輯的處理

package main
import (
	"fmt"
	"github.com/gocolly/colly/v2"
)
func main() {
	c := colly.NewCollector()
	c.OnRequest(func(r *colly.Request) {
		fmt.Println("Visiting", r.URL)
	})
	c.OnResponse(func(r *colly.Response) {
		fmt.Println("Visited", r.Request.URL)
	})
	c.OnError(func(_ *colly.Response, err error) {
		fmt.Println("Something went wrong:", err)
	})
	c.Visit("http://go-colly.org/")
}

colly提供的回調(diào)和回調(diào)的順序如下圖,每個(gè)回調(diào)可以設(shè)置多次,會(huì)依次執(zhí)行

常規(guī)配置

配置分兩部分,一部分是 colly 采集器的配置,一部分是 HTTP 的配置

colly 采集器的配置

新建 colly 采集器時(shí)指定配置,例如

c := colly.NewCollector(
	colly.UserAgent("example.com"),
	colly.DisallowedDomains("baidu.com", "bing.com"),
)
//...
c.Visit("http://baidu.com/")
c.Visit("http://go-colly.org/")

使用環(huán)境變量可以不用重新編譯代碼。看名字大家應(yīng)該也能猜到每個(gè)環(huán)境變量都有什么作用

注意環(huán)境變量有固定前綴COLLY_,官方文檔里并沒有說明(坑!)

  • COLLY_ALLOWED_DOMAINS (逗號(hào)分隔)
  • COLLY_CACHE_DIR (string)
  • COLLY_DETECT_CHARSET (y/n)
  • COLLY_DISABLE_COOKIES (y/n)
  • COLLY_DISALLOWED_DOMAINS (逗號(hào)分隔)
  • COLLY_IGNORE_ROBOTSTXT (y/n)
  • COLLY_MAX_BODY_SIZE (int)
  • COLLY_MAX_DEPTH (0 代表不限深度)
  • COLLY_PARSE_HTTP_ERROR_RESPONSE (y/n)
  • COLLY_USER_AGENT (string)

$ COLLY_DISALLOWED_DOMAINS=baidu.com,bing.com go run main.go
Visiting http://go-colly.org/
Visited http://go-colly.org/
Finished http://go-colly.org/

通過 colly 采集器的屬性進(jìn)行配置

c := colly.NewCollector()
c.UserAgent = "example.com"
//...
c.Visit("http://go-colly.org/")
c.DisallowedDomains = []string{"baidu.com", "bing.com"}
c.Visit("http://baidu.com/")

colly 采集器的配置優(yōu)先級(jí)就是上面介紹的順序:新建 < 環(huán)境變量 < 實(shí)例屬性

HTTP 的配置

colly 默認(rèn)使用的是 Go 標(biāo)準(zhǔn)庫中的 http client,我們可以進(jìn)行替換

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,
}

常見功能

作為一個(gè)爬蟲,很少會(huì)僅抓取一個(gè)鏈接,通常會(huì)抓取大量的鏈接,甚至?xí)粩喾治霎?dāng)前頁面中的鏈接,繼續(xù)進(jìn)行深度的爬取。代碼通常會(huì)類似下面

為了避免無限制的爬取,可以限制爬取的域名范圍,和訪問深度;

colly 會(huì)記錄已經(jīng)爬取過的鏈接,不會(huì)再重復(fù)爬取

func main() {
	c := colly.NewCollector(
		colly.AllowedDomains("httpbin.org"),
		colly.MaxDepth(2),
	)
	c.OnHTML("a[href]", func(e *colly.HTMLElement) {
		link := e.Attr("href")
		fmt.Printf("Link found: %q -> %s\n", e.Text, link)
		c.Visit(link)
	})
	c.OnError(func(_ *colly.Response, err error) {
		fmt.Println("Something went wrong:", err)
	})
	c.Visit("http://httpbin.org/links/20/3")
}

并行抓取

colly 默認(rèn)是串行逐個(gè)鏈接進(jìn)行爬取,想要提高爬取能力最快速簡單的方式就是開啟并行。

除了需要設(shè)置colly.Async(true)之外,還需要在最后c.Wait()等待所有并發(fā)的請(qǐng)求執(zhí)行完成

c.Limit可以針對(duì)某一個(gè)域名設(shè)置并發(fā)度和發(fā)起每一個(gè)請(qǐng)求的延遲時(shí)間

func main() {
	c := colly.NewCollector(
		colly.AllowedDomains("httpbin.org"),
		colly.MaxDepth(2),
		colly.Async(true),
	)
	c.OnHTML("a[href]", func(e *colly.HTMLElement) {
		link := e.Attr("href")
		fmt.Printf("Link found: %q -> %s\n", e.Text, link)
		c.Visit(link)
	})
  c.Limit(&colly.LimitRule{
		DomainGlob:  "*httpbin.*",
		Parallelism: 2,
		Delay:      5 * time.Second,
	})
	c.Visit("http://httpbin.org/links/20/3")
	c.Wait()
}

持久化的外部存儲(chǔ)

默認(rèn)情況下已訪問的 URL 和 cookie 等信息都是存儲(chǔ)在內(nèi)存中,服務(wù)重新啟動(dòng)后將會(huì)丟失這部分信息,且無法在多個(gè)機(jī)器直接共享。

當(dāng)我們構(gòu)建一個(gè)分布式爬蟲時(shí),我們需要一個(gè)公共的用于維護(hù)狀態(tài)的持久化存儲(chǔ),例如 redis 等。

package main
import (
	"fmt"
	"github.com/gocolly/colly/v2"
	"github.com/gocolly/redisstorage"
)
func main() {
	c := colly.NewCollector(
		colly.AllowedDomains("httpbin.org", "go-colly.org"),
		colly.MaxDepth(2),
	)
	storage := &redisstorage.Storage{
		Address:  "127.0.0.1:6379",
		Password: "",
		DB:       0,
		Prefix:   "httpbin_test",
	}
	err := c.SetStorage(storage)
	if err != nil {
		panic(err)
	}
  // 清除之前存儲(chǔ)的信息,可選
	if err := storage.Clear(); err != nil {
		panic(err)
	}
	defer storage.Client.Close()
	c.OnHTML("a[href]", func(e *colly.HTMLElement) {
		link := e.Attr("href")
		fmt.Printf("Link found: %q -> %s\n", e.Text, link)
		c.Visit(link)
	})
  // ...
	c.Visit("http://httpbin.org/links/20/3")
}

隊(duì)列

可以使用隊(duì)列來控制爬取的速率,默認(rèn)情況下隊(duì)列也是在內(nèi)存中的

import (
	"fmt"
	"github.com/gocolly/colly/v2"
	"github.com/gocolly/colly/v2/queue"
)
func main() {
	q, _ := queue.New(
		2, // 消費(fèi)的進(jìn)程數(shù)
		&queue.InMemoryQueueStorage{MaxSize: 10000}, // 默認(rèn)的隊(duì)列,內(nèi)存隊(duì)列
	)
	c := colly.NewCollector(
		colly.AllowedDomains("httpbin.org", "go-colly.org"),
		colly.MaxDepth(2),
	)
	c.OnHTML("a[href]", func(e *colly.HTMLElement) {
		link := e.Attr("href")
		fmt.Printf("Link found: %q -> %s\n", e.Text, link)
		q.AddURL(link)
	})
	q.AddURL("http://go-colly.org/")
	q.Run(c)
}

對(duì)于構(gòu)建分布式爬蟲來說,可以借助外部的隊(duì)列提高整體的消費(fèi)能力。

package main
import (
	"fmt"
	"github.com/gocolly/colly/v2"
	"github.com/gocolly/colly/v2/queue"
	"github.com/gocolly/redisstorage"
)
func main() {
	// 創(chuàng)建redis存儲(chǔ)
	storage := &redisstorage.Storage{
		Address:  "127.0.0.1:6379",
		Password: "",
		DB:       0,
		Prefix:   "httpbin_test",
	}
	q, err := queue.New(
		2, // 消費(fèi)的進(jìn)程數(shù)
		storage,
	)
	if err != nil{
		panic(err)
	}
	c := colly.NewCollector(
		colly.AllowedDomains("httpbin.org", "go-colly.org"),
		colly.MaxDepth(2),
	)
  err = c.SetStorage(storage)
	if err != nil {
		panic(err)
	}
	c.OnHTML("a[href]", func(e *colly.HTMLElement) {
		link := e.Attr("href")
		fmt.Printf("Link found: %q -> %s\n", e.Text, link)
		q.AddURL(link)
	})
	q.AddURL("http://go-colly.org/")
	q.Run(c)
}

總結(jié)

這篇文章作為一個(gè)入門介紹,看完后你應(yīng)該能 Get 到普通的 http client 庫和爬蟲庫的區(qū)別了吧。

colly 作為一個(gè)爬蟲框架集成了一系列針對(duì)爬蟲的 API,想要體驗(yàn) colly 的更多能力,建議還是好好閱讀下 colly 的文檔

到此這篇關(guān)于Go語言colly框架的快速入門的文章就介紹到這了,更多相關(guān)Go colly框架內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語言學(xué)習(xí)之鏈表的使用詳解

    Go語言學(xué)習(xí)之鏈表的使用詳解

    鏈表是一種物理存儲(chǔ)單元上非連續(xù)、非順序的存儲(chǔ)結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序是通過鏈表中的指針鏈接次序?qū)崿F(xiàn)的。本文將詳細(xì)為大家介紹Go語言中鏈表的使用,感興趣的可以了解一下
    2022-04-04
  • Go庫text與template包使用示例詳解

    Go庫text與template包使用示例詳解

    這篇文章主要為大家介紹了Go庫text與template包使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Golang使用Decimal庫避免運(yùn)算中精度損失詳細(xì)步驟

    Golang使用Decimal庫避免運(yùn)算中精度損失詳細(xì)步驟

    decimal是為了解決Golang中浮點(diǎn)數(shù)計(jì)算時(shí)精度丟失問題而生的一個(gè)庫,使用decimal庫我們可以避免在go中使用浮點(diǎn)數(shù)出現(xiàn)精度丟失的問題,下面這篇文章主要給大家介紹了關(guān)于Golang使用Decimal庫避免運(yùn)算中精度損失的相關(guān)資料,需要的朋友可以參考下
    2023-06-06
  • Golang 命名規(guī)范推薦的實(shí)現(xiàn)示例

    Golang 命名規(guī)范推薦的實(shí)現(xiàn)示例

    本文主要介紹了Golang 推薦命名規(guī)范的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2026-04-04
  • Go?中?time.After?可能導(dǎo)致的內(nèi)存泄露問題解析

    Go?中?time.After?可能導(dǎo)致的內(nèi)存泄露問題解析

    這篇文章主要介紹了Go?中?time.After?可能導(dǎo)致的內(nèi)存泄露,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-05-05
  • Go語言中使用Swagger 生成 API 文檔及常見問題解決

    Go語言中使用Swagger 生成 API 文檔及常見問題解決

    Swagger 是一個(gè)規(guī)范和完整的框架,用于生成、描述、調(diào)用和可視化 RESTful風(fēng)格的Web服務(wù),本文就來詳細(xì)的介紹一下如何實(shí)現(xiàn)Go語言中使用Swagger 生成 API 文檔,感興趣的可以了解一下
    2026-01-01
  • Golang中對(duì)json的優(yōu)雅處理方式

    Golang中對(duì)json的優(yōu)雅處理方式

    這篇文章主要給大家介紹了關(guān)于Golang中對(duì)json的優(yōu)雅處理方式,解析JSON在golang中很麻煩,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-06-06
  • GO web 數(shù)據(jù)庫預(yù)處理的實(shí)現(xiàn)

    GO web 數(shù)據(jù)庫預(yù)處理的實(shí)現(xiàn)

    本文主要介紹了GO web 數(shù)據(jù)庫預(yù)處理的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • golang通過cgo調(diào)用C++庫源碼示例

    golang通過cgo調(diào)用C++庫源碼示例

    這篇文章主要給大家介紹了關(guān)于golang通過cgo調(diào)用C++庫的相關(guān)資料,CGO是GO語言里面的一個(gè)特性,CGO屬于GOLANG的高級(jí)用法,主要是通過使用GOLANG調(diào)用CLANG實(shí)現(xiàn)的程序庫,需要的朋友可以參考下
    2024-02-02
  • Go單元測(cè)試對(duì)數(shù)據(jù)庫CRUD進(jìn)行Mock測(cè)試

    Go單元測(cè)試對(duì)數(shù)據(jù)庫CRUD進(jìn)行Mock測(cè)試

    這篇文章主要為大家介紹了Go單元測(cè)試對(duì)數(shù)據(jù)庫CRUD進(jìn)行Mock測(cè)試的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06

最新評(píng)論

德惠市| 陇西县| 潮州市| 哈尔滨市| 宣武区| 南召县| 兴安县| 泽库县| 通州区| 镇沅| 任丘市| 甘南县| 赣榆县| 南平市| 南康市| 滕州市| 鲁甸县| 瓮安县| 柘城县| 德安县| 松江区| 武安市| 正宁县| 永平县| 蒲江县| 太湖县| 连南| 来宾市| 北流市| 海门市| 金平| 黔西县| 张家港市| 宝坻区| 荥经县| 宁津县| 关岭| 封丘县| 克拉玛依市| 天水市| 拉孜县|