go-colly 官方文檔翻譯

簡介(Introduction)

  • 如何安裝艾帐?
如何安裝
  1. Colly 只依賴于Go 語言溉瓶,你可以通過 安裝指南 安裝它
  2. 安裝Colly执俩,在終端輸入如下命令然后回車安裝Colly
go get -u github.com/gocolly/colly/...
  • 入門
入門
  1. 開始使用Colly之前確保你已經(jīng)安裝最新版本晓勇,更詳細(xì)內(nèi)容見安裝指南
  2. 讓我們從一些簡單的例子開始
  3. 首先你需要導(dǎo)入Colly到你的代碼中
import "github.com/gocolly/colly"
收集器

Colly 的主要實例是收集器對象呜魄,當(dāng)Colly 收集器任務(wù)運行時师倔,收集器負(fù)責(zé)網(wǎng)絡(luò)通訊和執(zhí)行附加的回調(diào)任務(wù)构韵。你必須初始化收集器

c := colly.NewCollector()
回調(diào)

你可以把不同類型的回調(diào)函數(shù)附加到收集器上來控制收集任務(wù),然后取回信息趋艘,你可以在包文檔中查看相關(guān)章節(jié)

添加回調(diào)到收集器中
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.OnResponse(func(r *colly.Response) {
    fmt.Println("Visited", r.Request.URL)
})

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

c.OnXML("http://h1", func(e *colly.XMLElement) {
    fmt.Println(e.Text)
})

c.OnScraped(func(r *colly.Response) {
    fmt.Println("Finished", r.Request.URL)
})

回調(diào)函數(shù)執(zhí)行順序

  1. OnRequest
    在請求之前調(diào)用
  2. OnError
    在請求中出現(xiàn)錯誤時調(diào)用
  3. OnResponse
    響應(yīng)接收到之后調(diào)用
  4. OnHTML
    OnResponse 正確執(zhí)行后疲恢,如果接收到的文本是HTML時執(zhí)行
  5. OnXML
    OnResponse 正確執(zhí)行后,如果接收到的文本是XML時執(zhí)行
  6. OnScraped
    OnXML 回調(diào)后調(diào)用
  • 配置
配置

Colly 是一個高度自定義的爬蟲框架瓷胧,它提供合理的默認(rèn)配置显拳,而且提供了大量的配置去改變它

收集器配置

全面的收集器屬性列表可以在這兒查看,推薦使用colly.NewCollector(options...)這種方法來初始化收集器
使用默認(rèn)配置創(chuàng)建一個收集器

c1 := colly.NewCollector()

創(chuàng)建另外一個收集器搓萧,改變User-Agent 和 Url Revisit

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

或者

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

通過重新設(shè)置收集器的屬性可以在收集任務(wù)運行任何節(jié)點改變配置杂数。
一個很好的例子是 User-Agent 切換器遇八,在每個請求上改變User-Agent

const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

func RandomString() string {
    b := make([]byte, rand.Intn(10)+10)
    for i := range b {
        b[i] = letterBytes[rand.Intn(len(letterBytes))]
    }
    return string(b)
}

c := colly.NewCollector()

c.OnRequest(func(r *colly.Request) {
    r.Headers.Set("User-Agent", RandomString())
})

通過環(huán)境變量配置
收集器的默認(rèn)配置可以通過環(huán)境變量來改變,它允許我們在不通過編譯的情況下對配置進(jìn)行微調(diào)
環(huán)境變量解析是在收集器初始化的最后一步執(zhí)行耍休,所以每個變量在初始化后的改變都可能被環(huán)境變量配置覆蓋刃永。
環(huán)境變量配置

  • ALLOWED_DOMAINS (多個域名用逗號分割)
  • CACHE_DIR (string)
  • DETECT_CHARSET (y/n)
  • DISABLE_COOKIES (y/n)
  • DISALLOWED_DOMAINS (多個域名用逗號分割)
  • IGNORE_ROBOTSTXT (y/n)
  • MAX_BODY_SIZE (int)
  • MAX_DEPTH (int - 0 沒有限制)
  • PARSE_HTTP_ERROR_RESPONSE (y/n)
  • USER_AGENT (string)
    HTTP 配置
    Colly 使用golang的 http client 作為網(wǎng)絡(luò)層微王,HTTP設(shè)置可以通過改變默認(rèn)的HTTP roundtripper來調(diào)整
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,
}

最佳實踐(Best Practices)

  • 調(diào)試
調(diào)試

有時候?qū)?code>log.Println()函數(shù)放到回調(diào)函數(shù)中就足夠了施蜜,但有時候卻不行。Colly有收集器調(diào)試的內(nèi)置功能江兢,調(diào)試器接口可以使用不同的調(diào)試器實現(xiàn)喧锦。

將調(diào)試器添加到收集器

從Colly的repo中添加基本的日志調(diào)試器debug

