Python下開源爬蟲(spider)框架scrapy的使用

jopen 10年前發布 | 167K 次閱讀 網絡爬蟲 Scrapy

主機環境:Ubuntu 13.04

Python版本:2.7.4
——————————————————————————————————————————————————-

所謂網絡爬蟲,就是一個在網上到處或定向抓取數據的程序,當然,這種說法不夠專業,更專業的描述就是,抓取特定網站網頁的HTML數據。不過由于一個網站的網頁很多,而我們又不可能事先知道所有網頁的URL地址,所以,如何保證我們抓取到了網站的所有HTML頁面就是一個有待考究的問題了。
一般的方法是,定義一個入口頁面,然后一般一個頁面會有其他頁面的URL,于是從當前頁面獲取到這些URL加入到爬蟲的抓取隊列中,然后進入到新新頁面后再遞歸的進行上述的操作,其實說來就跟深度遍歷或廣度遍歷一樣。
上面介紹的只是爬蟲的一些概念而非搜索引擎,實際上搜索引擎的話其系統是相當復雜的,爬蟲只是搜索引擎的一個子系統而已。

Python 開源的爬蟲框架Scrapy是一個快速,高層次的屏幕抓取和web抓取框架,用于抓取web站點并從頁面中提取結構化的數據。Scrapy用途廣泛,可以用于數據挖掘、監測和自動化測試。Scrapy吸引人的地方在于它是一個框架,任何人都可以根據需求方便的修改。它也提供了多種類型爬蟲的基類,如 BaseSpider、sitemap爬蟲等,最新版本又提供了web2.0爬蟲的支持。

一、概述

Scrapy是一個用 Python 寫的 Crawler Framework ,簡單輕巧,并且非常方便,并且官網上說已經在實際生產中在使用了,不過現在還沒有 Release 版本,可以直接使用他們的 Mercurial 倉庫里抓取源碼進行安裝。
Scrapy 使用 Twisted 這個異步網絡庫來處理網絡通訊,架構清晰,并且包含了各種中間件接口,可以靈活的完成各種需求。
Scrapy整體架構如下圖所示,其中包含了它的主要組件及系統的數據處理流程(綠色箭頭所示)。下面就來一個個解釋每個組件的作用及數據的處理過程。

scrapy_architecture.png

綠線是數據流向,首先從初始 URL 開始,Scheduler 會將其交給 Downloader 進行下載,下載之后會交給 Spider 進行分析,Spider 分析出來的結果有兩種:一種是需要進一步抓取的鏈接,例如之前分析的“下一頁”的鏈接,這些東西會被傳回 Scheduler ;另一種是需要保存的數據,它們則被送到 Item Pipeline 那里,那是對數據進行后期處理(詳細分析、過濾、存儲等)的地方。另外,在數據流動的通道里還可以安裝各種中間件,進行必要的處理。

二、組件

1、Scrapy Engine(Scrapy引擎)

Scrapy引擎是用來控制整個系統的數據處理流程,并進行事務處理的觸發。更多的詳細內容可以看下面的數據處理流程。

2、Scheduler(調度)

調度程序從Scrapy引擎接受請求并排序列入隊列,并在Scrapy引擎發出請求后返還給他們。

3、Downloader(下載器)

下載器的主要職責是抓取網頁并將網頁內容返還給蜘蛛( Spiders)。

4、Spiders(蜘蛛)

蜘蛛是有Scrapy用戶自己定義用來解析網頁并抓取制定URL返回的內容的類,每個蜘蛛都能處理一個域名或一組域名。換句話說就是用來定義特定網站的抓取和解析規則。

蜘蛛的整個抓取流程(周期)是這樣的:

  1. 首先獲取第一個URL的初始請求,當請求返回后調取一個回調函數。第一個請求是通過調用start_requests()方法。該方法默認從start_urls中的Url中生成請求,并執行解析來調用回調函數。
  2. 在回調函數中,你可以解析網頁響應并返回項目對象和請求對象或兩者的迭代。這些請求也將包含一個回調,然后被Scrapy下載,然后有指定的回調處理。
  3. 在回調函數中,你解析網站的內容,同程使用的是Xpath選擇器(但是你也可以使用BeautifuSoup, lxml或其他任何你喜歡的程序),并生成解析的數據項。
  4. 最后,從蜘蛛返回的項目通常會進駐到項目管道。

5、Item Pipeline(項目管道)

項目管道的主要責任是負責處理有蜘蛛從網頁中抽取的項目,他的主要任務是清晰、驗證和存儲數據。當頁面被蜘蛛解析后,將被發送到項目管道,并經過幾個特定的次序處理數據。每個項目管道的組件都是有一個簡單的方法組成的Python類。他們獲取了項目并執行他們的方法,同時他們還需要確定的是是否需要在項目管道中繼續執行下一步或是直接丟棄掉不處理。

