PySpider
沒有用過框架寫爬蟲赊堪,有人推薦了pyspider,我也沒有和別的框架比對,就直接上手先用了负溪。
使用感受
框架的封裝性帶來的優(yōu)缺點在這里顯示的淋漓精致...
優(yōu)點
- 爬蟲該有的都有了——網站入口逃沿;分頁查詢婴渡;解析網頁幻锁;保存數(shù)據(還可以發(fā)消息);
- 爬取時間間隔設置边臼;
- 網頁有效期維護哄尔;
- 爬取多線程設置;
- 對無頭瀏覽器phantomjs的支持柠并;
- 支持web ui上調試代碼岭接,需求不高的情況下類似在線編寫代碼;
- 提供了一鍵式獲取css selector按鈕臼予,方便獲取元素鸣戴。
缺點
- 本身不支持xpath方式解析;
- 使用回調方式來運行pipline粘拾,框架把控回調的執(zhí)行窄锅,不夠靈活,多層爬取時需要遞歸方式調用index_page缰雇,導致代碼可能比較混亂入偷;
- 提供的css selector提取器實用性一般,有一些復雜一點的拿不到械哟;
- 任務運行/關閉很多時候令人迷惑疏之;
- 對phantomjs的調用會對電腦cpu造成較大壓力,據說是每次爬取都會啟停一個phantomjs線程暇咆;
- web ui沒有刪除任務的選項体捏,也沒有清空爬取到的數(shù)據的選項;
- web ui的方式編碼很費勁糯崎,我都是在IDE里面寫好再復制上去几缭;
- web ui不能像本地IDE一樣識別新加入的包。
版本:
pyspider v0.3.10
python 3.6.5
安裝啟動
參考官方Quick start可以很快上手: http://docs.pyspider.org/en/latest/Quickstart/
# 一鍵安裝pyspider
pip install pyspider
# 會在當前目錄下建立data文件夾沃呢,保存任務相關代碼年栓,數(shù)據,任務進度等薄霜,如果換了路徑啟動就找不到了
# 啟動所有pyspider的組件某抓,更多命令可以 pyspider help
pyspider all
之后可以在 http://localhost:5000/ 看到啟動了一個web ui,用來調試和運行pyspider的
框架機制補充
爬取
on_start并非只是個入口惰瓜,pyspider之后要爬取url不會超過on_start執(zhí)行的url的子集
換言之否副,不能爬取on_start的url的父路徑。
多層次路徑爬取
- on_start只會執(zhí)行一次崎坊,如果on_start中有循環(huán)調用crawl方法备禀,則只會執(zhí)行最后一條
- index_page可以遞歸調用自身,可以使用這個特性來爬取多層路徑
phantomjs
- phantomjs 將其
{phantomjs_home/bin}
添加到環(huán)境變量path中即可,重啟pyspider即可曲尸,注意要環(huán)境變量生效pyspider才能找到phantomjs赋续。 - 瀏覽器中能獲取到的dom,pyspider獲取不到另患,可能是需要設置phantomjs的調用
一些小特性
這里不一一羅列API了纽乱,主要講我使用過程中碰到的一些特性
from pyspider.libs.base_handler import *
# pyspider的實現(xiàn)類需要繼承BaseHandler,實現(xiàn)基本的幾個接口
class Handler(BaseHandler):
# 放一些self.crawl函數(shù)請求頁面時的http請求頭:referer昆箕,user-agent等
crawl_config = {
}
# pipline的起點鸦列,這里請求的url最好是下文請求的父級url,否則爬取不了鹏倘,我出過這樣的問題薯嗤,不知道是不是就是這樣的機制
# 只會執(zhí)行一次,即如果on_start中有循環(huán)self.crawl第股,只會執(zhí)行最后一次
@every(minutes=24 * 60) # 任務運行之間的間隔应民,用來不停的補采過期的數(shù)據
def on_start(self):
# 爬取網頁的核心函數(shù),支持phantomjs解析夕吻,需配置fetch_type='js'
self.crawl('http://scrapy.org/', callback=self.index_page)
# 理論上是爬取分頁的诲锹,但是如果有多層爬取也得靠index_page,需要在self.crawl中設置callback為index_page涉馅,形成遞歸归园,當然如果邏輯不通,用if-else分開即可稚矿,如果有人發(fā)現(xiàn)了更好的多層爬取的方式庸诱,拜托告訴我一聲...
@config(age=10 * 24 * 60 * 60) # 爬取結果的有效期
def index_page(self, response):
# response.doc得到一個pyquery對象,和操作一個jquery對象相似晤揣,相關api看pyquery官網即可
for each in response.doc('a[href^="http"]').items():
self.crawl(each.attr.href, callback=self.detail_page)
# 輸出解析結果桥爽,如果用默認的sqlite,只能return一個dict昧识,如果自己復寫了on_result钠四,就可以隨意返回了
@config(priority=2)
def detail_page(self, response):
return {
"url": response.url,
"title": response.doc('title').text(),
}
# 自定義結果處理方式
def on_result(self, result):
...
# 處理結果
...
# task結束時調用
def on_finished(self, response, task):
...
# 任務關閉時的操作,可以用來關數(shù)據庫連接之類
...
啟停任務
- 在 localhost:5000 的web ui上修改狀態(tài)即可
- running和debug狀態(tài)沒有區(qū)別
- rate/brust rate表示每秒爬取的網頁個數(shù)可以為小數(shù)跪楞,這樣可以放慢task調度缀去,brust理解為并發(fā)數(shù)
其他
- pyspider啟動后在當前目錄下生成data目錄,project相關的數(shù)據甸祭,換目錄啟動會找不到之前的數(shù)據
- pyspider自帶了sqlite缕碎,但是要保存到別的數(shù)據庫需要自己建連接,插入池户,關連接咏雌,相關的包自己導入后重啟pyspider即可
- project和task的信息在web-ui中不能修改凡怎,但是可以通過數(shù)據庫工具打開
data/{db_name}.db
的文件,刪除或者修改 - 可以通過web ui的result頁面的on_process項的內容做簡單的debug
- phantomjs的環(huán)境變量有一種可以立即生效的辦法处嫌,不贅述啦
- web ui中看似好的縮進可能是不合法的栅贴, 編輯器問題斟湃,復制出來格式化好了再粘貼回去