import (
    "github.com/gocolly/colly"
    "github.com/gocolly/colly/debug"
)

func main() {
    c := colly.NewCollector(colly.Debugger(&debug.LogDebugger{}))
    // [..]
}
實現(xiàn)一個自定義的調(diào)試器

你通過實現(xiàn)debug.Debugger類可以創(chuàng)建任何種類的調(diào)試器读规。一個好的例子是 LogDebugger

  • 分布式抓取

分布式爬蟲可以被不同方式實現(xiàn),取決于你的抓取任務(wù)是什么燃少。大多數(shù)情況下束亏,它足以擴(kuò)展網(wǎng)絡(luò)通信層,這可以使用代理和Colly的代理切換器輕松實現(xiàn)阵具。

代理選擇器

使用代理切換器仍然保持集中碍遍,而HTTP請求分布在多個代理之間。
Colly通過其SetProxyFunc()函數(shù)來切換代理阳液。任意自定義的函數(shù)可以通過SetProxyFunc()傳參怕敬,只要這個函數(shù)簽名為func(*http.Request) (*url.URL, error)

注意
通過使用 -D 可以將ssh 服務(wù)用到 sockets5代理上

Colly 有一個內(nèi)置的代理切換器,可以在每個請求上輪流切換代理列表
用法

package main

import (
    "github.com/gocolly/colly"
    "github.com/gocolly/colly/proxy"
)

func main() {
    c := colly.NewCollector()

    if p, err := proxy.RoundRobinProxySwitcher(
        "socks5://127.0.0.1:1337",
        "socks5://127.0.0.1:1338",
        "http://127.0.0.1:8080",
    ); err == nil {
        c.SetProxyFunc(p)
    }
    // ...
}

實現(xiàn)自定義的代理切換器:

var proxies []*url.URL = []*url.URL{
    &url.URL{Host: "127.0.0.1:8080"},
    &url.URL{Host: "127.0.0.1:8081"},
}

func randomProxySwitcher(_ *http.Request) (*url.URL, error) {
    return proxies[random.Intn(len(proxies))], nil
}

// ...
c.SetProxyFunc(randomProxySwitcher)
分布式爬蟲

管理獨立的和分布式的爬蟲最好的辦法是你可以將爬蟲包裝在服務(wù)器中帘皿。服務(wù)器可以是各種服務(wù)的比如HTTP东跪,TCP服務(wù)器和Google APP Engine。使用自定義的存儲實現(xiàn)集中和持久化的cookie來處理訪問的url

注意

Colly內(nèi)置支持Google APP Engine鹰溜。如果你需要從標(biāo)準(zhǔn)的APP Engine中使用Colly虽填,別忘了調(diào)用Collector.Appengine(*http.Request)
一個實現(xiàn)的例子可以從這兒查看

分布式存儲

默認(rèn)情況下曹动,訪問的url和cookie數(shù)據(jù)存儲在內(nèi)存中斋日,這對短生命周期抓取任務(wù)很簡單。但它對處理大規(guī)模和長時間爬取任務(wù)有很多限制仁期。
通過實現(xiàn)colly/storage.Storage
接口桑驱,Colly可以使用很多后端存儲來代替默認(rèn)的內(nèi)存存儲。查看existing storages.

  • 后端存儲
后端存儲

Colly可以通過內(nèi)存存儲cookie和訪問的url跛蛋,但它可以被任何實現(xiàn)了colly/storage.Storage的后端存儲覆蓋

現(xiàn)有的后端存儲
In-Memory Backend

Colly 默認(rèn)的后端存儲熬的,可以使用collector.SetStorage() 來覆蓋

Redis backend

詳細(xì)信息查閱redis example

SQLite3 backend
  • 使用多個收集器
使用多個收集器

如果一個爬蟲任務(wù)足夠復(fù)雜或者有各種各樣的子任務(wù),推薦使用多個收集器赊级。一個很好地例子coursera course scraper
使用了2個收集器押框,一個處理視圖頁面列表,另外一個處理課程詳情理逊。

注意

在調(diào)試中使用collector.ID來區(qū)分不同的收集器

克隆收集器

如果收集器中有非常相似的配置橡伞,你可以使用Clone() 方法來克隆收集器盒揉。Clone() 克隆收集器配置的副本,但不會添加回調(diào)函數(shù)兑徘。

c := colly.NewCollector(
    colly.UserAgent("myUserAgent"),
    colly.AllowedDomains("foo.com", "bar.com"),
)
// Custom User-Agent and allowed domains are cloned to c2
c2 := c.Clone()
在收集器之間傳遞自定義參數(shù)

使用收集器的Request() 方法可以在其他收集器中共享上下文
一個共享上下文的例子:

