強大高效而精簡易用的Golang爬蟲框架Colly,能否取代 Scrapy?
前言

任何剛接觸爬蟲編程的朋友可能都熟悉或者或多或少了解過基于 Python 異步框架 Twisted 的爬蟲框架 Scrapy。Scrapy 發展了將近 7 年,是爬蟲框架中的開山鼻祖,自然而然成為最受歡迎的也是應用最廣的爬蟲框架。對于 Scrapy 來說,其天然的優勢是支持并發,而且集成了 HTTP 請求、下載、解析、調度等爬蟲程序中常見的功能模塊,讓爬蟲工程師只專注于頁面解析和制定抓取規則,在當時極大的簡化了爬蟲開發流程,提高了開發效率。
但是,Scrapy 并不是完美的,它仍然有不少缺點。其中,它的模版定制化成為了制約 Scrapy 爬蟲項目的雙刃劍:一方面,Scrapy 抽象出了各種必要的模塊,包括爬蟲(Spider)、抓取結果(Item)、中間件(Middleware)、管道(Pipeline)、設置(Setting)等,讓用戶可以直接上手按照一定規則編寫自己想要開發的爬蟲程序;另一方面,這些高度抽象的模塊讓整個爬蟲項目顯得比較臃腫,每個爬蟲項目都需要按照相應的模版生成好幾個文件,導致配置、爬蟲等管理起來相對比較混亂。而且,Scrapy 在一些特殊場景例如分布式抓取時顯得心有余而力不足,因此很多高級爬蟲工程師甚至需要更改 Scrapy 源碼來滿足業務要求。
下圖是 Colly 和 Scrapy 在 Github 的 Star 數對比。可以看到 Colly 發展較晚,star 數不到 Scrapy 的三分之一,但還在高速增長當中。本文將著重介紹這個年輕而強大的爬蟲框架: Colly。
靜態語言 Golang
Colly 是基于靜態語言 Golang 開發的。眾所周知,Golang 也是一個比較年輕的語言,僅有 13 年歷史(相較而言,Python 有將近 30 年歷史)。Golang 天然支持并發(Concurrency),要起一個協程(Coroutine),只需要在調用函數前加一個 go 關鍵詞即可,非常簡單。當然,Golang 還有其他很棒的特性,例如通道(chan)。不過對于爬蟲來說支持并發是非常重要的,因為一個高效的爬蟲需要盡可能多的占用網絡帶寬資源,Golang 的并發特性給編寫爬蟲框架來說帶來了優勢。反觀 Python,如果要實現并發的話需要做很多工作,包括利用 asyncio 庫和從 JavaScript ES7 借鑒過來的 async/await 語法,并不是很直觀。
下面是 Golang 的異步語法例子。
func?run()?{
fmt.Printf("hello?world")
}
func?main()?{
go?run()
}
下面是 Python 的異步語法例子。
import?asyncio
async?def?main():
print('Hello?...')
await?asyncio.sleep(1)
print('...?World!')
#?Python?3.7+
asyncio.run(main())
Golang 作為靜態語言還有另一個非常重要的優勢,也就是其代碼的可預測性(Predictability)。靜態語言要求變量、參數以及函數返回結果都指定相應的類型,并且在編譯的時候會檢查類型的正確性,保證代碼的可靠性。用靜態語言編寫的一個好處,就是可以讓自己避免很多因為類型錯誤導致的 bug。因此,對于可靠性和健壯性要求較高的大型項目來說,用靜態語言編寫會是比較合理的選擇。編寫 Golang 程序的時候,IDE 會根據類型或變量自動補全潛在的代碼,是不是很香。相反,以 Python 為代表的動態語言,就沒那么嚴格了。雖然 Python 是強類型語言,但它并不存在預編譯的過程,因此無法在編譯時(Compile)檢測出類型錯誤。很多時候如果類型傳入不對,都會在運行時(Runtime)導致錯誤。網上流傳的 “動態一時爽,重構火葬場”,說的也是這個道理。雖然動態語言(例如 Python)給抓取結果賦予了一定的靈活性,但在我看來,大型爬蟲項目用靜態語言(例如 Golang)會是個更合理的選擇。
Colly
之前也介紹了,Colly 是一個由 Golang 編寫的爬蟲框架。Colly 其實是 Collector 或 Collecting 的昵稱。它精簡易用而強大高效,正在逐漸成為 Scrapy 以外的爬蟲框架選擇。
咱們下面用一個例子來看一下它是如何做到的。(本文不是 Colly 的參考文檔,僅希望通過一些例子來介紹 Colly 的優勢和特性,要看所有 API 請參考 Colly 官網文檔)
在任意目錄創建 baidu_spider.go 文件,并輸入下列代碼。
package?main
import?(
"fmt"
"github.com/crawlab-team/crawlab-go-sdk/entity"
"github.com/gocolly/colly/v2"
)
func?main()?{
//?生成?colly?采集器
c?:=?colly.NewCollector(
colly.AllowedDomains("www.baidu.com"),
colly.Async(true),
colly.UserAgent("Mozilla/5.0?(Macintosh;?Intel?Mac?OS?X?10_14_6)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/84.0.4147.135?Safari/537.36"),
)
//?抓取結果數據鉤子函數
c.OnHTML(".result.c-container",?func(e?*colly.HTMLElement)?{
//?抓取結果實例
item?:=?entity.Item{
"title":?e.ChildText("h3.t?>?a"),
"url":???e.ChildAttr("h3.t?>?a",?"href"),
}
//?打印抓取結果
fmt.Println(item)
//?取消注釋調用?Crawlab?Go?SDK?存入數據庫
//_?=?crawlab.SaveItem(item)
})
//?分頁鉤子函數
c.OnHTML("a.n",?func(e?*colly.HTMLElement)?{
_?=?c.Visit("https://www.baidu.com"?+?e.Attr("href"))
})
//?訪問初始?URL
startUrl?:=?"https://www.baidu.com/s?wd=crawlab"
_?=?c.Visit(startUrl)
//?等待爬蟲結束
c.Wait()
}
上面這個爬蟲腳本,僅有 40 行代碼。如果要用 Scrapy 來完成同樣的功能,可能需要更多代碼和文件目錄。
可以從代碼中看到,Colly 的爬蟲程序編寫非常簡單,主要包含四個部分:
生成 Colly 采集器(Collector)c,并傳入一些配置信息;
OnHTML 鉤子函數,包含 colly.HTMLElement 元素實例,這里主要是處理抓取結果的邏輯;
c.Visit 訪問函數,類似 Scrapy 中的 yield scrapy.Request;
c.Wait 等待函數,等待 Colly 爬蟲程序執行完畢。
創建好之后,在所在目錄執行 go run baidu_spider.go,即可運行百度搜索 “crawlab” 關鍵詞爬蟲。運行結果類似如下。
...
map[title:docker安裝爬蟲管理工具crawlab?-?kindvampire?-?博客園?url:http://www.baidu.com/link?url=ueCY-MwzzGwaVqXw3Q18Fz8rEodI1P_mv60lRd8H0UZdFC4xVnVwWtsh-HpiwaOFI1zVjZFeVca]
map[title:crawlab?python腳本關聯mongodb結果集,實例_kai4024589..._CSDN博客?url:http://www.baidu.com/link?url=2wFQZaLoEk7OOTHrf1LOJcPiBAZEFETQYbjrqnrJi_Wfqdx-gPFIyjt2q3f7lTC-8A6SWz_l8zE6D8SBs1j0c4DOIwbdAw8i]
map[title:手把手教你如何用Crawlab構建技術文章聚合平臺(一)_wei..._CSDN博客?url:http://www.baidu.com/link?url=nr9NOz2dqYFuaU5E1Zjz0OIfeeixSADNBNcHwj4dw9zypIky-9dVxd4RdzdS8-JMP7_X-LYpo0ydWmB8VNBmqq]
map[title:tikazyq-crawlab-master?crawlab爬蟲平臺?適合scrapy分布式部署...?url:http://www.baidu.com/link?url=VibsGu0BinYAUR_96pWCmcELObAXIPn7rKprlc9HR_607_cuEbxlcShUHqXjOoV6dnc4pND5F0K]
map[title:手把手教你如何用Crawlab構建技術文章聚合平臺(一)?-?個人文章...?url:http://www.baidu.com/link?url=SG6dJcLc20xIuiesjRIXu2XzGSR0N674BEnUTveJhYe5mRc9SFtggk-NL0pmAAa]
map[title:爬蟲管理平臺Crawlab?v0.3.0發布(Golang版本)?-?個人文章...?url:http://www.baidu.com/link?url=TItw3zWB4jHCoGmoQMm01E7oP2WlwfX7BRMsA9WDhaxHeQZZDi3I8bZh_kgTfpNx4fhtf42_]
map[title:Crawlab?單節點服務集群搭建部署簡明教程?-?個人文章?-?Segment...?url:http://www.baidu.com/link?url=cuYEFA1zjqK1GiEmDCjwRMLDGFVKDsz6u4ljYjQol-VwDdr_cBS9Y3UlgChkyCuO7A_]
...
你可能會納悶,Pipeline 和 Middleware 等 Scrapy 中定義的模塊去哪里了?其實,你需要注意的是,這些模塊并不是必須的,只是大佬們在開發爬蟲過程中總結出來的一些實用的邏輯,抽象出來了而已。如果要在 Colly 中實現 Pipeline,直接在 c.OnHTML 鉤子函數中的回調函數中調用一下后續處理函數即可,例如下面代碼。
...
c.OnHTML(".result.c-container",?func(e?*colly.HTMLElement)?{
item?:=?entity.Item{
"title":?e.ChildText("h3.t?>?a"),
"url":???e.ChildAttr("h3.t?>?a",?"href"),
}
//?后續處理抓取結果
PostProcess(item)
})
...
從這個例子中,你可以看到 Colly 的 API 非常簡單、清爽,而正是這種簡單賦予了其極高的靈活性(Flexibility),讓開發者可以在框架內做很多復雜的事情。
當然,Colly 也是有缺點的。從目前的開發進度來看,Colly 似乎還無法支持動態渲染內容的抓取,例如 Ajax 數據渲染,而這個在 Scrapy 中是有現成的不少解決方案的。不過從最近的 Github 上的 Pull Request 來看,支持動態渲染內容應該會很快支持 chromedp 了,也就是支持調用 Chromium 來運行 JavaScript 內容。另外,Colly 似乎還缺少 Scrapy 中內置的日志系統和數據統計模塊,似乎有些過于輕量化。
不過,我們有理由相信,隨著今后不斷迭代,Colly 會變得越來越全面和強大的。
與 Crawlab 集成
Crawlab 是支持任何語言和框架的分布式爬蟲管理平臺,理論上能運行所有類型的爬蟲,包括 Colly 和 Scrapy。對 Crawlab 不了解的朋友可以查看 Crawlab 官網 以及 Github 首頁)。
首先利用 Crawlab CLI 將爬蟲文件上傳。
~/projects/tikazyq/colly-crawlers/baidu(master*)???crawlab?upload
go.mod
go.sum
baidu_spider.go
uploaded?successfully
然后在 Crawlab 的爬蟲詳情界面中輸入執行命令 go run baidu_spider.go,點擊 “運行” 開啟爬蟲。然后爬蟲就會開始運行。
等待一段時間,爬蟲運行結束。我們可以在日志中看到打印出來的結果。
并且,我們還可以在 “結果” 中查看抓取到的結果數據。這些結果是默認保存在 MongoDB 數據庫里的。
因此,用 Crawlab 來管理 Colly 爬蟲是非常方便的。
總結
本文從介紹知名爬蟲框架 Scrapy 的優缺點開始,引入了基于 Golang 的高效而簡單的爬蟲框架 Colly。然后我們用一個百度搜索引擎抓取的例子,闡述了 Colly 的優勢,也就是它精簡而清爽的 API 以及靜態語言的健壯性,還有很多其他實用特性。Colly 的出現,或許象征著爬蟲開發者對簡潔的追求,所謂 “大道至簡”,就是用簡單而純粹的東西創造巨大的價值。爬蟲技術的發展,是一個開發流程由復雜變簡單、而程序功能由簡單變復雜的過程。爬蟲技術經歷了 urllib/requests+BeautifulSoup 原始技術,到 Scrapy 的全能框架,再到如今的 Colly 的輕量級框架。而如今已經有不少所謂的 “低代碼” 甚至 “無代碼” 爬蟲平臺了,例如 Crawlab 可配置爬蟲、八爪魚/后羿采集器。而智能化的爬蟲抓取也在逐漸變得流行。從這個角度來看,Colly 相對于 Scrapy 應該是進步了。不過現在要說 Colly 能否取代 Scrapy 還為時過早,因為 Scrapy 還有很多優秀的特性和生態是 Colly 暫時無法替代的。但是,Colly 目前正在高速發展,逐漸被開發者所了解,隨著不斷的反饋迭代,Colly 非常有潛力成為另一個爬蟲界的必備技術。
參考
Colly Github: https://github.com/gocolly/colly
Colly 文檔: https://pkg.go.dev/github.com/gocolly/colly/v2?tab=doc
Crawlab Github: https://github.com/crawlab-team/crawlab
Crawlab 官網: https://crawlab.cn
Crawlab 演示: https://demo-pro.crawlab.cn
Go Python Scrapy
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。