Scrapy爬蟲入門教程十一 Request和Response(請求和響應)

NO IMAGE

Scrapy爬蟲入門教程一 安裝和基本使用 

Scrapy爬蟲入門教程二 官方提供Demo 

Scrapy爬蟲入門教程三 命令列工具介紹和示例 

Scrapy爬蟲入門教程四 Spider(爬蟲) 

Scrapy爬蟲入門教程五 Selectors(選擇器) 

Scrapy爬蟲入門教程六 Items(專案) 

Scrapy爬蟲入門教程七 Item Loaders(專案載入器) 

Scrapy爬蟲入門教程八 互動式 shell 方便除錯 

Scrapy爬蟲入門教程九 Item Pipeline(專案管道) 

Scrapy爬蟲入門教程十 Feed exports(匯出檔案) 

Scrapy爬蟲入門教程十一 Request和Response(請求和響應) 

Scrapy爬蟲入門教程十二 Link Extractors(連結提取器)

Scrapy爬蟲入門教程十三 Settings(設定)

 

開發環境: 
Python 3.6.0 版本 (當前最新) 
Scrapy 1.3.2 版本 (當前最新)

 

目錄

請求和響應

Request objects

將附加資料傳遞給回撥函式

使用errbacks在請求處理中捕獲異常

Request.meta特殊鍵

請求子類

請求使用示例

響應物件

響應子類


 

請求和響應

Scrapy的Request和Response物件用於爬網網站。

通常,Request物件在爬蟲程式中生成並傳遞到系統,直到它們到達下載程式,後者執行請求並返回一個Response物件,該物件返回到發出請求的爬蟲程式。

上面一段話比較拗口,有web經驗的同學,應該都瞭解的,不明白看下面的圖大概理解下。

爬蟲爬蟲RequestRequestResponseResponse建立獲取下載資料資料

兩個類Request和Response類都有一些子類,它們新增基類中不需要的功能。這些在下面的請求子類和 響應子類中描述。


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請求,它通常是在爬蟲生成,並由下載執行,從而生成Response。

  • 引數:

    • url(string) – 此請求的網址
    • callback(callable) – 將使用此請求的響應(一旦下載)作為其第一個引數呼叫的函式。有關更多資訊,請參閱下面的將附加資料傳遞給回撥函式。如果請求沒有指定回撥,parse()將使用spider的 方法。請注意,如果在處理期間引發異常,則會呼叫errback。
    • method(string) – 此請求的HTTP方法。預設為’GET’。
    • meta(dict) – 屬性的初始值Request.meta。如果給定,在此引數中傳遞的dict將被淺複製。
    • body(str或unicode) – 請求體。如果unicode傳遞了a,那麼它被編碼為 str使用傳遞的編碼(預設為utf-8)。如果 body沒有給出,則儲存一個空字串。不管這個引數的型別,儲存的最終值將是一個str(不會是unicode或None)。
    • headers(dict) – 這個請求的頭。dict值可以是字串(對於單值標頭)或列表(對於多值標頭)。如果 None作為值傳遞,則不會傳送HTTP頭。
    • cookie(dict或list) – 請求cookie。這些可以以兩種形式傳送。

      • 使用dict:
      request_with_cookies = Request(url="http://www.example.com",
      cookies={'currency': 'USD', 'country': 'UY'})
      • 1
      • 2
      • 使用列表:
      request_with_cookies = Request(url="http://www.example.com",
      cookies=[{'name': 'currency',
      'value': 'USD',
      'domain': 'example.com',
      'path': '/currency'}])

後一種形式允許定製 cookie的屬性domain和path屬性。這只有在儲存Cookie用於以後的請求時才有用。

當某些網站返回Cookie(在響應中)時,這些Cookie會儲存在該域的Cookie中,並在將來的請求中再次傳送。這是任何常規網路瀏覽器的典型行為。但是,如果由於某種原因,您想要避免與現有Cookie合併,您可以通過將dont_merge_cookies關鍵字設定為True 來指示Scrapy如此操作 Request.meta。

不合並Cookie的請求示例:

