Python3 爬蟲學習筆記第十八章 —— 【爬蟲框架 pyspider — 深入理解】
文章目錄
【18.1】啓動參數
常用啓動命令:pyspider all
,完整命令結構爲:pyspider [OPTIONS] COMMAND [ARGS]
,OPTIONS 爲可選參數,包含以下參數:
- -c, --config FILENAME:指定配置文件名稱
- –logging-config TEXT:日誌配置文件名稱,默認: pyspider/pyspider/logging.conf
- –debug:開啓調試模式
- –queue-maxsize INTEGER:隊列的最大長度
- –taskdb TEXT:taskdb 的數據庫連接字符串,默認: sqlite
- –projectdb TEXT:projectdb 的數據庫連接字符串,默認: sqlite
- –resultdb TEXT:resultdb 的數據庫連接字符串,默認: sqlite
- –message-queue TEXT:消息隊列連接字符串,默認: multiprocessing.Queue
- –phantomjs-proxy TEXT:PhantomJS 使用的代理,ip:port 的形式
- –data-path TEXT:數據庫存放的路徑
- –add-sys-path / --not-add-sys-path:將當前工作目錄添加到python lib搜索路徑
- –version:顯示 pyspider 的版本信息
- –help:顯示幫助信息
配置文件爲一個 JSON 文件,一般爲 config.json 文件,常用配置如下:
{
"taskdb": "mysql+taskdb://username:password@host:port/taskdb",
"projectdb": "mysql+projectdb://username:password@host:port/projectdb",
"resultdb": "mysql+resultdb://username:password@host:port/resultdb",
"message_queue": "amqp://username:password@host:port/%2F",
"webui": {
"port": 5000,
"username": "some_name",
"password": "some_passwd",
"need-auth": true
}
}
可以設置對應的用戶名,密碼,端口等信息,使用命令 pyspider -c config.json all
即可運行
【18.2】運行單個組件
pyspider 的架構主要分爲 Scheduler(調度器)、Fetcher(抓取器)、Processer(處理器)三個部分,都可以單獨運行,基本命令: pyspider [component_name] [options]
【18.2.1】運行 Scheduler
pyspider scheduler [OPTIONS]
Options:
--xmlrpc /--no-xmlrpc
--xmlrpc-host TEXT
--xmlrpc-port INTEGER
--inqueue-limit INTEGER 任務隊列的最大長度,如果滿了則新的任務會被忽略
--delete-time INTEGER 設置爲 delete 標記之前的刪除時間
--active-tasks INTEGER 當前活躍任務數量配置
--loop-limit INTEGER 單輪最多調度的任務數量
--fail-pause-num INTEGER 上次失敗時自動暫停項目暫停次數,任務失敗,將0設置爲禁用
--scheduler-cls TEXT Scheduler 使用的類
--threads TEXT ThreadBaseScheduler 的線程號,默認值:4
--help 顯示幫助信息
【18.2.2】運行 Fetcher
pyspider fetcher [OPTIONS]
Options:
--xmlrpc /--no-xmlrpc
--xmlrpc-host TEXT
--xmlrpc-port INTEGER
--poolsize INTEGER 同時請求的個數
--proxy TEXT 使用的代理
--user-agent TEXT 使用的 User-Agent
--timeout TEXT 超時時間
--phantomjs-endpoint TEXT phantomjs 的端點,通過 pyspider 啓動 phantomjs
--splash-endpoint TEXT 執行 splash 的端點:http://splash.readthedocs.io/en/stable/api.html execut
--fetcher-cls TEXT Fetcher 使用的類
--help 顯示幫助信息
【18.2.3】運行 Processer
pyspider processor [OPTIONS]
Options:
--processor-cls TEXT Processor 使用的類
--process-time-limit INTEGER 腳本處理時間限制
--help 顯示幫助信息
【18.2.4】運行 WebUI
pyspider webui [OPTIONS]
Options:
--host TEXT 運行地址
--port INTEGER 運行端口
--cdn TEXT JS 和 CSS 的 CDN 服務器
--scheduler-rpc TEXT Scheduler 的 xmlrpc 路徑
--fetcher-rpc TEXT Fetcher 的 xmlrpc 路徑
--max-rate FLOAT 每個項目最大的 rate 值
--max-burst FLOAT 每個項目最大的 burst 值
--username TEXT Auth 驗證的用戶名
--password TEXT Auth 驗證的密碼
--need-auth 是否需要驗證
--webui-instance TEXT 運行時使用的 Flask 應用
--process-time-limit INTEGER 調試中的腳本處理時間限制
--help 顯示幫助信息
【18.3】crawl() 方法各參數
參數文檔:http://docs.pyspider.org/en/latest/apis/self.crawl/
- url:爬取目標 URL,可以定義爲單個 URL 字符串,也可以定義成 URL 列表
- callback:回調函數,指定了該 URL 對應的響應內容用哪個方法來解析,示例:
代碼解釋:指定def on_start(self): self.crawl('http://www.itrhx.com/', callback=self.index_page)
callback
爲index_page
,代表爬取 http://www.itrhx.com/ 得到的響應會用index_page()
方法來解析,而index_page()
方法的第一個參數就是響應對象,如下所示:def index_page(self, response): pass
-
age:任務的有效時間,如果某個任務在有效時間內且已經被執行,則它不會重複執行,有如下兩種設置方法:
def on_start(self): self.crawl('http://www.itrhx.com/', callback=self.callback, age=10*24*60*60)
@config(age=10 * 24 * 60 * 60) def callback(self): pass
- priority:爬取任務的優先級,其值默認是 0,priority 的數值越大,對應的請求會越優先被調度,如下所示,
2.html
頁面將會優先爬取:def index_page(self): self.crawl('http://www.itrhx.com/1.html', callback=self.index_page) self.crawl('http://www.itrhx.com/2.html', callback=self.detail_page, priority=1)
- exetime:設置定時任務,其值是時間戳,默認是 0,即代表立即執行,如下所示表示該任務會在 30 分鐘之後執行:
import time def on_start(self): self.crawl('http://www.itrhx.com/', callback=self.callback, exetime=time.time()+30*60)
- retries:定義重試次數,其值默認是 3
- itag:設置判定網頁是否發生變化的節點值,在爬取時會判定次當前節點是否和上次爬取到的節點相同。如果節點相同,則證明頁面沒有更新,就不會重複爬取,如下所示:
代碼解釋:設置def index_page(self, response): for item in response.doc('.item').items(): self.crawl(item.find('a').attr.url, callback=self.detail_page, itag=item.find('.update-time').text())
update-time
這個節點的值爲 itag,在下次爬取時就會首先檢測這個值有沒有發生變化,如果沒有變化,則不再重複爬取,否則執行爬取
- auto_recrawl:開啓時,爬取任務在過期後會重新執行,循環時間即定義的 age 時間長度,如下所示:
代碼解釋:定義def on_start(self): self.crawl('http://www.itrhx.com/', callback=self.callback, age=5*60*60, auto_recrawl=True)
age
有效期爲 5 小時,設置了auto_recrawl
爲True
,這樣任務就會每 5 小時執行一次
- method:HTTP 請求方式,默認爲 GET,如果想發起 POST 請求,可以將 method 設置爲 POST
- params:定義 GET 請求參數,如下所示表示兩個等價的爬取任務:
def on_start(self): self.crawl('http://httpbin.org/get', callback=self.callback, params={'a': 123, 'b': 'c'}) self.crawl('http://httpbin.org/get?a=123&b=c', callback=self.callback)
- data:POST 表單數據,當請求方式爲 POST 時,我們可以通過此參數傳遞表單數據,如下所示:
def on_start(self): self.crawl('http://httpbin.org/post', callback=self.callback, method='POST', data={'a': 123, 'b': 'c'})
- files:上傳的文件,需要指定文件名,如下所示:
def on_start(self): self.crawl('http://httpbin.org/post', callback=self.callback, method='POST', files={field: {filename: 'content'}})
- user_agent:爬取使用的 User-Agent
- headers:爬取時使用的 Headers,即 Request Headers
- cookies:爬取時使用的 Cookies,爲字典格式
- connect_timeout:在初始化連接時的最長等待時間,默認爲 20 秒
- timeout:抓取網頁時的最長等待時間,默認爲 120 秒
- allow_redirects:確定是否自動處理重定向,默認爲 True
- validate_cert:確定是否驗證證書,此選項對 HTTPS 請求有效,默認爲 True
- proxy:爬取時使用的代理,支持用戶名密碼的配置,格式爲
username:password@hostname:port
,如下所示:
也可以設置def on_start(self): self.crawl('http://httpbin.org/get', callback=self.callback, proxy='127.0.0.1:9743')
craw_config
來實現全局配置,如下所示:class Handler(BaseHandler): crawl_config = {'proxy': '127.0.0.1:9743'}
- fetch_type:開啓 PhantomJS 渲染,如果遇到 JavaScript 渲染的頁面,指定此字段即可實現 PhantomJS 的對接,pyspider 將會使用 PhantomJS 進行網頁的抓取,如下所示:
def on_start(self): self.crawl('https://www.taobao.com', callback=self.index_page, fetch_type='js')
- js_script:頁面加載完畢後執行的 JavaScript 腳本,如下所示,頁面加載成功後將執行頁面混動的 JavaScript 代碼,頁面會下拉到最底部:
def on_start(self): self.crawl('http://www.example.org/', callback=self.callback, fetch_type='js', js_script=''' function() {window.scrollTo(0,document.body.scrollHeight); return 123; } ''')
- js_run_at:代表 JavaScript 腳本運行的位置,是在頁面節點開頭還是結尾,默認是結尾,即
document-end
- js_viewport_width/js_viewport_height:JavaScript 渲染頁面時的窗口大小
- load_images:在加載 JavaScript 頁面時確定是否加載圖片,默認爲否
- save:在不同的方法之間傳遞參數,如下所示:
def on_start(self): self.crawl('http://www.example.org/', callback=self.callback, save={'page': 1}) def callback(self, response): return response.save['page']
- cancel:取消任務,如果一個任務是
ACTIVE
狀態的,則需要將force_update
設置爲True
- force_update:即使任務處於 ACTIVE 狀態,那也會強制更新狀態
【18.4】任務區分
pyspider 判斷兩個任務是否是重複的是使用的是該任務對應的 URL 的 MD5 值作爲任務的唯一 ID,如果 ID 相同,那麼兩個任務就會判定爲相同,其中一個就不會爬取了
某些情況下,請求的鏈接是同一個,但是 POST 的參數不同,這時可以重寫 task_id()
方法,利用 URL 和 POST 的參數來生成 ID,改變這個 ID 的計算方式來實現不同任務的區分:
import json
from pyspider.libs.utils import md5string
def get_taskid(self, task):
return md5string(task['url']+json.dumps(task['fetch'].get('data', '')))
【18.5】全局配置
pyspider 可以使用 crawl_config
來指定全局的配置,配置中的參數會和 crawl()
方法創建任務時的參數合併:
class Handler(BaseHandler):
crawl_config = {
'headers': {'User-Agent': 'GoogleBot',}
'proxy': '127.0.0.1:9743'
}
【18.6】定時爬取
通過 every
屬性來設置爬取的時間間隔,如下代碼表示每天執行一次爬取:
@every(minutes=24 * 60)
def on_start(self):
for url in urllist:
self.crawl(url, callback=self.index_page)
注意事項:如果設置了任務的有效時間(age 參數),因爲在有效時間內爬取不會重複,所以要把有效時間設置得比重複時間更短,這樣纔可以實現定時爬取
錯誤舉例:設定任務的過期時間爲 5 天,而自動爬取的時間間隔爲 1 天,當第二次嘗試重新爬取的時候,pyspider 會監測到此任務尚未過期,便不會執行爬取:
@every(minutes=24 * 60)
def on_start(self):
self.crawl('http://www.itrhx.com/', callback=self.index_page)
@config(age=5 * 24 * 60 * 60)
def index_page(self):
pass