項目管道通常執行的過程有:

  1. 清洗HTML數據
  2. 驗證解析到的數據(檢查項目是否包含必要的字段)
  3. 檢查是否是重復數據(如果重復就刪除)
  4. 將解析到的數據存儲到數據庫中

6、Downloader middlewares(下載器中間件)

下載中間件是位于Scrapy引擎和下載器之間的鉤子框架,主要是處理Scrapy引擎與下載器之間的請求及響應。它提供了一個自定義的代碼的方式來拓展 Scrapy的功能。下載中間器是一個處理請求和響應的鉤子框架。他是輕量級的,對Scrapy盡享全局控制的底層的系統。

7、Spider middlewares(蜘蛛中間件)

蜘蛛中間件是介于Scrapy引擎和蜘蛛之間的鉤子框架,主要工作是處理蜘蛛的響應輸入和請求輸出。它提供一個自定義代碼的方式來拓展Scrapy的功能。蛛中間件是一個掛接到Scrapy的蜘蛛處理機制的框架,你可以插入自定義的代碼來處理發送給蜘蛛的請求和返回蜘蛛獲取的響應內容和項目。

8、Scheduler middlewares(調度中間件)

調度中間件是介于Scrapy引擎和調度之間的中間件,主要工作是處從Scrapy引擎發送到調度的請求和響應。他提供了一個自定義的代碼來拓展Scrapy的功能。

三、數據處理流程

Scrapy的整個數據處理流程有Scrapy引擎進行控制,其主要的運行方式為:

  1. 引擎打開一個域名,時蜘蛛處理這個域名,并讓蜘蛛獲取第一個爬取的URL。
  2. 引擎從蜘蛛那獲取第一個需要爬取的URL,然后作為請求在調度中進行調度。
  3. 引擎從調度那獲取接下來進行爬取的頁面。
  4. 調度將下一個爬取的URL返回給引擎,引擎將他們通過下載中間件發送到下載器。
  5. 當網頁被下載器下載完成以后,響應內容通過下載中間件被發送到引擎。
  6. 引擎收到下載器的響應并將它通過蜘蛛中間件發送到蜘蛛進行處理。
  7. 蜘蛛處理響應并返回爬取到的項目,然后給引擎發送新的請求。
  8. 引擎將抓取到的項目項目管道,并向調度發送請求。
  9. 系統重復第二部后面的操作,直到調度中沒有請求,然后斷開引擎與域之間的聯系。

四、驅動器

Scrapy是由 Twisted 寫的一個受歡迎的Python事件驅動網絡框架,它使用的是非堵塞的異步處理。如果要獲得更多關于異步編程和Twisted的信息,請參考下面兩條鏈接。

參考文獻:http://doc. scrapy .org/topics/architecture.html

————————————————————————————————————————————

以上內容轉載自http://www.tuicool.com/articles/fiyIbq

也可以參考官方的文檔。

下面的實例實現的是爬取本博客的所有文章。

定制的爬蟲代碼:my_spider.py

01 #!/usr/bin/env python
02 #-*- coding:utf-8 -*-
03  
04 from scrapy.spider import BaseSpider
05 from scrapy.selector import HtmlXPathSelector
06  
07 from mymodules.items import Website
08  
09 class My_Spider(BaseSpider):
10     name = "my_spider"
11     allowed_domains = ["yanming8.cn"]
12     start_urls = [
13        "http://blog.yanming8.cn"
14     ]
15  
16     def parse(self, response):
17         hxs = HtmlXPathSelector(response)
18         blogs_url = hxs.select('//h2/a/@href').extract()
19         items = []
20         items.extend([self.make_requests_from_url(url).replace(callback=self.parse_post)
21                   for url in blogs_url])
22  
23         pages = hxs.select('//div[@class="loop-nav-previous grid_5 alpha"]/a[not(@title)]/@href').extract()
24         for next_page in pages:
25             items.append(self.make_requests_from_url(next_page))
26  
27         return items
28  
29     def parse_post(self, response):
30  
31         hxs = HtmlXPathSelector(response)
32  
33         item = Website()
34         item['url'= unicode(response.url)
35         item['name'= hxs.select('//h1[@class="entry-title entry-title-single"]/text()').extract()
36         item['description'= response.body_as_unicode()
37         print response.url,item['name']
38         return item

 

代碼中parse函數是用于獲取文章列表的,并將每一頁的文章地址加入list列表并返回,該函數是默認的回調函數。

代碼中parse_post函數是用于獲取每篇文章的具體內容。

然后會返回給pipeline進行處理,在這里可以進行索引內容的文件或者數據庫存儲。

來自:http://blog.yanming8.cn/archives/125

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!