欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go語言colly框架的快速入門

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

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

這樣就行了么?運行下試試,沒有任何輸出。

$ go run main.go

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

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

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)的順序如下圖,每個回調(diào)可以設(shè)置多次,會依次執(zhí)行

常規(guī)配置

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

colly 采集器的配置

新建 colly 采集器時指定配置,例如

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)該也能猜到每個環(huán)境變量都有什么作用

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

  • 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_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 采集器的屬性進行配置

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)先級就是上面介紹的順序:新建 < 環(huán)境變量 < 實例屬性

HTTP 的配置

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

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

常見功能

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

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

colly 會記錄已經(jīng)爬取過的鏈接,不會再重復(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 默認是串行逐個鏈接進行爬取,想要提高爬取能力最快速簡單的方式就是開啟并行。

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

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

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()
}

持久化的外部存儲

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

當(dāng)我們構(gòu)建一個分布式爬蟲時,我們需要一個公共的用于維護狀態(tài)的持久化存儲,例如 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)
	}
  // 清除之前存儲的信息,可選
	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")
}

隊列

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

import (
	"fmt"
	"github.com/gocolly/colly/v2"
	"github.com/gocolly/colly/v2/queue"
)
func main() {
	q, _ := queue.New(
		2, // 消費的進程數(shù)
		&queue.InMemoryQueueStorage{MaxSize: 10000}, // 默認的隊列,內(nèi)存隊列
	)
	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)
}

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

package main
import (
	"fmt"
	"github.com/gocolly/colly/v2"
	"github.com/gocolly/colly/v2/queue"
	"github.com/gocolly/redisstorage"
)
func main() {
	// 創(chuàng)建redis存儲
	storage := &redisstorage.Storage{
		Address:  "127.0.0.1:6379",
		Password: "",
		DB:       0,
		Prefix:   "httpbin_test",
	}
	q, err := queue.New(
		2, // 消費的進程數(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é)

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

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

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

相關(guān)文章

  • golang利用redis和gin實現(xiàn)保存登錄狀態(tài)校驗登錄功能

    golang利用redis和gin實現(xiàn)保存登錄狀態(tài)校驗登錄功能

    這篇文章主要介紹了golang利用redis和gin實現(xiàn)保存登錄狀態(tài)校驗登錄功能,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2024-01-01
  • Go?interface{}?轉(zhuǎn)切片類型的實現(xiàn)方法

    Go?interface{}?轉(zhuǎn)切片類型的實現(xiàn)方法

    本文主要介紹了Go?interface{}?轉(zhuǎn)切片類型的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • Go?數(shù)據(jù)結(jié)構(gòu)之二叉樹詳情

    Go?數(shù)據(jù)結(jié)構(gòu)之二叉樹詳情

    這篇文章主要介紹了?Go?數(shù)據(jù)結(jié)構(gòu)之二叉樹詳情,二叉樹是一種數(shù)據(jù)結(jié)構(gòu),在每個節(jié)點下面最多存在兩個其他節(jié)點。即一個節(jié)點要么連接至一個、兩個節(jié)點或不連接其他節(jié)點,下文基于GO語言展開二叉樹結(jié)構(gòu)詳情,需要的朋友可以參考一下
    2022-05-05
  • Go語言官方依賴注入工具Wire的使用教程

    Go語言官方依賴注入工具Wire的使用教程

    依賴注入是一種實現(xiàn)控制反轉(zhuǎn)且用于解決依賴性問題的設(shè)計模式。Golang?中常用的依賴注入工具主要有?Inject?、Dig?等。但是今天主要介紹的是?Go?團隊開發(fā)的?Wire,一個編譯期實現(xiàn)依賴注入的工具,感興趣的可以了解一下
    2022-09-09
  • go語言base64加密解密的方法

    go語言base64加密解密的方法

    這篇文章主要介紹了go語言base64加密解密的方法,實例分析了Go語言base64加密解密的技巧,需要的朋友可以參考下
    2015-03-03
  • Golang常用環(huán)境變量說明與設(shè)置詳解

    Golang常用環(huán)境變量說明與設(shè)置詳解

    這篇文章主要介紹了Golang常用環(huán)境變量說明與設(shè)置,需要的朋友可以參考下
    2020-02-02
  • Go如何實現(xiàn)HTTP請求限流示例

    Go如何實現(xiàn)HTTP請求限流示例

    本篇文章主要介紹了Go如何實現(xiàn)HTTP請求限流示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04
  • 一文帶你感受Go語言空結(jié)構(gòu)體的魔力

    一文帶你感受Go語言空結(jié)構(gòu)體的魔力

    在?Go?語言中,有一種特殊的用法可能讓許多人感到困惑,那就是空結(jié)構(gòu)體,本文將對Go空結(jié)構(gòu)體進行詳解,準(zhǔn)備一杯你最喜歡的飲料或茶,隨著本文一探究竟吧
    2023-05-05
  • Golang報“import cycle not allowed”錯誤的2種解決方法

    Golang報“import cycle not allowed”錯誤的2種解決方法

    這篇文章主要給大家介紹了關(guān)于Golang報"import cycle not allowed"錯誤的2種解決方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以們下面隨著小編來一起看看吧
    2018-08-08
  • Go語言實現(xiàn)JSON解析的方法詳解

    Go語言實現(xiàn)JSON解析的方法詳解

    在日常項目中,使用Json格式進行數(shù)據(jù)封裝是比較常見的操作。本文將詳細講解如何利用Go語言實現(xiàn)JSON的解析,感興趣的小伙伴可以學(xué)習(xí)一下
    2022-04-04

最新評論