request_with_cookies = Request(url="http://www.example.com",
cookies={'currency': 'USD', 'country': 'UY'},
meta={'dont_merge_cookies': True})

有關詳細資訊,請參閱CookiesMiddleware

  • encoding(string) – 此請求的編碼(預設為’utf-8’)。此編碼將用於對URL進行百分比編碼,並將正文轉換為str(如果給定unicode)。
  • priority(int) – 此請求的優先順序(預設為0)。排程器使用優先順序來定義用於處理請求的順序。具有較高優先順序值的請求將較早執行。允許負值以指示相對低優先順序。
  • dont_filter(boolean) – 表示此請求不應由排程程式過濾。當您想要多次執行相同的請求時忽略重複過濾器時使用。小心使用它,或者你會進入爬行迴圈。預設為False。
  • errback(callable) – 如果在處理請求時引發任何異常,將呼叫的函式。這包括失敗的404 HTTP錯誤等頁面。它接收一個Twisted Failure例項作為第一個引數。有關更多資訊,請參閱使用errbacks在請求處理捕獲異常

  • url 
    包含此請求的網址的字串。請記住,此屬性包含轉義的網址,因此它可能與建構函式中傳遞的網址不同。

此屬性為只讀。更改請求使用的URL replace()

  • method 
    表示請求中的HTTP方法的字串。這保證是大寫的。例如:"GET","POST","PUT"

  • headers 
    包含請求標頭的類似字典的物件。

  • body 
    包含請求正文的str。

此屬性為只讀。更改請求使用的正文 replace()

  • meta 
    包含此請求的任意後設資料的字典。此dict對於新請求為空,通常由不同的Scrapy元件(擴充套件程式,中介軟體等)填充。因此,此dict中包含的資料取決於您啟用的擴充套件。

有關Scrapy識別的特殊元鍵列表,請參閱Request.meta特殊鍵

當使用or 方法克隆請求時,此dict是淺複製的 ,並且也可以在您的爬蟲中從屬性訪問。copy()replace()response.meta

  • copy() 
    返回一個新的請求,它是這個請求的副本。另請參見: 將附加資料傳遞到回撥函式

  • replace([url, method, headers, body, cookies, meta, encoding, dont_filter, callback, errback]) 
    返回具有相同成員的Request物件,但通過指定的任何關鍵字引數賦予新值的成員除外。該屬性Request.meta是預設複製(除非新的值在給定的meta引數)。另請參見 將附加資料傳遞給回撥函式

將附加資料傳遞給回撥函式

請求的回撥是當下載該請求的響應時將被呼叫的函式。將使用下載的Response物件作為其第一個引數來呼叫回撥函式。

例:

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)

在某些情況下,您可能有興趣向這些回撥函式傳遞引數,以便稍後在第二個回撥中接收引數。您可以使用該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是在處理異常時被呼叫的函式。

它接收一個Twisted Failure例項作為第一個引數,並可用於跟蹤連線建立超時,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屬性可以包含任何任意資料,但有一些特殊的鍵由Scrapy及其內建擴充套件識別。

那些是:

dont_redirect
dont_retry
handle_httpstatus_list
handle_httpstatus_all
dont_merge_cookies(參見cookies建構函式的Request引數)
cookiejar
dont_cache
redirect_urls
bindaddress
dont_obey_robotstxt
download_timeout
download_maxsize
download_latency
proxy

bindaddress

用於執行請求的出站IP地址的IP。

download_timeout

下載器在超時前等待的時間量(以秒為單位)。參見:DOWNLOAD_TIMEOUT

download_latency

自請求已啟動以來,用於獲取響應的時間量,即通過網路傳送的HTTP訊息。此元鍵僅在響應已下載時可用。雖然大多數其他元鍵用於控制Scrapy行為,但這應該是隻讀的。

請求子類

這裡是內建子類的Request列表。您還可以將其子類化以實現您自己的自定義功能。

FormRequest物件 
FormRequest類擴充套件了Request具有處理HTML表單的功能的基礎。它使用lxml.html表單 從Response物件的表單資料預填充表單欄位。

class scrapy.http.FormRequest(url[, formdata, ...])

