Python版本管理:pyenv和pyenv-virtualenv
Scrapy爬蟲入門教程一 安裝和基本使用
Scrapy爬蟲入門教程二 官方提供Demo
Scrapy爬蟲入門教程三 命令行工具介紹和示例
Scrapy爬蟲入門教程四 Spider(爬蟲)
Scrapy爬蟲入門教程五 Selectors(選擇器)
Scrapy爬蟲入門教程六 Items(項目)
Scrapy爬蟲入門教程七 Item Loaders(項目加載器)
Scrapy爬蟲入門教程八 交互式 shell 方便調(diào)試
Scrapy爬蟲入門教程九 Item Pipeline(項目管道)
Scrapy爬蟲入門教程十 Feed exports(導(dǎo)出文件)
Scrapy爬蟲入門教程十一 Request和Response(請求和響應(yīng))
Scrapy爬蟲入門教程十二 Link Extractors(鏈接提取器)
開發(fā)環(huán)境:
Python 3.6.0 版本
(當(dāng)前最新)
Scrapy 1.3.2 版本
(當(dāng)前最新)
請求和響應(yīng)
Scrapy的Request和Response對象用于爬網(wǎng)網(wǎng)站。
通常苔埋,Request對象在爬蟲程序中生成并傳遞到系統(tǒng)懦砂,直到它們到達下載程序,后者執(zhí)行請求并返回一個Response對象组橄,該對象返回到發(fā)出請求的爬蟲程序荞膘。
上面一段話比較拗口,有web經(jīng)驗的同學(xué)玉工,應(yīng)該都了解的羽资,不明白看下面的圖大概理解下。
爬蟲->Request:創(chuàng)建
Request->Response:獲取下載數(shù)據(jù)
Response->爬蟲:數(shù)據(jù)
兩個類Request和Response類都有一些子類遵班,它們添加基類中不需要的功能屠升。這些在下面的請求子類和 響應(yīng)子類中描述。
Request objects
class scrapy.http.Request(url[, callback, method='GET', headers, body, cookies, meta, encoding='utf-8', priority=0, dont_filter=False, errback])
一個Request對象表示一個HTTP請求狭郑,它通常是在爬蟲生成腹暖,并由下載執(zhí)行,從而生成Response翰萨。
- 參數(shù):
url(string)
- 此請求的網(wǎng)址callback(callable)
- 將使用此請求的響應(yīng)(一旦下載)作為其第一個參數(shù)調(diào)用的函數(shù)脏答。有關(guān)更多信息,請參閱下面的將附加數(shù)據(jù)傳遞給回調(diào)函數(shù)缨历。如果請求沒有指定回調(diào)以蕴,parse()將使用spider的 方法。請注意辛孵,如果在處理期間引發(fā)異常丛肮,則會調(diào)用errback。method(string)
- 此請求的HTTP方法魄缚。默認為'GET'宝与。meta(dict)
- 屬性的初始值Request.meta。如果給定冶匹,在此參數(shù)中傳遞的dict將被淺復(fù)制习劫。body(str或unicode)
- 請求體。如果unicode傳遞了a嚼隘,那么它被編碼為 str使用傳遞的編碼(默認為utf-8)诽里。如果 body沒有給出,則存儲一個空字符串飞蛹。不管這個參數(shù)的類型谤狡,存儲的最終值將是一個str(不會是unicode或None)灸眼。headers(dict)
- 這個請求的頭。dict值可以是字符串(對于單值標頭)或列表(對于多值標頭)墓懂。如果 None作為值傳遞焰宣,則不會發(fā)送HTTP頭。-
cookie(dict或list)
- 請求cookie捕仔。這些可以以兩種形式發(fā)送匕积。- 使用dict:
request_with_cookies = Request(url="http://www.example.com", cookies={'currency': 'USD', 'country': 'UY'})
* 使用列表:
```
request_with_cookies = Request(url="http://www.example.com",
cookies=[{'name': 'currency',
'value': 'USD',
'domain': 'example.com',
'path': '/currency'}])
```
后一種形式允許定制 cookie的屬性domain和path屬性。這只有在保存Cookie用于以后的請求時才有用榜跌。
當(dāng)某些網(wǎng)站返回Cookie(在響應(yīng)中)時闪唆,這些Cookie會存儲在該域的Cookie中,并在將來的請求中再次發(fā)送斜做。這是任何常規(guī)網(wǎng)絡(luò)瀏覽器的典型行為苞氮。但是,如果由于某種原因瓤逼,您想要避免與現(xiàn)有Cookie合并笼吟,您可以通過將dont_merge_cookies關(guān)鍵字設(shè)置為True 來指示Scrapy如此操作 Request.meta。
不合并Cookie的請求示例:
request_with_cookies = Request(url="http://www.example.com",
cookies={'currency': 'USD', 'country': 'UY'},
meta={'dont_merge_cookies': True})
有關(guān)詳細信息霸旗,請參閱CookiesMiddleware贷帮。
encoding(string)
- 此請求的編碼(默認為'utf-8')。此編碼將用于對URL進行百分比編碼诱告,并將正文轉(zhuǎn)換為str(如果給定unicode)撵枢。priority(int)
- 此請求的優(yōu)先級(默認為0)。調(diào)度器使用優(yōu)先級來定義用于處理請求的順序精居。具有較高優(yōu)先級值的請求將較早執(zhí)行锄禽。允許負值以指示相對低優(yōu)先級。dont_filter(boolean)
- 表示此請求不應(yīng)由調(diào)度程序過濾靴姿。當(dāng)您想要多次執(zhí)行相同的請求時忽略重復(fù)過濾器時使用沃但。小心使用它,或者你會進入爬行循環(huán)佛吓。默認為False提前。errback(callable)
- 如果在處理請求時引發(fā)任何異常错妖,將調(diào)用的函數(shù)赛糟。這包括失敗的404 HTTP錯誤等頁面睁搭。它接收一個Twisted Failure實例作為第一個參數(shù)。有關(guān)更多信息吱型,請參閱使用errbacks在請求處理中捕獲異常逸贾。url
包含此請求的網(wǎng)址的字符串。請記住,此屬性包含轉(zhuǎn)義的網(wǎng)址耕陷,因此它可能與構(gòu)造函數(shù)中傳遞的網(wǎng)址不同掂名。
此屬性為只讀。更改請求使用的URL replace()
哟沫。
method
表示請求中的HTTP方法的字符串。這保證是大寫的锌介。例如:"GET"嗜诀,"POST","PUT"
等headers
包含請求標頭的類似字典的對象孔祸。body
包含請求正文的str隆敢。
此屬性為只讀。更改請求使用的正文 replace()
崔慧。
-
meta
包含此請求的任意元數(shù)據(jù)的字典拂蝎。此dict對于新請求為空,通常由不同的Scrapy組件(擴展程序惶室,中間件等)填充温自。因此,此dict中包含的數(shù)據(jù)取決于您啟用的擴展皇钞。
有關(guān)Scrapy識別的特殊元鍵列表悼泌,請參閱Request.meta特殊鍵。
當(dāng)使用or 方法克隆請求時夹界,此dict是淺復(fù)制的 馆里,并且也可以在您的爬蟲中從屬性訪問。copy()replace()response.meta
copy()
返回一個新的請求可柿,它是這個請求的副本鸠踪。另請參見: 將附加數(shù)據(jù)傳遞到回調(diào)函數(shù)。replace([url, method, headers, body, cookies, meta, encoding, dont_filter, callback, errback])
返回具有相同成員的Request對象复斥,但通過指定的任何關(guān)鍵字參數(shù)賦予新值的成員除外营密。該屬性Request.meta是默認復(fù)制(除非新的值在給定的meta參數(shù))。另請參見 將附加數(shù)據(jù)傳遞給回調(diào)函數(shù)永票。
將附加數(shù)據(jù)傳遞給回調(diào)函數(shù)
請求的回調(diào)是當(dāng)下載該請求的響應(yīng)時將被調(diào)用的函數(shù)卵贱。將使用下載的Response對象作為其第一個參數(shù)來調(diào)用回調(diào)函數(shù)。
例:
def parse_page1(self, response):
return scrapy.Request("http://www.example.com/some_page.html",
callback=self.parse_page2)
def parse_page2(self, response):
# this would log http://www.example.com/some_page.html
self.logger.info("Visited %s", response.url)
在某些情況下侣集,您可能有興趣向這些回調(diào)函數(shù)傳遞參數(shù)键俱,以便稍后在第二個回調(diào)中接收參數(shù)。您可以使用該Request.meta
屬性世分。
以下是使用此機制傳遞項目以填充來自不同頁面的不同字段的示例:
def parse_page1(self, response):
item = MyItem()
item['main_url'] = response.url
request = scrapy.Request("http://www.example.com/some_page.html",
callback=self.parse_page2)
request.meta['item'] = item
yield request
def parse_page2(self, response):
item = response.meta['item']
item['other_url'] = response.url
yield item
使用errbacks在請求處理中捕獲異常
請求的errback是在處理異常時被調(diào)用的函數(shù)编振。
它接收一個Twisted Failure實例作為第一個參數(shù),并可用于跟蹤連接建立超時,DNS錯誤等踪央。
這里有一個示例爬蟲記錄所有錯誤臀玄,并捕獲一些特定的錯誤,如果需要:
import scrapy
from scrapy.spidermiddlewares.httperror import HttpError
from twisted.internet.error import DNSLookupError
from twisted.internet.error import TimeoutError, TCPTimedOutError
class ErrbackSpider(scrapy.Spider):
name = "errback_example"
start_urls = [
"http://www.httpbin.org/", # HTTP 200 expected
"http://www.httpbin.org/status/404", # Not found error
"http://www.httpbin.org/status/500", # server issue
"http://www.httpbin.org:12345/", # non-responding host, timeout expected
"http://www.httphttpbinbin.org/", # DNS error expected
]
def start_requests(self):
for u in self.start_urls:
yield scrapy.Request(u, callback=self.parse_httpbin,
errback=self.errback_httpbin,
dont_filter=True)
def parse_httpbin(self, response):
self.logger.info('Got successful response from {}'.format(response.url))
# do something useful here...
def errback_httpbin(self, failure):
# log all failures
self.logger.error(repr(failure))
# in case you want to do something special for some errors,
# you may need the failure's type:
if failure.check(HttpError):
# these exceptions come from HttpError spider middleware
# you can get the non-200 response
response = failure.value.response
self.logger.error('HttpError on %s', response.url)
elif failure.check(DNSLookupError):
# this is the original request
request = failure.request
self.logger.error('DNSLookupError on %s', request.url)
elif failure.check(TimeoutError, TCPTimedOutError):
request = failure.request
self.logger.error('TimeoutError on %s', request.url)
Request.meta特殊鍵
該Request.meta
屬性可以包含任何任意數(shù)據(jù)畅蹂,但有一些特殊的鍵由Scrapy及其內(nèi)置擴展識別健无。
那些是:
dont_redirect
dont_retry
handle_httpstatus_list
handle_httpstatus_all
dont_merge_cookies(參見cookies構(gòu)造函數(shù)的Request參數(shù))
cookiejar
dont_cache
redirect_urls
bindaddress
dont_obey_robotstxt
download_timeout
download_maxsize
download_latency
proxy
bindaddress
用于執(zhí)行請求的出站IP地址的IP。
download_timeout
下載器在超時前等待的時間量(以秒為單位)液斜。參見:DOWNLOAD_TIMEOUT
累贤。
download_latency
自請求已啟動以來,用于獲取響應(yīng)的時間量少漆,即通過網(wǎng)絡(luò)發(fā)送的HTTP消息臼膏。此元鍵僅在響應(yīng)已下載時可用。雖然大多數(shù)其他元鍵用于控制Scrapy行為示损,但這應(yīng)該是只讀的渗磅。
請求子類
這里是內(nèi)置子類的Request列表。您還可以將其子類化以實現(xiàn)您自己的自定義功能检访。
FormRequest對象
FormRequest類擴展了Request具有處理HTML表單的功能的基礎(chǔ)始鱼。它使用lxml.html表單 從Response對象的表單數(shù)據(jù)預(yù)填充表單字段。
class scrapy.http.FormRequest(url[, formdata, ...])
本FormRequest
類增加了新的構(gòu)造函數(shù)的參數(shù)烛谊。其余的參數(shù)與Request
類相同风响,這里沒有記錄。
- 參數(shù):formdata(元組的dict或iterable) - 是一個包含HTML Form數(shù)據(jù)的字典(或(key丹禀,value)元組的迭代)状勤,它將被url編碼并分配給請求的主體。
該FormRequest
對象支持除標準以下類方法Request的方法:
classmethod from_response(response[, formname=None, formid=None, formnumber=0, formdata=None, formxpath=None, formcss=None, clickdata=None, dont_click=False, ...])
返回一個新FormRequest
對象双泪,其中的表單字段值已預(yù)先<form>
填充在給定響應(yīng)中包含的HTML 元素中持搜。有關(guān)示例,請參閱 使用FormRequest.from_response()來模擬用戶登錄焙矛。
該策略是在任何可查看的表單控件上默認自動模擬點擊葫盼,如a 。即使這是相當(dāng)方便村斟,并且經(jīng)常想要的行為贫导,有時它可能導(dǎo)致難以調(diào)試的問題。例如蟆盹,當(dāng)使用使用javascript填充和/或提交的表單時孩灯,默認行為可能不是最合適的。要禁用此行為逾滥,您可以將參數(shù)設(shè)置 為峰档。此外,如果要更改單擊的控件(而不是禁用它),您還可以使用 參數(shù)讥巡。<input type="submit"> from_response() dont_click True clickdata
參數(shù):
- response(Responseobject) - 包含將用于預(yù)填充表單字段的HTML表單的響應(yīng)
- formname(string) - 如果給定掀亩,將使用name屬性設(shè)置為此值的形式。
- formid(string) - 如果給定欢顷,將使用id屬性設(shè)置為此值的形式槽棍。
- formxpath(string) - 如果給定,將使用匹配xpath的第一個表單抬驴。
- formcss(string) - 如果給定刹泄,將使用匹配css選擇器的第一個形式。
- formnumber(integer) - 當(dāng)響應(yīng)包含多個表單時要使用的表單的數(shù)量怎爵。第一個(也是默認)是0。
- formdata(dict) - 要在表單數(shù)據(jù)中覆蓋的字段盅蝗。如果響應(yīng)<form>元素中已存在字段鳖链,則其值將被在此參數(shù)中傳遞的值覆蓋。
- clickdata(dict) - 查找控件被點擊的屬性墩莫。如果沒有提供芙委,表單數(shù)據(jù)將被提交,模擬第一個可點擊元素的點擊狂秦。除了html屬性灌侣,控件可以通過其相對于表單中其他提交表輸入的基于零的索引,通過nr屬性來標識裂问。
- dont_click(boolean) - 如果為True侧啼,表單數(shù)據(jù)將在不點擊任何元素的情況下提交。
這個類方法的其他參數(shù)直接傳遞給 FormRequest構(gòu)造函數(shù)堪簿。
在新版本0.10.3:該formname參數(shù)痊乾。
在新版本0.17:該formxpath參數(shù)。
新的版本1.1.0:該formcss參數(shù)椭更。
新的版本1.1.0:該formid參數(shù)哪审。
請求使用示例
使用FormRequest通過HTTP POST發(fā)送數(shù)據(jù)
如果你想在你的爬蟲中模擬HTML表單POST并發(fā)送幾個鍵值字段,你可以返回一個FormRequest對象(從你的爬蟲)像這樣:
return [FormRequest(url="http://www.example.com/post/action",
formdata={'name': 'John Doe', 'age': '27'},
callback=self.after_post)]
使用FormRequest.from_response()來模擬用戶登錄
網(wǎng)站通常通過元素(例如會話相關(guān)數(shù)據(jù)或認證令牌(用于登錄頁面))提供預(yù)填充的表單字段虑瀑。進行剪貼時湿滓,您需要自動預(yù)填充這些字段,并且只覆蓋其中的一些舌狗,例如用戶名和密碼叽奥。您可以使用 此作業(yè)的方法。這里有一個使用它的爬蟲示例:<input type="hidden"> FormRequest.from_response()
import scrapy
class LoginSpider(scrapy.Spider):
name = 'example.com'
start_urls = ['http://www.example.com/users/login.php']
def parse(self, response):
return scrapy.FormRequest.from_response(
response,
formdata={'username': 'john', 'password': 'secret'},
callback=self.after_login
)
def after_login(self, response):
# check login succeed before going on
if "authentication failed" in response.body:
self.logger.error("Login failed")
return
# continue scraping with authenticated session...
響應(yīng)對象
class scrapy.http.Response(url[, status=200, headers=None, body=b'', flags=None, request=None])
一個Response對象表示的HTTP響應(yīng)把夸,這通常是下載(由下載)而线,并供給到爬蟲進行處理。
參數(shù):
- url(string) - 此響應(yīng)的URL
- status(integer) - 響應(yīng)的HTTP狀態(tài)。默認為200膀篮。
- headers(dict) - 這個響應(yīng)的頭嘹狞。dict值可以是字符串(對于單值標頭)或列表(對于多值標頭)。
- body(str) - 響應(yīng)體誓竿。它必須是str磅网,而不是unicode,除非你使用一個編碼感知響應(yīng)子類筷屡,如
TextResponse
涧偷。 - flags(list) - 是一個包含屬性初始值的
Response.flags
列表。如果給定毙死,列表將被淺復(fù)制燎潮。 - request(Requestobject) - 屬性的初始值
Response.request
。這代表Request生成此響應(yīng)扼倘。
url
包含響應(yīng)的URL的字符串确封。
此屬性為只讀。更改響應(yīng)使用的URL replace()再菊。
status
表示響應(yīng)的HTTP狀態(tài)的整數(shù)爪喘。示例:200, 404纠拔。
headers
包含響應(yīng)標題的類字典對象秉剑。可以使用get()返回具有指定名稱的第一個標頭值或getlist()返回具有指定名稱的所有標頭值來訪問值稠诲。例如侦鹏,此調(diào)用會為您提供標題中的所有Cookie:
response.headers.getlist('Set-Cookie')
body
本回復(fù)的正文。記住Response.body總是一個字節(jié)對象吕粹。如果你想unicode版本使用 TextResponse.text(只在TextResponse 和子類中可用)种柑。
此屬性為只讀。更改響應(yīng)使用的主體 replace()匹耕。
request
Request生成此響應(yīng)的對象聚请。在響應(yīng)和請求通過所有下載中間件后,此屬性在Scrapy引擎中分配稳其。特別地驶赏,這意味著:
HTTP重定向?qū)?dǎo)致將原始請求(重定向之前的URL)分配給重定向響應(yīng)(重定向后具有最終URL)。
Response.request.url并不總是等于Response.url
此屬性僅在爬蟲程序代碼和 Spider Middleware中可用既鞠,但不能在Downloader Middleware中使用(盡管您有通過其他方式可用的請求)和處理程序response_downloaded煤傍。
meta
的快捷方式Request.meta的屬性 Response.request對象(即self.request.meta)。
與Response.request屬性不同嘱蛋,Response.meta 屬性沿重定向和重試傳播蚯姆,因此您將獲得Request.meta從您的爬蟲發(fā)送的原始屬性五续。
也可以看看
Request.meta 屬性
flags
包含此響應(yīng)的標志的列表。標志是用于標記響應(yīng)的標簽龄恋。例如:'cached'疙驾,'redirected '等等。它們顯示在Response(__ str__ 方法)的字符串表示上郭毕,它被引擎用于日志記錄它碎。
copy()
返回一個新的響應(yīng),它是此響應(yīng)的副本显押。
replace([ url扳肛,status,headers挖息,body,request,flags,cls ] )
返回具有相同成員的Response對象咕娄,但通過指定的任何關(guān)鍵字參數(shù)賦予新值的成員除外费变。該屬性Response.meta是默認復(fù)制滑负。
urljoin(url )
通過將響應(yīng)url與可能的相對URL 組合構(gòu)造絕對url凡傅。
這是一個包裝在urlparse.urljoin槽华,它只是一個別名,使這個調(diào)用:
urlparse.urljoin(response.url, url)
響應(yīng)子類
這里是可用的內(nèi)置Response子類的列表义辕。您還可以將Response類子類化以實現(xiàn)您自己的功能虾标。
TextResponse對象
class scrapy.http.TextResponse(url[, encoding[, ...]])
TextResponse對象向基Response類添加編碼能力 ,這意味著僅用于二進制數(shù)據(jù)灌砖,例如圖像璧函,聲音或任何媒體文件。
TextResponse對象支持一個新的構(gòu)造函數(shù)參數(shù)基显,除了基礎(chǔ)Response對象蘸吓。其余的功能與Response類相同,這里沒有記錄撩幽。
參數(shù): encoding(string) - 是一個字符串库继,包含用于此響應(yīng)的編碼。如果你創(chuàng)建一個TextResponse具有unicode主體的對象窜醉,它將使用這個編碼進行編碼(記住body屬性總是一個字符串)制跟。如果encoding是None(默認值),則將在響應(yīng)標頭和正文中查找編碼酱虎。
TextResponse除了標準對象之外雨膨,對象還支持以下屬性Response
text
響應(yīng)體,如unicode读串。
同樣response.body.decode(response.encoding)
聊记,但結(jié)果是在第一次調(diào)用后緩存撒妈,因此您可以訪問 response.text
多次,無需額外的開銷排监。
注意
unicode(response.body)不是一個正確的方法來將響應(yīng)身體轉(zhuǎn)換為unicode:您將使用系統(tǒng)默認編碼(通常為ascii)而不是響應(yīng)編碼狰右。
encoding
包含此響應(yīng)的編碼的字符串。編碼通過嘗試以下機制按順序解決:
- 在構(gòu)造函數(shù)編碼參數(shù)中傳遞的編碼
- 在Content-Type HTTP頭中聲明的編碼舆床。如果此編碼無效(即未知)棋蚌,則會被忽略,并嘗試下一個解析機制挨队。
- 在響應(yīng)主體中聲明的編碼谷暮。TextResponse類不提供任何特殊功能。然而盛垦, HtmlResponse和XmlResponse類做湿弦。
- 通過查看響應(yīng)體來推斷的編碼。這是更脆弱的方法腾夯,但也是最后一個嘗試颊埃。
selector
一個Selector使用響應(yīng)為目標實例。選擇器在第一次訪問時被延遲實例化蝶俱。
TextResponse對象除了標準對象外還支持以下方法Response:
xpath(查詢)
快捷方式TextResponse.selector.xpath(query)
:
response.xpath('//p')
css(query)
快捷方式 TextResponse.selector.css(query)
:
response.css('p')
body_as_unicode()
同樣text班利,但可用作方法。保留此方法以實現(xiàn)向后兼容; 請喜歡response.text榨呆。
HtmlResponse對象
class scrapy.http.HtmlResponse(url [肥败,... ] )
本HtmlResponse類的子類,TextResponse 這增加了通過查看HTML編碼自動發(fā)現(xiàn)支持META HTTP-EQUIV屬性愕提。見TextResponse.encoding。
XmlResponse對象
class scrapy.http.XmlResponse(url [皿哨,... ] )
本XmlResponse類的子類浅侨,TextResponse這增加了通過查看XML聲明線路編碼自動發(fā)現(xiàn)支持。見TextResponse.encoding证膨。