跟我学系列,走进Scrapy爬虫(六)Spiders爬虫
本章工作任務
任務1:為什么要使用Spiders?
任務2:如何使用Spiders?
任務3:Spiders的擴展
本章技能目標及重難點
編號 技能點描述 級別
1 為什么要使用Spiders? ★
2 如何使用Spiders? ★★★
3 Spiders的擴展 ★★
注: "★"理解級別 "★★"掌握級別 "★★★"應用級別
本章學習目標
本章開始學習Scrapy的Spiders,需要同學們學會使用Spiders及相關擴展的Spiders應用。
本章學習建議
本章適合有Python爬蟲基礎的學員學習。
本章內容(學習活動)
6.1為什么要使用Spiders?
6.1.1Spider 介紹
Spider 類定義了如何爬取某個(或某些)網站。包括了爬取的動作(例如:是否跟進鏈接)以及如何從網頁的內容中提取結構化數據(爬取 item)。換句話說,Spider 就是您定義爬取的動作及分析某個網頁(或者是有些網頁)的地方。
對 spider 來說,爬取的循環類似下文:
1.以初始的 URL 初始化 Request,并設置回調函數。當該 request 下載完畢并返回時,將生成 response,并作為參數傳給該回調函數。
2.spider 中初始的 request 是通過調用 start_requests()來獲取的。start_requests()讀取 start_urls 中的 URL, 并以 parse 為回調函數生成 Request。
3.在回調函數內分析返回的(網頁)內容,返回 Item 對象或者 Request 或者一個包括二者的可迭代容器。 返回的 Request 對象之后會經過 Scrapy 處理,下載相應的內容,并調用設置的 callback 函數(函數可相同)。
4.在回調函數內,您可以使用 選擇器(Selectors) (您也可以使用 BeautifulSoup, lxml 或者您想用的任何解析器) 來分析網頁內容,并根據分析的數據生成 item。
5.最后,由 spider 返回的 item 將被存到數據庫(由某些 Item Pipeline 處理)或使用 Feed exports 存入到文件中。
雖然該循環對任何類型的 spider 都(多少)適用,但 Scrapy 仍然為了不同的需求提供了多種默認 spider。 之后將討論這些 spider。
6.1.2 創建Spider
Spider 可以通過接受參數來修改其功能。 spider 參數一般用來定義初始 URL 或者指定限制爬取網站的部分。 您也可以使用其來配置 spider 的任何功能。
在運行 crawl 時添加-a 可以傳遞 Spider 參數:
scrapy crawl myspider -a category=electronics
Spider 在構造器(constructor)中獲取參數,如圖6-1所示。
6-1 Spider參數
Spider 參數也可以通過 Scrapyd 的 schedule.json API 來傳遞。
6.2如何使用Spiders?
Scrapy 提供多種方便的通用 spider 供您繼承使用。 這些 spider 為一些常用的爬取情況提供方便的特性, 例如根據某些規則跟進某個網站的所有鏈接、根據 Sitemaps 來進行爬取,或者分析 XML/CSV 源。
下面 spider 的示例中,我們假定您有個項目在 myproject.items 模塊中聲明了 TestItem,如圖6-2所示。
6-2 TestItem
6.2.1Spider定義
class scrapy.spider.Spider
Spider 是最簡單的 spider。每個其他的 spider 必須繼承自該類(包括 Scrapy 自帶的其他 spider 以及您自己編寫的 spider)。Spider 并沒有提供什么特殊的功能。其僅僅請求給定的 start_urls/start_requests,并根據返回的結果(resulting responses)調用 spider 的 parse 方法。
1.參數
name
定義 spider 名字的字符串(string)。spider 的名字定義了 Scrapy 如何定位(并初始化)spider,所以其必須是唯一的。 不過您可以生成多個相同的 spider 實例(instance),這沒有任何限制。 name 是 spider 最重要的屬性,而且是必須的。
如果該 spider 爬取單個網站(single domain),一個常見的做法是以該網站(domain)(加或不加后綴)來命名 spider。 例如,如果 spider 爬取 mywebsite.com,該 spider 通常會被命名為 mywebsite 。
allowed_domains
可選。包含了 spider 允許爬取的域名(domain)列表(list)。 當 OffsiteMiddleware 啟用時, 域名不在列表中的 URL 不會被跟進。
start_urls
URL 列表。當沒有制定特定的 URL 時,spider 將從該列表中開始進行爬取。 因此,第一個被獲取到的頁面的 URL 將是該列表之一。后續的 URL 將會從獲取到的數據中提取。
2.方法
start_requests()
該方法必須返回一個可迭代對象(iterable)。該對象包含了 spider 用于爬取的第一個 Request。
當 spider 啟動爬取并且未制定 URL 時,該方法被調用。 當指定了 URL 時,make_requests_from_url()將被調用來創建 Request 對象。 該方法僅僅會被 Scrapy 調用一次,因此您可以將其實現為生成器。
該方法的默認實現是使用 start_urls 的 url 生成 Request。
如果您想要修改最初爬取某個網站的 Request 對象,您可以重寫(override)該方法。 例如,如果您需要在啟動時以 POST 登錄某個網站,你可以這么寫,如圖6-3所示。
6-3 start_requests
make_requests_from_url(url)
該方法接受一個 URL 并返回用于爬取的 Request 對象。該方法在初始化 request 時被 start_requests()調用,也被用于轉化 url 為 request。
默認未被復寫(overridden)的情況下,該方法返回的 Request 對象中,parse()作為回調函數,dont_filter 參數也被設置為開啟。(詳情參見 Request)。
parse(response)
當 response 沒有指定回調函數時,該方法是 Scrapy 處理下載的 response 的默認方法。
parse 負責處理 response 并返回處理的數據以及(/或)跟進的 URL。 Spider 對其他的 Request 的回調函數也有相同的要求。
該方法及其他的 Request 回調函數必須返回一個包含 Request 及(或) Item 的可迭代的對象。
參數:response (Response) – 用于分析的 response
log(message[, level, component])
使用 scrapy.log.msg() 方法記錄(log)message。log 中自動帶上該 spider 的 name 屬性。關于Logging我會在后面的爬蟲小技巧課程中做詳細講解。
closed(reason)
當 spider 關閉時,該函數被調用。 該方法提供了一個替代調用 signals.connect()來監聽 spider_closed 信號的快捷方式。
6.2.2 Spider樣例
讓我們來看一個例子,如圖6-4所示。
6-4 Spider樣例
另一個在單個回調函數中返回多個 Request 以及 Item 的例子,如圖6-5所示。
6-5 Spider樣例
6.2.3CrawlSpider
class scrapy.contrib.spiders.CrawlSpider
爬取一般網站常用的 spider。其定義了一些規則(rule)來提供跟進 link 的方便的機制。 也許該 spider 并不是完全適合您的特定網站或項目,但其對很多情況都使用。因此您可以以其為起點,根據需求修改部分方法。當然您也可以實現自己的 spider。
除了從 Spider 繼承過來的(您必須提供的)屬性外,其提供了一個新的屬性:
rules
一個包含一個(或多個) Rule 對象的集合(list)。 每個 Rule 對爬取網站的動作定義了特定表現。 Rule 對象在下邊會介紹。 如果多個 rule 匹配了相同的鏈接,則根據他們在本屬性中被定義的順序,第一個會被使用。
該 spider 也提供了一個可復寫(overrideable)的方法:
parse_start_url(response)
當 start_url 的請求返回時,該方法被調用。 該方法分析最初的返回值并必須返回一個 Item 對象或者 一個 Request 對象或者 一個可迭代的包含二者對象。
6.2.4 爬取規則(Crawling rules)
class scrapy.contrib.spiders.Rule(link_extractor, callback=None, cb_kwargs=None, follow=None, process_links=None, process_request=None)
link_extractor 是一個 Link Extractor 對象。其定義了如何從爬取到的頁面提取鏈接。
callback 是一個 callable 或 string(該 spider 中同名的函數將會被調用)。從 link_extractor 中每獲取到鏈接時將會調用該函數。該回調函數接受一個 response 作為其第一個參數,并返回一個包含 Item 以及(或) Request 對象(或者這兩者的子類)的列表(list)。(注意:當編寫爬蟲規則時,請避免使用 parse 作為回調函數。 由于 CrawlSpider 使用 parse 方法來實現其邏輯,如果 您覆蓋了 parse 方法,crawl spider 將會運行失敗。)
cb_kwargs 包含傳遞給回調函數的參數(keyword argument)的字典。
follow 是一個布爾(boolean)值,指定了根據該規則從 response 提取的鏈接是否需要跟進。 如果 callback 為 None,follow 默認設置為 True,否則默認為 False。
process_links 是一個 callable 或 string(該 spider 中同名的函數將會被調用)。 從 link_extractor 中獲取到鏈接列表時將會調用該函數。該方法主要用來過濾。
process_request 是一個 callable 或 string(該 spider 中同名的函數將會被調用)。 該規則提取到每個 request 時都會調用該函數。該函數必須返回一個 request 或者 None。 (用來過濾 request)
6.2.5 CrawlSpider 樣例
接下來給出配合 rule 使用 CrawlSpider 的例子,如圖6-6所示。
6-6 CrawlSpider樣例
該 spider 將從 example.com 的首頁開始爬取,獲取 category 以及 item 的鏈接并對后者使用 parse_item 方法。當 item 獲得返回(response)時,將使用 XPath 處理 HTML 并生成一些數據填入 Item 中。
6.3Spiders擴展
6.3.1 XMLFeedSpider
class scrapy.contrib.spiders.XMLFeedSpider
XMLFeedSpider 被設計用于通過迭代各個節點來分析 XML 源(XML feed)。迭代器可以從 iternodes,xml,html 選擇。鑒于 xml 以及 html 迭代器需要先讀取所有 DOM 再分析而引起的性能問題,一般還是推薦使用 iternodes。不過使用 html 作為迭代器能有效應對錯誤的 XML。
您必須定義下列類屬性來設置迭代器以及標簽名(tag name):
Iterator
用于確定使用哪個迭代器的 string。可選項有:
l 'iternodes' -一個高性能的基于正則表達式的迭代器
l 'html' -使用 Selector 的迭代器。 需要注意的是該迭代器使用 DOM 進行分析,其需要將所有的 DOM 載入內存, 當數據量大的時候會產生問題。
l 'xml' -使用 Selector 的迭代器。 需要注意的是該迭代器使用 DOM 進行分析,其需要將所有的DOM 載入內存,當數據量大的時候會產生問題。
默認值為 iternodes 。
Itertag
一個包含開始迭代的節點名的 string。例如,itertag = 'product'
namespaces
一個由 (prefix, url) 元組(tuple)所組成的 list。 其定義了在該文檔中會被 spider 處理的可用的 namespace。 prefix 及 uri 會被自動調用 register_namespace()生成 namespace。
您可以通過在 itertag 屬性中制定節點的 namespace。代碼如圖6-7所示。
6-7 XMLFeedSpider
除了這些新的屬性之外,該 spider 也有以下可以覆蓋(overrideable)的方法:
adapt_response(response)
該方法在 spider 分析 response 前被調用。您可以在 response 被分析之前使用該函數來修改內容(body)。該方法接受一個 response 并返回一個 response(可以相同也可以不同)。
parse_node(response, selector)
當節點符合提供的標簽名時(itertag)該方法被調用。 接收到的 response 以及相應的 Selector 作為參數傳遞給該方法。 該方法返回一個 Item 對象或者 Request 對象 或者一個包含二者的可迭代對象(iterable)。
process_results(response, results)
當 spider 返回結果(item 或 request)時該方法被調用。設定該方法的目的是在結果返回給框架核心(framework core)之前做最后的處理,例如設定 item 的 ID。其接受一個結果的列表(list of results)及對應的 response。其結果必須返回一個結果的列表(list of results)(包含 Item 或者 Request 對象)。
6.3.2 XMLFeedSpider 樣例
該 spider 十分易用。下邊是其中一個例子,代碼如圖6-8所示。
6-8 XMLFeedSpider例子
簡單來說,我們在這里創建了一個 spider,從給定的 start_urls 中下載 feed,并迭代 feed 中每個 item 標簽,輸出,并在 Item 中存儲有些隨機數據。
6.3.3 CSVFeedSpider
class scrapy.contrib.spiders.CSVFeedSpider
該 spider 除了其按行遍歷而不是節點之外其他和 XMLFeedSpider 十分類似。 而其在每次迭代時調用的是 parse_row()。
delimiter
在 CSV 文件中用于區分字段的分隔符。類型為 string。 默認為 ',' (逗號)。
quotechar
填寫一個字符串,表示CSV文件中的每個字段的特征,默認為”“(引號)。
headers
在 CSV 文件中包含的用來提取字段的行的列表。參考下邊的例子。
parse_row(response, row)
該方法接收一個 response 對象及一個以提供或檢測出來的 header 為鍵的字典(代表每行)。 該 spider 中,您也可以覆蓋 adapt_response 及 process_results 方法來進行預處理(pre-processing)及后(post-processing)處理。
6.3.4 CSVFeedSpider 樣例
下面的例子和之前的例子很像,但使用了 CSVFeedSpider,如圖6-9所示。
6-9 CSVFeed例子
6.3.5 SitemapSpiderss
class scrapy.contrib.spiders.SitemapSpider
SitemapSpider 使您爬取網站時可以通過 Sitemaps 來發現爬取的 URL。
其支持嵌套的 sitemap,并能從 robots.txt 中獲取 sitemap 的 url。
sitemap_urls
包含您要爬取的 url 的 sitemap 的 url 列表(list)。您也可以指定為一個 robots.txt,spider 會從中分析并提取 url。
sitemap_rules
一個包含 (regex, callback) 元組的列表(list):
l regex 是一個用于匹配從 sitemap 提供的 url 的正則表達式。regex 可以是一個字符串或者編譯的正則對象(compiled regex object)。
l callback 指定了匹配正則表達式的 url 的處理函數。callback 可以是一個字符串(spider 中方法的名字)或者是 callable。
代碼例如:
sitemap_rules = [('/product/', 'parse_product')]
規則按順序進行匹配,之后第一個匹配才會被應用。
如果您忽略該屬性,sitemap 中發現的所有 url 將會被 parse 函數處理。
sitemap_follow
一個用于匹配要跟進的 sitemap 的正則表達式的列表(list)。其僅僅被應用在 使用 Sitemap index files 來指向其他 sitemap 文件的站點。
默認情況下所有的 sitemap 都會被跟進。
sitemap_alternate_links
指定當一個 url 有可選的鏈接時,是否跟進。 有些非英文網站會在一個 url 塊內提供其他語言的網站鏈接。
例如:
<url>
<loc>http://example.com/</loc>
<xhtml:link rel="alternate" hreflang="de" href="http://example.com/de"/>
</url>
當 sitemap_alternate_links 設置時,兩個 URL 都會被獲取。 當 sitemap_alternate_links 關閉時,只有 http://example.com/ 會被獲取。
默認 sitemap_alternate_links 關閉。
6.3.6 SitemapSpider 樣例
簡單的例子:使用 parse 處理通過 sitemap 發現的所有 url,代碼如圖6-10所示。
6-10 SitemapSpider例子
用特定的函數處理某些 url,其他的使用另外的 callback,代碼如圖6-11所示。
6-11 SitemapSpider例子
跟進 robots.txt 文件定義的 sitemap 并只跟進包含有..sitemap_shop 的 url,代碼如圖6-12所示。
6-12 SitemapSpider例子
在 SitemapSpider 中使用其他 url,代碼如圖6-13所示。
6-13 SitemapSpider例子
6.3.7 在 spider 中啟動 shell 來查看 response
有時您想在 spider 的某個位置中查看被處理的 response, 以確認您期望的 response 到達特定位置。
這可以通過 scrapy.s
總結
以上是生活随笔為你收集整理的跟我学系列,走进Scrapy爬虫(六)Spiders爬虫的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于AlertDialog的小坑
- 下一篇: 同花顺l2接口使用体验感怎么样?