1. 與scrapy的比較:
- pyspider提供 了 WebUI,爬蟲的編寫、除錯都是在 WebUI 中進行的 。 而 Scrapy原生是不具備這個功能的,它採用的是程式碼和命令列操作,但可以通過對接 Portia實現視覺化配置。
- pyspider除錯非常方便 , WebUI操作便捷直觀。 Scrapy則是使用 parse命令進行除錯, ;民:方便程度不及 p)叩ider。
- pyspider支援 PhantomJS來進行 JavaScript誼染頁面的採集 。 Scrapy可以對接 Scrapy-Splash元件,這需要額外配置 。
-
pyspider中內建了 pyquery作為選擇器。 Scrapy對接了 XPath、 css選擇器和正則匹配。
-
pyspider 的可擴充套件程度不足,可配製化程度不高 。 Scrapy 可以 通過對接 Middleware、 Pipeline、Extension等元件實現非常強大 的功能, 模組之間的稠合程度低,可擴充套件程度極高 。
2. pyspider的架構:
pyspider的架構主要分為 Scheduler (排程器)、 Fetcher (抓取器)、 Processer (處理器) 三個部分,整個爬取過程受到 Monitor (監控器)的監控,抓取的結果被 Result Worker (結果處理器)處理。
Scheduler 發起任務排程, Fetcher 負責抓取網頁內容, Processer 負責解析網頁內容,然後將新生成的 Request發給 Scheduler進行排程,將生成的提取結果輸出儲存。
- 每個 pyspider 的專案對應一個 Python j閱本,該指令碼中定義了一個 Handler 類,它有一個on_start()方法。 爬取首先呼叫 on_start()方法生成最初的抓取任務,然後傳送給 Scheduler進行排程 。
- Scheduler將抓取任務分發給 Fetcher進行抓取, Fetcher執行並得到響應,隨後將響應傳送給Processer。
- Processer 處理響應並提取 H-',新的 URL 生成新的抓取任務,然後通過訊息佇列的方式通知Schduler 當前抓取任務執行情況,並將新生成的抓取任務傳送給 Scheduler。 如果生成了新的提取結果,則將其傳送到結果佇列等待 ResultWorker處理。
- Scheduler 接收到新的抓取任務,然後查詢資料庫,判斷其如果是新的抓取任務或者是需要重試的任務就繼續進行排程,然後將其傳送回 Fetcher進行抓取。
- 不斷重複以上工作,直到所有的任務都執行完畢,抓取結束 。
- 抓取結束後,程式會回撥 on_finished()方法,這裡可以定義後處理過程。
3.使用
pyspider all
http:localhost:5000
當爬取網頁無法載入圖片時,可能是圖片是由JS渲染的
1 def index_page(self, response): 2 for each in response.doc('li > .tit > a').items(): 3 self.crawl(each.attr.href, 4 callback=self.detail_page, 5 fetch_type='js')#啟用PhantomJS渲染 6 next = response.doc('.next').attr.href 7 self.crawl(next,callback=self.index_page)
1 from pyspider.libs.base_handler import * 2 3 4 class Handler(BaseHandler): 5 crawl_config = { 6 } 7 8 @every(minutes=24 * 60) 9 def on_start(self): 10 self.crawl('http://travel.qunar.com/travelbook/list.htm', callback=self.index_page) 11 12 @config(age=10 * 24 * 60 * 60) 13 def index_page(self, response): 14 for each in response.doc('li > .tit > a').items(): 15 self.crawl(each.attr.href, 16 callback=self.detail_page, 17 fetch_type='js') 18 next = response.doc('.next').attr.href 19 self.crawl(next,callback=self.index_page) 20 21 @config(priority=2) 22 def detail_page(self, response): 23 return { 24 "url": response.url, 25 #"title": response.doc('title').text(), 26 "title": response.doc('#booktitle').text(), 27 "date": response.doc('.when .data').text(), 28 "day": response.doc('.howlong .data').text(), 29 "who": response.doc('.who .data').text(), 30 "text": response.doc('#b_panel_schedule').text(), 31 "image": response.doc('.cover_img').attr.src 32 }
rate/burst代表當前的爬取速率, rate代表 l 秒發IH多少個請求, burst相當於流量控制中的令牌桶演算法的令牌數, rate和 burst設定的越大,爬取速率越快,當然連率需要考慮本機效能和爬取過快被封的問題。 process中的 5m、 lh、 ld指的是最近 5分、l 小時 、 l 天內的請求’情況, all 代表所有的請求情況 。 請求由不同顏色表示,藍色的代表等待被執行的請求 ,綠色的代表成功的請求,黃色的代表請求失敗後等待重試的請求,紅色的代表失敗次數過 多rfi被忽略的請求,這樣可以直觀知道爬取的進度和請求情況.
pyspider [OPTIONS) COMMAND [ARGS)
1 Options: 2 -c, --config FILENAME 指定配置檔名稱 3 --logging-config TEXT 日誌配置檔名稱 ,預設 :pyspider/pyspider/logging.conf 4 --debug 開啟除錯模式 5 --queue-maxsize INTEGER 佇列的最大長反 6 --taskdb TEXT taskdb 的資料庫連線字串,預設: sqlite 7 --projectdb TEXT projectdb 的資料庫連線字串,預設: sqlite 8 --resultdb TEXT resultdb 的資料庫連線字串,預設: sqlite 9 --message-queue TEXT 訊息隊連線字串,預設· multiprocessing.Queue 10 --phantomjs-proxy TEXT PhantomJS 使用的代理, ip:port 的形式 11 --data-path TEXT 資料庫存放的路徑 12 --version pyspider 的版本 13 --help 顯示幫助資訊 14
crawl用法
• url
url是爬取時的 URL,可以定義為單個 URL字串,也可以定義成 URL列表
• callback
callback是回撥函式,指定了該 URL對應的響應內容用哪個方法來解析,
• age
age 是任務的有效時間 。 如果某個任務在有效時間內且已經被執行,則它不會重複執行
• priority
priority 是爬取任務的優先順序,其值預設是 0,priority 的數值越大,對應的請求會越優先被排程,
• exetime
exetime引數可以設定定時任務,其值是時間戳,預設是 0,即代表立即執行
• retries
retries 可以定義重試次數,其值預設是 3。
• itag
itag 引數設定判定網頁是存發生變化的節點值,在爬取時會判定次當前節點是否和上次爬取到的節點相同 。 如果節點相同,則證明頁面沒有更新,就不會重複爬取,
• auto recrawl
當開啟 時,爬取任務在過期後會重新執行,迴圈時間即定義的 age 時間長度
• method
method是 HTTP請求方式,它預設是 GET。 如果想發起 POST請求,可以將 method設定為 POST。
• params
我們可以方便地使用 params 來定義 GET請求引數
• data
data是 POST表單資料。 當請求方式為 POST時,我們可以通過此引數傳遞表單資料
• files
files 是上傳的檔案,需要指定檔名
• user_agent
user_agent 是爬取使用的 User-Agent。
• headers
headers是爬取時使用的 Headers,即 Request Headers
cookies
cookies 是爬取時使用的 Cookies,為字典格式 。
• connect timeout
connect timeout是在初始化連線時的最長等待時間,它預設是 20秒。
• timeout
timeout 是抓取網頁時的最長等待時間,它預設是 120秒。
• allow redirects
allow redirects 確定是否自動處理重定向,它預設是 True。
• proxy
proxy是爬取時使用的代理,它支援使用者名稱密碼的配置,格式為 username:password@hostname:port,
• fetch_type
fetch_type開啟 PhantomJS渲染 。如果遇到 JavaScript渲染的頁面,指定此欄位即可實現 PhantomJS的對接,pyspider將會使用 PhantomJS 進行網頁的抓取,
• js_script
js script 是頁面載入完畢後執行的 JavaScript指令碼
• js_run_at
JavaScript指令碼執行的位置,是在頁面節點開頭還是結尾 , 預設是結尾, 即 document-end。
• js_viewport_width/js_viewport_height
js_viewport_width/js_viewport_height是 JavaScript渲染頁面時的視窗大小。
• load_images
load_images在載入 JavaScript頁面時確定是否載入圖片,它預設是否。
• save
save 引數非常有用,可以在不同的方法之 間傳遞引數
• cancel
cancel是取消任務,如果一個任務是 ACTIVE狀態的, 則需要將 force_update設定為 True。
• force_ update
即使任務處於 ACTIVE狀態,那也會強制更新狀態。
pyspider判斷兩個任務是否是重複 的是使用的是該任務對應的 URL 的 MD5 值作為任務的唯一ID,如果ID 相 同,那麼兩個任務就會判定為相同,其中一個就不會爬取了 。 很多情況下請求的連結叮能是同一個,但是POST的引數不同。 這時可以重寫task_id()方法,改變這個ID的計算方式來實現不同任務的區分,
定時爬取
1 @every(minutes=24 * 60) 2 def on_start(self): 3 for url in urllist: 4 self.crawl(url, callback=self.index_page)