scrapy學習筆記(二)框架結構工做原理

scrapy結構圖:

scrapy組件:

  • ENGINE:引擎,框架的核心,其它全部組件在其控制下協同工做。
  • SCHEDULER:調度器,負責對SPIDER提交的下載請求進行調度。
  • DOWNLOADER:下載器,負責下載頁面(發送HTTP請求/接收HTTP響應)。
  • SPIDER:爬蟲,負責提取頁面中的數據,併產生對新頁面的下載請求。
  • MIDDLEWARE:中間件,負責對Request對象和Response對象進行處理。
  • ITEM PIPELINE:數據管道,負責對爬取到的數據進行處理。

對於用戶來講,Spider是最核心的組件,Scrapy爬蟲開發是圍繞實現Spider展開的。css

框架中的數據流:

  • REQUEST:scrapy中的HTTP請求對象。
  • RESPONSE:scrapy中的HTTP響應對象。
  • ITEM:從頁面中爬取的一項數據。

Request和Response是HTTP協議中的術語,即HTTP請求和HTTP響應,Scrapy框架中定義了相應的Request和Response類,這裏的Item表明Spider從頁面中爬取的一項數據。html

scrapy大體工做流程:

  1. 當SPIDER要爬取某URL地址的頁面時,需使用該URL構造一個Request對象,提交給ENGINE。
  2. ENGINE將Request對象傳給SCHEDULER,SCHEDULER對URL進行去重,按某種算法進行排隊,以後的某個時刻SCHEDULER將其出隊,將處理好的Request對象返回給ENGINE。
  3. ENGINESCHEDULER處理後的Request對象發送給DOWNLOADER下載頁面。
  4. DOWNLOADER根據MIDDLEWARE的規則,使用Request對象中的URL地址發送一次HTTP請求到網站服務器,以後用服務器返回的HTTP響應構造出一個Response對象,其中包含頁面的HTML文本。DOWNLOADER將結果Resopnse對象傳給ENGINE
  5. ENGINE將Response對象發送給SPIDER的頁面解析函數(構造Request對象時指定)進行處理,頁面解析函數從頁面中提取數據,封裝成Item後提交給ENGINE。
  6. ENGINE將Item送往ITEMPIPELINES進行處理,最終以某種數據格式寫入文件(csv,json)或者存儲到數據庫中。

整個流程的核心都是圍繞着ENGINE進行的。

Request對象

Request對象用來描述一個HTTP請求,下面是其構造器方法的參數列表。算法

Request(url, callback=None, method='GET', headers=None, body=None,
                 cookies=None, meta=None, encoding='utf-8', priority=0,
                 dont_filter=False, errback=None, flags=None)

# url(必選):請求頁面的url地址,bytes或str類型,如'http://www.baidu.com'。
# callback:頁面解析函數, Callable類型,Request對象請求的頁面下載完成後,由該參數指定的頁面解析函數被調用。若是未傳遞該參數,默認調用Spider的parse方法。
# method:HTTP請求的方法,默認爲'GET'。
# headers:HTTP請求的頭部字典,dict類型,例如{'Accept':'text/html', 'User-Agent':Mozilla/5.0'}。若是其中某項的值爲None,就表示不發送該項HTTP頭部,例如{'Cookie':None},禁止發送Cookie。
# body:HTTP請求的正文,bytes或str類型。
# cookies:Cookie信息字典,dict類型,例如{'currency':  'USD','country': 'UY'}。
# meta:Request的元數據字典,dict類型,用於給框架中其餘組件傳遞信息,好比中間件Item  Pipeline。其餘組件可使用Request對象的meta屬性訪問該元數據字典(request.meta),也用於給響應處理函數傳遞信息,
# 詳見Response的meta屬性。
# encoding:url和body參數的編碼默認爲'utf-8'。若是傳入的url或body參數是str類型,就使用該參數進行編碼。 # priority:請求的優先級默認值爲0,優先級高的請求優先下載。 # dont_filter:默認狀況下(dont_filter=False),對同一個url地址屢次提交下載請求,後面的請求會被去重過濾器過濾(避免重複下載)。若是將該參數置爲True,可使請求避免被過濾,強制下載。例如,在屢次爬取
# 一個內容隨時間而變化的頁面時(每次使用相同的url),能夠將該參數置爲True。
# errback:請求出現異常或者出現HTTP錯誤時(如404頁面不存在)的回調函數。

雖然參數不少,但除了url參數外,其餘都帶有默認值。在構造Request對象時,一般咱們只需傳遞一個url參數或再加一個callback參數,其餘使用默認值便可。數據庫

Response對象:

Response對象用來描述一個HTTP響應,Response只是一個基類,根據響應內容的不一樣有以下子類:json

  • TextResponse
  • HtmlResponse
  • XmlResponse

