這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
Pholcus
Pholcus(幽靈蛛)是一款純Go語言編寫的支援分布式的高並發、重量級爬蟲軟體,定位於互連網資料擷取,為具備一定Go或JS編程基礎的人提供一個只需關注規則定製的功能強大的爬蟲工具。
它支援單機、服務端、用戶端三種運行模式,擁有Web、GUI、命令列三種操作介面;規則簡單靈活、批量任務並發、輸出方式豐富(mysql/mongodb/csv/excel等)、有大量Demo共用;另外它還支援橫縱向兩種抓模數式,支援類比登入和任務暫停、取消等一系列進階功能。
爬蟲原理
架構特點
-
為具備一定Go或JS編程基礎的使用者提供只需關注規則定製、功能完備的重量級爬蟲工具;
-
支援單機、服務端、用戶端三種運行模式;
-
GUI(Windows)、Web、Cmd 三種操作介面,可通過參數控制開啟檔案;
-
支援狀態控制,如暫停、恢複、停止等;
-
可控制採集量;
-
可控制並發協程數;
-
支援多採集任務並發執行;
-
支援代理IP列表,可控制更換頻率;
-
支援採集過程隨機停歇,類比人工行為;
-
根據規則需求,提供自訂配置輸入介面
-
有mysql、mongodb、csv、excel、原檔案下載共五種輸出方式;
-
支援分批輸出,且每批數量可控;
-
支援靜態Go和動態JS兩種採集規則,支援橫縱向兩種抓模數式,且有大量Demo;
-
持久化成功記錄,便於自動去重;
-
序列化失敗請求,支援還原序列化自動重載處理;
-
採用surfer高並發下載器,支援 GET/POST/HEAD 方法及 http/https 協議,同時支援固定UserAgent自動儲存cookie與隨機大量UserAgent禁用cookie兩種模式,高度類比瀏覽器行為,可實現類比登入等功能;
-
伺服器/用戶端模式採用Teleport高並發SocketAPI架構,全雙工系統長串連通訊,內部資料轉送格式為JSON。
下載安裝
-
下載第三方依賴包源碼,放至 GOPATH/src 目錄下 [點擊下載 ZIP]
-
下載更新源碼,命令列如下
go get -u -v github.com/henrylee2cn/pholcus
備忘:Pholcus公開維護的spider規則庫地址 https://github.com/pholcus/spider_lib
建立項目
package mainimport ( "github.com/henrylee2cn/pholcus/exec" _ "github.com/pholcus/spider_lib" // 此為公開維護的spider規則庫 // _ "spider_lib_pte" // 同樣你也可以自由添加自己的規則庫)func main() { // 設定運行時預設操作介面,並開始運行 // 運行軟體前,可設定 -a_ui 參數為"web"、"gui"或"cmd",指定本次啟動並執行操作介面 // 其中"gui"僅支援Windows系統 exec.DefaultRun("web")}
編譯運行
正常編譯方法
cd {{replace your gopath}}/src/github.com/henrylee2cn/pholcusgo install 或者 go build
Windows下隱藏cmd視窗的編譯方法
cd {{replace your gopath}}/src/github.com/henrylee2cn/pholcusgo install -ldflags="-H windowsgui" 或者 go build -ldflags="-H windowsgui"
查看選擇性參數:
pholcus -h
Web版操作介面如下:
GUI版操作介面之模式選擇介面如下
Cmd版運行參數設定樣本如下
$ pholcus -_ui=cmd -a_mode=0 -c_spider=3,8 -a_outtype=csv -a_thread=20 -a_dockercap=5000 -a_pause=300-a_proxyminute=0 -a_keyins="<pholcus><golang>" -a_limit=10 -a_success=true -a_failure=true
運行時目錄檔案
├─pholcus 軟體│├─pholcus_pkg 運行時檔案目錄│ ├─config.ini 設定檔│ ││ ├─proxy.lib 代理IP列表檔案│ ││ ├─spiders 動態規則目錄│ │ └─xxx.pholcus.html 動態規則檔案│ ││ ├─phantomjs 程式檔案│ ││ ├─text_out 文本資料檔案輸出目錄│ ││ ├─file_out 檔案結果輸出目錄│ ││ ├─logs 日誌目錄│ ││ ├─history 記錄目錄│ │└─└─cache 臨時緩衝目錄
動態規則樣本
特點:動態載入規則,無需重新編譯軟體,書寫簡單,添加自由,適用於輕量級的採集項目。
xxx.pholcus.html
<Spider> <Name>HTML動態規則樣本</Name> <DeScription>HTML動態規則樣本 [Auto Page] [http://xxx.xxx.xxx]</DeScription> <Pausetime>300</Pausetime> <EnableLimit>false</EnableLimit> <EnableCookie>true</EnableCookie> <EnableKeyin>false</EnableKeyin> <NotDefaultField>false</NotDefaultField> <Namespace> <Script></Script> </Namespace> <SubNamespace> <Script></Script> </SubNamespace> <Root> <Script param="ctx"> console.log("Root"); ctx.JsAddQueue({ Url: "http://xxx.xxx.xxx", Rule: "登入頁" }); </Script> </Root> <Rule name="登入頁"> <AidFunc> <Script param="ctx,aid"> </Script> </AidFunc> <ParseFunc> <Script param="ctx"> console.log(ctx.GetRuleName()); ctx.JsAddQueue({ Url: "http://xxx.xxx.xxx", Rule: "登入後", Method: "POST", PostData: "username=44444444@qq.com&password=44444444&login_btn=login_btn&submit=login_btn" }); </Script> </ParseFunc> </Rule> <Rule name="登入後"> <ParseFunc> <Script param="ctx"> console.log(ctx.GetRuleName()); ctx.Output({ "全部": ctx.GetText() }); ctx.JsAddQueue({ Url: "http://accounts.xxx.xxx/member", Rule: "個人中心", Header: { "Referer": [ctx.GetUrl()] } }); </Script> </ParseFunc> </Rule> <Rule name="個人中心"> <ParseFunc> <Script param="ctx"> console.log("個人中心: " + ctx.GetRuleName()); ctx.Output({ "全部": ctx.GetText() }); </Script> </ParseFunc> </Rule></Spider>
靜態規則樣本
特點:隨軟體一同編譯,定製性更強,效率更高,適用於重量級的採集項目。
xxx.go
func init() { Spider{ Name: "靜態規則樣本", Description: "靜態規則樣本 [Auto Page] [http://xxx.xxx.xxx]", // Pausetime: 300, // Limit: LIMIT, // Keyin: KEYIN, EnableCookie: true, NotDefaultField: false, Namespace: nil, SubNamespace: nil, RuleTree: &RuleTree{ Root: func(ctx *Context) { ctx.AddQueue(&request.Request{Url: "http://xxx.xxx.xxx", Rule: "登入頁"}) }, Trunk: map[string]*Rule{ "登入頁": { ParseFunc: func(ctx *Context) { ctx.AddQueue(&request.Request{ Url: "http://xxx.xxx.xxx", Rule: "登入後", Method: "POST", PostData: "username=123456@qq.com&password=123456&login_btn=login_btn&submit=login_btn", }) }, }, "登入後": { ParseFunc: func(ctx *Context) { ctx.Output(map[string]interface{}{ "全部": ctx.GetText(), }) ctx.AddQueue(&request.Request{ Url: "http://accounts.xxx.xxx/member", Rule: "個人中心", Header: http.Header{"Referer": []string{ctx.GetUrl()}}, }) }, }, "個人中心": { ParseFunc: func(ctx *Context) { ctx.Output(map[string]interface{}{ "全部": ctx.GetText(), }) }, }, }, }, }.Register()}
FAQ
請求隊列中,重複的URL是否會自動去重?
url預設情況下是去重的,但是可以通過設定Request.Reloadable=true忽略重複。
URL指向的頁面內容若有更新,架構是否有判斷的機制?
url頁面內容的更新,架構無法直接支援判斷,但是使用者可以自己在規則中自訂支援。
請求成功是依據web頭的狀態代碼判斷?
不是判斷狀態,而是判斷伺服器有無響應流返回。即,404頁面同樣屬於成功。
請求失敗後的重新請求機制?
每個url嘗試下載指定次數之後,若依然失敗,則將該請求追加到一個類似defer性質的特殊隊列中。 在當前任務正常結束後,將自動添加至下載隊列,再次進行下載。如果依然有沒下載成功的,則儲存至失敗記錄。 當下次執行該條爬蟲規則時,可通過選擇繼承曆史失敗記錄,把這些失敗請求自動加入defer性質的特殊隊列……(後面是重複步驟)
貢獻者名單
貢獻者 |
貢獻內容 |
henrylee2cn |
軟體作者 |
kas |
surfer下載器中phantomjs核心 |
wang898jian |
參與完全手冊編寫 |
第三方依賴包
go get github.com/pholcus/spider_libgo get github.com/henrylee2cn/teleportgo get github.com/PuerkitoBio/goquerygo get github.com/robertkrimen/ottogo get github.com/andybalholm/cascadiago get github.com/lxn/walkgo get github.com/lxn/wingo get github.com/go-sql-driver/mysqlgo get github.com/jteeuwen/go-bindata/...go get github.com/elazarl/go-bindata-assetfs/...go get gopkg.in/mgo.v2<以下需翻牆下載>go get golang.org/x/net/htmlgo get golang.org/x/text/encodinggo get golang.org/x/text/transform
(在此感謝以上開源項目的支援!)