這是scrapy爬蟲架構的第一篇,本系列專題将包含以下内容:
介紹scrapy架構的主體以及各個元件的意義;
舉執行個體講解其具體應用。
開始第一節: 介紹scrapy架構的主體以及各個元件的意義。
scrapy是一個為了爬取網站資料,提取結構性資料而編寫的應用架構。 可以應用在包括資料挖掘,資訊處理或存儲曆史資料等一系列的程式中。
其最初是為了 頁面抓取 (更确切來說, 網絡抓取 )所設計的, 也可以應用在擷取api所傳回的資料(例如 amazon associates web services ) 或者通用的網絡爬蟲。
安裝scrapy需要一些依賴:
python
python package: pip and setuptools. 現在 pip 依賴 setuptools ,如果未安裝,則會自動安裝setuptools 。
lxml. 大多數linux發行版自帶了lxml。如果缺失,請檢視 installing lxml
openssl. 除了windows(請檢視 平台安裝指南)之外的系統都已經提供。
當安裝好這些依賴之後,隻需要運作pip install scrapy,即可安裝完scrapy。
然後運作:
scrapy startproject tutorial
即可自動建立官方标準的代碼目錄。
tutorial/
scrapy.cfg
tutorial/
__init__.py
items.py
pipelines.py
settings.py
spiders/
__init__.py
...
其中:
tutorial/: 該項目的python總子產品。
tutorial/items.py: 項目中的item檔案,編寫爬取的字段名稱等;
tutorial/pipelines.py: 項目中的pipelines檔案;
tutorial/settings.py: 項目的設定檔案,較為重要;
tutorial/spiders/: 放置spider代碼的主目錄;
scrapy整體架構神圖:
scrapy中的資料流由執行引擎控制,其過程如下:
引擎打開一個網站(open a domain),找到處理該網站的spider并向該spider請求第一個要爬取的url(s)。
引擎從spider中擷取到第一個要爬取的url并在排程器(scheduler)以request排程。
引擎向排程器請求下一個要爬取的url。
排程器傳回下一個要爬取的url給引擎,引擎将url通過下載下傳中間件(請求(request)方向)轉發給下載下傳器(downloader)。
一旦頁面下載下傳完畢,下載下傳器生成一個該頁面的response,并将其通過下載下傳中間件(傳回(response)方向)發送給引擎。
引擎從下載下傳器中接收到response并通過spider中間件(輸入方向)發送給spider處理。
spider處理response并傳回爬取到的item及(跟進的)新的request給引擎。
引擎将(spider傳回的)爬取到的item給item pipeline,将(spider傳回的)request給排程器。
(從第二步)重複直到排程器中沒有更多地request,引擎關閉該網站。
以上是老生常談,下面談一些經驗:
如果需要大批量分布式爬取,建議采用redis資料庫存儲,可安裝scrapy-redis,使用redis資料庫來替換scrapy原本使用的隊列結構(deque),并配合其它資料庫存儲,例如mysql或者mongodb,爬取效率将會極大提高。并且其自帶的dupefilter.py負責執行requst的去重,使用redis的set資料結構,通過settings檔案正确設定後,即便停止scrapy爬蟲,當下次重新開始後也能自動去重。原因就是在redis已經存儲了request的資訊。
當涉及到代理ip,headers頭中間請求資訊處理的時候,可以通過中間件middleware來實作。spider中間件是介入到scrapy的spider處理機制的鈎子架構,可以添加代碼來處理發送給 spiders的response及spider産生的item和request。
合理設定settings檔案,需要熟練掌握 settings 的各種設定。
可以重新定義def start_requests(self)函數來加載cookie資訊,form資訊的送出用scrapy.formrequest以及scrapy.formrequest.from_response這兩個函數,scrapy.formrequest.from_response能實作自動送出form資料。
采用scrapy+phantomjs,。 downloadmiddleware 對從 scheduler 送來的 request 對象在請求之前進行預處理,可以實作添加 headers, user_agent,還有 cookie 等功能 。但也可以通過中間件直接傳回 htmlresponse 對象,略過請求的子產品,直接扔給 response 的回調函數處理。
class custommetamiddleware(object):
def process_request(self,request,spider):
dcap = dict(desiredcapabilities.phantomjs)
dcap["phantomjs.page.settings.loadimages"] = false
dcap["phantomjs.page.settings.resourcetimeout"] = 10
driver = webdriver.phantomjs("d:xx\xx",desired_capabilities=dcap)
driver.get(request.url)
body = driver.page_source.encode('utf8')
url = driver.current_url
driver.quit()
return htmlresponse(request.url,body=body)
綜上,是對scrapy的各個元件一些個人的經驗總結。
本文作者:蚍蜉撼大樹
來源:51cto