FormRequest類增加了新的建構函式的引數。其餘的引數與Request類相同,這裡沒有記錄。

  • 引數:formdata(元組的dict或iterable) – 是一個包含HTML Form資料的字典(或(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物件,其中的表單欄位值已預先<form>填充在給定響應中包含的HTML 元素中。有關示例,請參閱 使用FormRequest.from_response()來模擬使用者登入

該策略是在任何可檢視的表單控制元件上預設自動模擬點選,如a 。即使這是相當方便,並且經常想要的行為,有時它可能導致難以除錯的問題。例如,當使用使用javascript填充和/或提交的表單時,預設行為可能不是最合適的。要禁用此行為,您可以將引數設定 為。此外,如果要更改單擊的控制元件(而不是禁用它),您還可以使用 引數。<input type="submit"> from_response() dont_click True clickdata

引數:

  • response(Responseobject) – 包含將用於預填充表單欄位的HTML表單的響應
  • formname(string) – 如果給定,將使用name屬性設定為此值的形式。
  • formid(string) – 如果給定,將使用id屬性設定為此值的形式。
  • formxpath(string) – 如果給定,將使用匹配xpath的第一個表單。
  • formcss(string) – 如果給定,將使用匹配css選擇器的第一個形式。
  • formnumber(integer) – 當響應包含多個表單時要使用的表單的數量。第一個(也是預設)是0。
  • formdata(dict) – 要在表單資料中覆蓋的欄位。如果響應元素中已存在欄位,則其值將被在此引數中傳遞的值覆蓋。
  • clickdata(dict) – 查詢控制元件被點選的屬性。如果沒有提供,表單資料將被提交,模擬第一個可點選元素的點選。除了html屬性,控制元件可以通過其相對於表單中其他提交表輸入的基於零的索引,通過nr屬性來標識。
  • dont_click(boolean) – 如果為True,表單資料將在不點選任何元素的情況下提交。

這個類方法的其他引數直接傳遞給 FormRequest建構函式。 
在新版本0.10.3:該formname引數。 
在新版本0.17:該formxpath引數。 
新的版本1.1.0:該formcss引數。 
新的版本1.1.0:該formid引數。


 

請求使用示例

使用FormRequest通過HTTP POST傳送資料

如果你想在你的爬蟲中模擬HTML表單POST併傳送幾個鍵值欄位,你可以返回一個FormRequest物件(從你的爬蟲)像這樣:

return [FormRequest(url="http://www.example.com/post/action",
formdata={'name': 'John Doe', 'age': '27'},
callback=self.after_post)]

使用FormRequest.from_response()來模擬使用者登入

網站通常通過元素(例如會話相關資料或認證令牌(用於登入頁面))提供預填充的表單欄位。進行剪貼時,您需要自動預填充這些欄位,並且只覆蓋其中的一些,例如使用者名稱和密碼。您可以使用 此作業的方法。這裡有一個使用它的爬蟲示例:<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...

響應物件

class scrapy.http.Response(url[, status=200, headers=None, body=b'', flags=None, request=None]) 
一個Response物件表示的HTTP響應,這通常是下載(由下載),並供給到爬蟲進行處理。

引數:

  • url(string) – 此響應的URL
  • status(integer) – 響應的HTTP狀態。預設為200
  • headers(dict) – 這個響應的頭。dict值可以是字串(對於單值標頭)或列表(對於多值標頭)。
  • body(str) – 響應體。它必須是str,而不是unicode,除非你使用一個編碼感知響應子類,如 TextResponse
  • flags(list) – 是一個包含屬性初始值的 Response.flags列表。如果給定,列表將被淺複製。
  • request(Requestobject) – 屬性的初始值Response.request。這代表Request生成此響應。

url 
包含響應的URL的字串。

此屬性為只讀。更改響應使用的URL replace()。

status 
表示響應的HTTP狀態的整數。示例:200, 404。

headers 
包含響應標題的類字典物件。可以使用get()返回具有指定名稱的第一個標頭值或getlist()返回具有指定名稱的所有標頭值來訪問值。例如,此呼叫會為您提供標題中的所有Cookie:

response.headers.getlist('Set-Cookie')

body 
本回復的正文。記住Response.body總是一個位元組物件。如果你想unicode版本使用 TextResponse.text(只在TextResponse 和子類中可用)。

此屬性為只讀。更改響應使用的主體 replace()。

request 
Request生成此響應的物件。在響應和請求通過所有下載中介軟體後,此屬性在Scrapy引擎中分配。特別地,這意味著:

HTTP重定向將導致將原始請求(重定向之前的URL)分配給重定向響應(重定向後具有最終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從您的爬蟲傳送的原始屬性。

也可以看看

Request.meta 屬性

flags 
包含此響應的標誌的列表。標誌是用於標記響應的標籤。例如:’cached’,’redirected ‘等等。它們顯示在Response(_ str_ 方法)的字串表示上,它被引擎用於日誌記錄。

copy() 
返回一個新的響應,它是此響應的副本。

replace([ url,status,headers,body,request,flags,cls ] ) 
返回具有相同成員的Response物件,但通過指定的任何關鍵字引數賦予新值的成員除外。該屬性Response.meta是預設複製。

urljoin(url ) 
通過將響應url與可能的相對URL 組合構造絕對url。

這是一個包裝在urlparse.urljoin,它只是一個別名,使這個呼叫:

urlparse.urljoin(response.url, url)

 

響應子類

這裡是可用的內建Response子類的列表。您還可以將Response類子類化以實現您自己的功能。

TextResponse物件

class scrapy.http.TextResponse(url[, encoding[, ...]])

TextResponse物件向基Response類新增編碼能力 ,這意味著僅用於二進位制資料,例如影象,聲音或任何媒體檔案。

TextResponse物件支援一個新的建構函式引數,除了基礎Response物件。其餘的功能與Response類相同,這裡沒有記錄。

引數: encoding(string) – 是一個字串,包含用於此響應的編碼。如果你建立一個TextResponse具有unicode主體的物件,它將使用這個編碼進行編碼(記住body屬性總是一個字串)。如果encoding是None(預設值),則將在響應標頭和正文中查詢編碼。 
TextResponse除了標準物件之外,物件還支援以下屬性Response

text 
響應體,如unicode。

同樣response.body.decode(response.encoding),但結果是在第一次呼叫後快取,因此您可以訪問 response.text多次,無需額外的開銷。

注意 
unicode(response.body)不是一個正確的方法來將響應身體轉換為unicode:您將使用系統預設編碼(通常為ascii)而不是響應編碼。

encoding 
包含此響應的編碼的字串。編碼通過嘗試以下機制按順序解決:

  1. 在建構函式編碼引數中傳遞的編碼
  2. 在Content-Type HTTP頭中宣告的編碼。如果此編碼無效(即未知),則會被忽略,並嘗試下一個解析機制。
  3. 在響應主體中宣告的編碼。TextResponse類不提供任何特殊功能。然而, HtmlResponse和XmlResponse類做。
  4. 通過檢視響應體來推斷的編碼。這是更脆弱的方法,但也是最後一個嘗試。

selector 
一個Selector使用響應為目標例項。選擇器在第一次訪問時被延遲例項化。

TextResponse物件除了標準物件外還支援以下方法Response:

xpath(查詢) 
快捷方式TextResponse.selector.xpath(query)

response.xpath('//p')

 

css(query) 
快捷方式 TextResponse.selector.css(query):

response.css('p')

 

body_as_unicode() 
同樣text,但可用作方法。保留此方法以實現向後相容; 請喜歡response.text。

HtmlResponse物件

class scrapy.http.HtmlResponse(url [,... ] ) 
本HtmlResponse類的子類,TextResponse 這增加了通過檢視HTML編碼自動發現支援META HTTP-EQUIV屬性。見TextResponse.encoding。

XmlResponse物件

class scrapy.http.XmlResponse(url [,... ] ) 
本XmlResponse類的子類,TextResponse這增加了通過檢視XML宣告線路編碼自動發現支援。見TextResponse.encoding。

 

轉載自:https://blog.csdn.net/inke88/article/details/61204180