當一個頁面下載完成時,下載器依據HTTP響應頭部中的Content-Type信息建立某個Response的子類對象。咱們一般爬取的網頁,其內容是HTML文本,建立的即是HtmlResponse對象,其中HtmlResponse和XmlResponse是TextResponse的子類。實際上,這3個子類只有細微的差異,這裏以HtmlResponse爲例進行講解。服務器

下面是HtmlResponse對象的屬性及方法。cookie

url:HTTP響應的url地址,str類型。
status:HTTP響應的狀態碼,int類型,例如200,404。
headers:HTTP響應的頭頭部,類字典類型,能夠調用get或getlist方法對其進行訪問,例如:response.headers.get('Content-Type')  response.headers.getlist('Set-Cookie')
body:HTTP響應正文,bytes類型。
text:文本形式的HTTP響應正文,str類型,它是由response.body使用response.encoding解碼獲得的,即reponse.text = response.body.decode(response.encoding)
encoding:HTTP響應正文的編碼,它的值多是從HTTP響應頭部或正文中解析出來的。
request:產生該HTTP響應的Request對象。
meta:即response.request.meta,在構造Request對象時,可將要傳遞給響應處理函數的信息經過meta參數傳入;響應處理函數處理響應時,經過response.meta將信息取出。
selector:Selector對象用於在Response中提取數據。
xpath(query):使用XPath選擇器在Response中提取數據,實際上它是response.selector.xpath方法的快捷方式。
css(query):使用CSS選擇器在Response中提取數據,實際上它是response.selector.css方法的快捷方式。
urljoin(url):用於構造絕對url。當傳入的url參數是一個相對地址時,根據response.url計算出相應的絕對url。例如:

response.url爲http://www.example.com/a,url爲b/index.html,調用response.urljoin(url)的結果爲http://www.example.com/a/b/index.html。

雖然HtmlResponse對象有不少屬性,但最經常使用的是如下的3個方法:框架

  • xpath(query)
  • css(query)
  • urljoin(url)

前兩個方法用於提取數據,後一個方法用於構造絕對url。scrapy

spied開發流程

實現一個Spider子類的過程很像是完成一系列填空題,Scrapy框架提出如下問題讓用戶在Spider子類中做答:ide

  • 爬蟲從哪一個或哪些頁面開始爬取?
  • 對於一個已下載的頁面,提取其中的哪些數據?
  • 爬取完當前頁面後,接下來爬取哪一個或哪些頁面?

實現一個Spider只須要完成下面4個步驟:

  • 繼承scrapy.Spider。
  • 爲Spider取名。
  • 設定起始爬取點。
  • 實現頁面解析函數。

scrapy.Spider基類實現瞭如下內容:

  • 供Scrapy引擎調用的接口,例如用來建立Spider實例的類方法from_crawler。
  • 供用戶使用的實用工具函數,例如能夠調用log方法將調試信息輸出到日誌。
  • 供用戶訪問的屬性,例如能夠經過settings屬性訪問配置文件中的配置。

 關於起始URL start_urls:

start_urls一般被實現成一個列表,其中放入全部起始爬取點的url(例子中只有一個起始點)。看到這裏,你們可能會想,請求頁面下載不是必定要提交Request對象麼?而咱們僅定義了url列表,是誰
暗中構造並提交了相應的Request對象呢?

  1. 咱們將起始URL提交給ENGINE。
  2. ENGINE調用start_requests方法,咱們沒有實現整個方法,因此調用了基類的start_requests方法。
  3. 經過閱讀Spider基類的源碼能夠看到以下內容:
  4. 基類的start_requests將咱們的URL封裝成Request對象。

由此咱們知道Request對象是調用基類start_requests方法產生的,所以咱們也能夠本身定義start_requests方法(覆蓋基類Spider的start_requests方法),直接構造並提交起始爬取點的Request對象。在某些場景下使用這種方式更加靈活,例若有時想爲Request添加特定的HTTP請求頭部,或想爲Request指定特定的頁面解析函數。

頁面解析函數parse:

頁面解析函數也就是構造Request對象時經過callback參數指定的回調函數(或默認的parse方法)。頁面解析函數是實現Spider中最核心的部分,它須要完成如下兩項工做:

  • 使用選擇器提取頁面中的數據,將數據封裝後(Item或字典)提交給Scrapy引擎。
  • 使用選擇器或LinkExtractor提取頁面中的連接,用其構造新的Request對象並提交給Scrapy引擎(下載連接頁面)。

一個頁面中可能包含多項數據以及多個連接,所以頁面解析函數被要求返回一個可迭代對象(一般被實現成一個生成器函數),每次迭代返回一項數據(Item或字典)或一個Request對象。

內容小結:

  • 瞭解scrapy的六個組件的功能。
  • 理解scrapy工做流程。
相關文章
相關標籤/搜索