c.OnResponse(func(r *colly.Response) {
    r.Ctx.Put(r.Headers.Get("Custom-Header"))
    c2.Request("GET", "https://foo.com/", nil, r.Ctx, nil)
}
  • 爬蟲配置
爬蟲配置

Colly的默認(rèn)配置已經(jīng)經(jīng)過優(yōu)化刚盈,可以在一個任務(wù)重抓取數(shù)量較小的站點。如果你想抓取上百萬個站點挂脑,這樣的啟動不是最好的藕漱。這里有一些調(diào)整:

使用持久化的后端存儲

默認(rèn)情況下,Colly將cookie和訪問過的URL存儲在內(nèi)存中崭闲,你可以使用任意自定義的后端存儲來替換內(nèi)置的內(nèi)存存儲肋联。在這里查看更多詳情。

對于遞歸調(diào)用的長任務(wù)使用異步存儲

默認(rèn)情況下刁俭,Colly在請求未完成時會阻塞橄仍。所以,在回調(diào)函數(shù)中遞歸調(diào)用Collector.Visit會產(chǎn)生不斷增長的堆棧牍戚,使用Collector.Async = true 可以避免(不要忘記了與異步一起使用c.Wait()

禁用或限制連接保持活動狀態(tài)

Colly使用HTTP keep-alive提高爬取速度侮繁,它需要打開文件描述符,所以max-fd限制可以輕松達(dá)到長時間運行任務(wù)

使用如下代碼可以禁用HTTP keep-alive
c := colly.NewCollector()
c.WithTransport(&http.Transport{
    DisableKeepAlives: true,
})
  • 擴(kuò)展
擴(kuò)展

擴(kuò)展是Colly附帶的小型輔助工具翘魄,插件列表可以在此處獲得

用法

以下示例啟用隨機(jī)User-Agent切換器和Referrer setter擴(kuò)展鼎天,并訪問httpbin.org兩次

import (
    "log"

    "github.com/gocolly/colly"
    "github.com/gocolly/colly/extensions"
)

func main() {
    c := colly.NewCollector()
    visited := false

    extensions.RandomUserAgent(c)
    extensions.Referrer(c)

    c.OnResponse(func(r *colly.Response) {
        log.Println(string(r.Body))
        if !visited {
            visited = true
            r.Request.Visit("/get?q=2")
        }
    })

    c.Visit("http://httpbin.org/get")
}

案例(Examples)

后面文檔都只有代碼,詳情見官網(wǎng)文檔

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末暑竟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子育勺,更是在濱河造成了極大的恐慌但荤,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涧至,死亡現(xiàn)場離奇詭異腹躁,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)南蓬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進(jìn)店門纺非,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人赘方,你說我怎么就攤上這事烧颖。” “怎么了窄陡?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵炕淮,是天一觀的道長。 經(jīng)常有香客問我跳夭,道長涂圆,這世上最難降的妖魔是什么们镜? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮润歉,結(jié)果婚禮上模狭,老公的妹妹穿的比我還像新娘。我一直安慰自己踩衩,他們只是感情好嚼鹉,可當(dāng)我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著九妈,像睡著了一般反砌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上萌朱,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天宴树,我揣著相機(jī)與錄音,去河邊找鬼晶疼。 笑死酒贬,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的翠霍。 我是一名探鬼主播锭吨,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼寒匙!你這毒婦竟也來了零如?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤锄弱,失蹤者是張志新(化名)和其女友劉穎考蕾,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體会宪,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡肖卧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了掸鹅。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片塞帐。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖巍沙,靈堂內(nèi)的尸體忽然破棺而出葵姥,到底是詐尸還是另有隱情,我是刑警寧澤赎瞎,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布牌里,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏牡辽。R本人自食惡果不足惜喳篇,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望态辛。 院中可真熱鬧麸澜,春花似錦、人聲如沸奏黑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽熟史。三九已至馁害,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蹂匹,已是汗流浹背碘菜。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留限寞,地道東北人忍啸。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像履植,于是被迫代替她去往敵國和親计雌。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,658評論 2 350

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理玫霎,服務(wù)發(fā)現(xiàn)凿滤,斷路器,智...
    卡卡羅2017閱讀 134,637評論 18 139
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架庶近,建立于...
    Hsinwong閱讀 22,366評論 1 92
  • https://nodejs.org/api/documentation.html 工具模塊 Assert 測試 ...
    KeKeMars閱讀 6,313評論 0 6
  • 楔子 王者峽谷的迷霧 這座峽谷的天空永遠(yuǎn)都是血色的鸭巴,連下的雨的都是紅色的。這放肆的紅與這峽谷的殘酷景色很契合拦盹。這片...
    馳星周閱讀 487評論 2 3
  • 害怕那朝陽不會升起 害怕那夜空沒有星星 害怕明天的日子不會好轉(zhuǎn) 害怕前方的道路永遠(yuǎn)迷途 害怕,未來沒有你的陪伴溪椎。 ...
    楊耿耿閱讀 360評論 0 0