本文參照官方文檔譯
API 參考
- self.crawl
- Response
- self.send_message
- @every
- @catch_status_code_error
一 self.crawl(url, **kwargs)
pyspider 主要的API,用于創(chuàng)建一個(gè)爬取任務(wù),url 為目標(biāo)地址。
參 數(shù)
*必選參數(shù)
url: 抓取的目標(biāo)地址
callback: 回調(diào)函數(shù)
def on_start(self):
self.crawl(url='http://scrapy.org/', callback=self.index_page)
*以下參數(shù)是可選的
age: 任務(wù)的有效期,以秒為單位,在有效期內(nèi),該頁面被爬蟲視為未修改狀態(tài),忽略抓取。默認(rèn)值為-1:永久有效
@config(age=10 * 24 * 60 * 60) # 這里表示有效期為10天,既10天內(nèi)不會(huì)改變
def index_page(self, response):
...
priority: 爬取優(yōu)先級(jí),數(shù)字越大優(yōu)先級(jí)越大,默認(rèn)為0??梢杂眠@個(gè)來先做寬度搜索BFS并減少隊(duì)列中的任務(wù)數(shù)(這可能會(huì)花費(fèi)更多的內(nèi)存資源)
def index_page(self):
self.crawl('http://www.example.org/page2.html', callback=self.index_page)
self.crawl('http://www.example.org/233.html', callback=self.detail_page,
priority=1)
exetime:Unix時(shí)間戳中任務(wù)的執(zhí)行時(shí)間,默認(rèn)為0(立即執(zhí)行)
import time
def on_start(self):
self.crawl('http://www.example.org/', callback=self.callback,
exetime=time.time()+30*60) # 標(biāo)識(shí)30分鐘之后再執(zhí)行
retries: 失敗重試次數(shù),默認(rèn):3
itag: 任務(wù)標(biāo)記值,此標(biāo)記會(huì)在抓取時(shí)對(duì)比,如果這個(gè)值發(fā)生改變,不管有效期有沒有到都會(huì)重新抓取新內(nèi)容.多數(shù)用來動(dòng)態(tài)判斷內(nèi)容是否修改或強(qiáng)制重爬.默認(rèn)值是:None。(如果你想重新爬取所有任務(wù),你可以通過在Handler.crawl_config 設(shè)置itag值來重新設(shè)置新的版本號(hào))
example1:
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字段值改變,則無論有效期多少,重新爬取
example1:
class Handler(BaseHandler):
crawl_config = {
'itag': 'v223'
}
auto_recrawl: 自動(dòng)重爬,當(dāng)設(shè)置為True時(shí),任務(wù)每過一次有效期(age)都會(huì)自動(dòng)重新爬取,默認(rèn)值為False
def on_start(self):
self.crawl('http://www.example.org/', callback=self.callback,
age=5*60*60, auto_recrawl=True)
method: HTTP請(qǐng)求方法,默認(rèn):GET
params:URL后面的請(qǐng)求參數(shù),字典
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)
#這兩種請(qǐng)求是一樣的
data: POST請(qǐng)求參數(shù),字典值會(huì)form-encode后再附加
def on_start(self):
self.crawl('http://httpbin.org/post', callback=self.callback,
method='POST', data={'a': 123, 'b': 'c'})
files: 文件上傳,字典類型{field: {filename: 'content'}}
user_agent: 請(qǐng)求user-agent
headers: 請(qǐng)求頭,字典類型
cookies:自定義請(qǐng)求的cookies,字典類型
connect_timeout: 指定請(qǐng)求時(shí)鏈接超時(shí)時(shí)間,單位秒,默認(rèn)值:20
timeout: 請(qǐng)求內(nèi)容里最大等待秒數(shù).默認(rèn)值:120
allow_redirects: 遇到30x狀態(tài)碼時(shí)是否重新請(qǐng)求跟隨.默認(rèn)是:True
validate_cert: 遇到HTTPS類型的URL時(shí)是否驗(yàn)證證書,默認(rèn)值:True
proxy: 設(shè)置代理服務(wù)器,格式如username:password@hostname:port暫時(shí)只支持http代理(也可以在Handler.crawl_config中設(shè)置全局代理)
class Handler(BaseHandler):
crawl_config = {
'proxy': 'localhost:8080'
}
etag: 頁面內(nèi)容沒改變則使用HTTP Etag機(jī)制傳遞進(jìn)程默認(rèn)值:True
last_modified: 頁面內(nèi)容沒改變則使用HTTP Last-Modified標(biāo)機(jī)制傳遞進(jìn)程默認(rèn)值:True
fetch_type: 設(shè)置是否啟用JavaScript解析引擎. default: None
js_script: 頁面加載前或者加載后運(yùn)行JavaScript 腳本,格式:function() { document.write("binux"); }
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;
}
''')
#在這個(gè)函數(shù)中,腳本會(huì)將頁面滾動(dòng)到底部。函數(shù)中返回的值可以通過Response.js_script_result來返回
js_run_at: 和上面運(yùn)行js腳本js_script一起使用,可以設(shè)置運(yùn)行腳本的位置在開頭document-start或是結(jié)尾document-end,默認(rèn):document-end
js_viewport_width/js_viewport_height: JavaScript渲染頁面時(shí)的窗口大小。
load_images: 當(dāng)開啟js fetcher時(shí),是否讀取圖片,默認(rèn)為False
save: save 參數(shù)非常有用,可以在不同的方法之 間傳遞參數(shù),比如傳遞一個(gè)對(duì)象給callback函數(shù)
def on_start(self):
self.crawl('http://www.example.org/', callback=self.callback,
save={'a': 123})
def callback(self, response):
return response.save['a']
taskid: pyspider判斷兩個(gè)任務(wù)是否是重復(fù) 的是使用的是該任務(wù)對(duì)應(yīng)的 URL 的 MD5 值作為任務(wù)的唯一ID,如果ID 相 同,那么兩個(gè)任務(wù)就會(huì)判定為相同,其中一個(gè)就不會(huì)爬取了 。 很多情況下請(qǐng)求的鏈接叮能是同一個(gè),但是POST的參數(shù)不同。 這時(shí)可以重寫task_id()方法,改變這個(gè)ID的計(jì)算方式來實(shí)現(xiàn)不同任務(wù)的區(qū)分
import json
from pyspider.libs.utils import md5string
def get_taskid(self, task):
return md5string(task['url']+json.dumps(task['fetch'].get('data', '')))
force_update: 即使任務(wù)處于 ACTIVE狀態(tài),那也會(huì)強(qiáng)制更新狀態(tài)
cancel: cancel是取消任務(wù),如果一個(gè)任務(wù)是 ACTIVE狀態(tài)的, 則需要將 force_update設(shè)置為 True
cURL command
self.crawl(curl_command)
cURL用于發(fā)HTTP請(qǐng)求命令行工具輕松獲取Chrome Devtools>網(wǎng)絡(luò)面板右鍵單擊請(qǐng)求復(fù)制cURL
您使用cURL命令作第參數(shù)self.crawl解析命令并使HTTP請(qǐng)求像curl
如何刪除任務(wù)?
將任務(wù)的 group 設(shè)置為 delete ,并將狀態(tài)設(shè)置為 STOP,沒有更新 24小時(shí) 之后,scheduler 會(huì)自動(dòng)刪除任務(wù)。
@config(**kwargs)
將修飾方法用作回調(diào)時(shí)self.crawl的默認(rèn)參數(shù)。
@config(age=15*60)
def index_page(self, response):
self.crawl('http://www.example.org/list-1.html', callback=self.index_page)
self.crawl('http://www.example.org/product-233', callback=self.detail_page)
@config(age=10*24*60*60)
def detail_page(self, response):
return {...}
# 1.html的存活期為15分鐘,而233頁面的存活期為10天,因?yàn)樗幕卣{(diào)函數(shù)市detail_page,所以共享detail_page的config
Handler.crawl_config = {}
全局參數(shù)
class Handler(BaseHandler):
crawl_config = {
'headers': {
'User-Agent': 'GoogleBot',
}
}
...
二 response
Response.url
Response.textContent of response, in unicode.if Response.encoding is None and chardet module is available, encoding of content will be guessed.
Response.content
Response.doc pyspider封裝的一個(gè) PyQuery對(duì)象看
Response.etree lxml對(duì)象
Response.json json對(duì)象
Response.status_code
Response.orig_url 如果在請(qǐng)求期間有任何重定向,這里是您通過self.crawl提交的URL。
Response.headers 不區(qū)分大小寫的dict保存響應(yīng)的頭。
Response.cookies
Response.error http請(qǐng)求的錯(cuò)誤信息
Response.cookies
Response.time http請(qǐng)求時(shí)間
Response.ok 如果請(qǐng)求成功為Ture
Response.encoding response.content的編碼。如果response.encoding為none,編碼將由header、content或chardet(如果可用)進(jìn)行猜測(cè)。手動(dòng)設(shè)置內(nèi)容編碼將覆蓋猜測(cè)的編碼。
Response.save self.crawl api保存的對(duì)象
Response.js_script_result JS腳本返回的內(nèi)容
Response.raise_for_status() 如果狀態(tài)代碼不是200或response.error存在,則引發(fā)httperror。
三 self.send_message
self.send_message(project, msg, [url]) 向其他項(xiàng)目發(fā)送消息??梢酝ㄟ^def on_message(self,project,message)回調(diào)接收。
-
project發(fā)送消息的項(xiàng)目名稱 -
msgjson對(duì)象 -
urlresult will been overwrite if have same taskid. send_message share a same taskid by default. Change this to return multiple result by one response
pyspider send_message [OPTIONS] PROJECT MESSAGE 你也可以通過命令行發(fā)送消息給其它項(xiàng)目
Usage: pyspider send_message [OPTIONS] PROJECT MESSAGE
Send Message to project from command line
Options:
--scheduler-rpc TEXT xmlrpc path of scheduler
--help Show this message and exit.
def on_message(self, project, message) 從其它項(xiàng)目接收消息
四 @catch_status_code_error
非200響應(yīng)將被視為獲取失敗,不會(huì)傳遞到回調(diào)。使用此修飾符覆蓋此功能。
def on_start(self):
self.crawl('http://httpbin.org/status/404', self.callback)
@catch_status_code_error
def callback(self, response):
...
五 @every(minutes=0, seconds=0)
該方法將每隔幾分鐘或幾秒調(diào)用一次
@every(minutes=24 * 60)
def on_start(self):
for url in urllist:
pass
URL將每24小時(shí)重新啟動(dòng)一次。請(qǐng)注意,如果還使用了age,并且該時(shí)間段比@every長,則將放棄爬網(wǎng)請(qǐng)求,因?yàn)樗灰暈槲锤模?
@every(minutes=24 * 60)
def on_start(self):
self.crawl('http://www.example.org/', callback=self.index_page)
@config(age=10 * 24 * 60 * 60)
def index_page(self):
...
盡管爬行請(qǐng)求每天都會(huì)觸發(fā),但它被丟棄,并且只每隔10天重新啟動(dòng)一次。