Scrapy 框架 入門教程
Scrapy入門教程
在本篇教程中,我已經安裝好Scrapy
本篇教程中將帶您完成下列任務:
- 創建一個Scrapy項目
- 定義提取的Item
- 編寫爬取網站的 spider 並提取 Item
- 編寫 Item Pipeline 來存儲提取到的Item(即數據)
創建項目
在開始爬取之前,您必須創建一個新的Scrapy項目。 進入您打算存儲代碼的目錄中,運行下列命令:
scrapy startproject tutorial
tutorial/ scrapy.cfg tutorial/ __init__.py items.py pipelines.py settings.py spiders/ __init__.py ...
這些文件分別是:
scrapy.cfg
: 項目的配置文件tutorial/
: 該項目的python模塊。之後您將在此加入代碼。tutorial/items.py
: 項目中的item文件.tutorial/pipelines.py
: 項目中的pipelines文件.tutorial/settings.py
: 項目的設置文件.tutorial/spiders/
: 放置spider代碼的目錄.
定義Item
Item 是保存爬取到的數據的容器;其使用方法和python字典類似, 並且提供了額外保護機制來避免拼寫錯誤導致的未定義字段錯誤。
首先根據需要從dmoz.org獲取到的數據對item進行建模。 我們需要從dmoz中獲取名字,url,以及網站的描述。 對此,在item中定義相應的字段。編輯 tutorial
目錄中的 items.py
文件:
import scrapy class DmozItem(scrapy.Item): title = scrapy.Field() link = scrapy.Field() desc = scrapy.Field()
一開始這看起來可能有點復雜,但是通過定義item, 您可以很方便的使用Scrapy的其他方法。而這些方法需要知道您的item的定義。
編寫第一個爬蟲(Spider)
Spider是用戶編寫用於從單個網站(或者一些網站)爬取數據的類。
其包含了一個用於下載的初始URL,如何跟進網頁中的鏈接以及如何分析頁面中的內容, 提取生成 item 的方法。
為了創建一個Spider,您必須繼承 scrapy.Spider
類, 且定義以下三個屬性:
name
: 用於區別Spider。 該名字必須是唯一的,您不可以為不同的Spider設定相同的名字。start_urls
: 包含了Spider在啟動時進行爬取的url列表。 因此,第一個被獲取到的頁面將是其中之一。 後續的URL則從初始的URL獲取到的數據中提取。parse()
是spider的一個方法。 被調用時,每個初始URL完成下載後生成的Response
對象將會作為唯一的參數傳遞給該函數。 該方法負責解析返回的數據(response data),提取數據(生成item)以及生成需要進一步處理的URL的Request
對象。
以下為我們的第一個Spider代碼,保存在 tutorial/spiders
目錄下的 dmoz_spider.py
文件中:
import scrapy class DmozSpider(scrapy.Spider): name = "dmoz" allowed_domains = ["dmoz.org"] start_urls = [ "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/", "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/" ] def parse(self, response): filename = response.url.split("/")[-2] with open(filename, ‘wb‘) as f: f.write(response.body)
爬取
進入項目的根目錄,執行下列命令啟動spider:
scrapy crawl dmoz
crawl dmoz
啟動用於爬取 dmoz.org
的spider,您將得到類似的輸出:
2014-01-23 18:13:07-0400 [scrapy] INFO: Scrapy started (bot: tutorial) 2014-01-23 18:13:07-0400 [scrapy] INFO: Optional features available: ... 2014-01-23 18:13:07-0400 [scrapy] INFO: Overridden settings: {} 2014-01-23 18:13:07-0400 [scrapy] INFO: Enabled extensions: ... 2014-01-23 18:13:07-0400 [scrapy] INFO: Enabled downloader middlewares: ... 2014-01-23 18:13:07-0400 [scrapy] INFO: Enabled spider middlewares: ... 2014-01-23 18:13:07-0400 [scrapy] INFO: Enabled item pipelines: ... 2014-01-23 18:13:07-0400 [dmoz] INFO: Spider opened 2014-01-23 18:13:08-0400 [dmoz] DEBUG: Crawled (200) <GET http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/> (referer: None) 2014-01-23 18:13:09-0400 [dmoz] DEBUG: Crawled (200) <GET http://www.dmoz.org/Computers/Programming/Languages/Python/Books/> (referer: None) 2014-01-23 18:13:09-0400 [dmoz] INFO: Closing spider (finished)
查看包含 [dmoz]
的輸出,可以看到輸出的log中包含定義在 start_urls
的初始URL,並且與spider中是一一對應的。在log中可以看到其沒有指向其他頁面( (referer:None)
)。
除此之外,更有趣的事情發生了。就像我們 parse
方法指定的那樣,有兩個包含url所對應的內容的文件被創建了: Book , Resources 。
剛才發生了什麽?
Scrapy為Spider的 start_urls
屬性中的每個URL創建了 scrapy.Request
對象,並將 parse
方法作為回調函數(callback)賦值給了Request。
Request對象經過調度,執行生成 scrapy.http.Response
對象並送回給spider parse()
方法。
提取Item
這裏給出XPath表達式的例子及對應的含義:
/html/head/title
: 選擇HTML文檔中<head>
標簽內的<title>
元素/html/head/title/text()
: 選擇上面提到的<title>
元素的文字//td
: 選擇所有的<td>
元素//div[@class="mine"]
: 選擇所有具有class="mine"
屬性的div
元素
Selector有四個基本的方法(點擊相應的方法可以看到詳細的API文檔):
xpath()
: 傳入xpath表達式,返回該表達式所對應的所有節點的selector list列表 。css()
: 傳入CSS表達式,返回該表達式所對應的所有節點的selector list列表.extract()
: 序列化該節點為unicode字符串並返回list。re()
: 根據傳入的正則表達式對數據進行提取,返回unicode字符串list列表。
在Shell中嘗試Selector選擇器
為了介紹Selector的使用方法,接下來我們將要使用內置的 Scrapy shell 。Scrapy Shell需要您預裝好IPython(一個擴展的Python終端)。
您需要進入項目的根目錄,執行下列命令來啟動shell:
scrapy shell "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/"
註意:當您在終端運行Scrapy時,請一定記得給url地址加上引號,否則包含參數的url(例如 &
字符)會導致Scrapy運行失敗。
shell的輸出類似:
[ ... Scrapy log here ... ] 2014-01-23 17:11:42-0400 [default] DEBUG: Crawled (200) <GET http://www.dmoz.org/Computers/Programming/Languages/Python/Books/> (referer: None) [s] Available Scrapy objects: [s] crawler <scrapy.crawler.Crawler object at 0x3636b50> [s] item {} [s] request <GET http://www.dmoz.org/Computers/Programming/Languages/Python/Books/> [s] response <200 http://www.dmoz.org/Computers/Programming/Languages/Python/Books/> [s] settings <scrapy.settings.Settings object at 0x3fadc50> [s] spider <Spider ‘default‘ at 0x3cebf50> [s] Useful shortcuts: [s] shelp() Shell help (print this help) [s] fetch(req_or_url) Fetch request (or URL) and update local objects [s] view(response) View response in a browser In [1]:
當shell載入後,您將得到一個包含response數據的本地 response
變量。輸入 response.body
將輸出response的包體, 輸出 response.headers
可以看到response的包頭。
更為重要的是,當輸入 response.selector
時, 您將獲取到一個可以用於查詢返回數據的selector(選擇器), 以及映射到 response.selector.xpath()
、 response.selector.css()
的 快捷方法(shortcut): response.xpath()
和 response.css()
。
同時,shell根據response提前初始化了變量 sel
。該selector根據response的類型自動選擇最合適的分析規則(XML vs HTML)。
讓我們來試試:
In [1]: response.xpath(‘//title‘) Out[1]: [<Selector xpath=‘//title‘ data=u‘<title>Open Directory - Computers: Progr‘>] In [2]: response.xpath(‘//title‘).extract() Out[2]: [u‘<title>Open Directory - Computers: Programming: Languages: Python: Books</title>‘] In [3]: response.xpath(‘//title/text()‘) Out[3]: [<Selector xpath=‘//title/text()‘ data=u‘Open Directory - Computers: Programming:‘>] In [4]: response.xpath(‘//title/text()‘).extract() Out[4]: [u‘Open Directory - Computers: Programming: Languages: Python: Books‘] In [5]: response.xpath(‘//title/text()‘).re(‘(\w+):‘) Out[5]: [u‘Computers‘, u‘Programming‘, u‘Languages‘, u‘Python‘]
在我們的spider中加入這段代碼:
一般來說,Spider將會將爬取到的數據以 Item
對象返回。所以為了將爬取的數據返回,我們最終的代碼將是:
import scrapy from tutorial.items import DmozItem class DmozSpider(scrapy.Spider): name = "dmoz" allowed_domains = ["dmoz.org"] start_urls = [ "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/", "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/" ] def parse(self, response): for sel in response.xpath(‘//ul/li‘): item = DmozItem() item[‘title‘] = sel.xpath(‘a/text()‘).extract() item[‘link‘] = sel.xpath(‘a/@href‘).extract() item[‘desc‘] = sel.xpath(‘text()‘).extract() yield item
現在嘗試再次爬取dmoz.org,您將看到爬取到的網站信息被成功輸出:
scrapy crawl dmoz
[dmoz] DEBUG: Scraped from <200 http://www.dmoz.org/Computers/Programming/Languages/Python/Books/> {‘desc‘: [u‘ - By David Mertz; Addison Wesley. Book in progress, full text, ASCII format. Asks for feedback. [author website, Gnosis Software, Inc.\n], ‘link‘: [u‘http://gnosis.cx/TPiP/‘], ‘title‘: [u‘Text Processing in Python‘]} [dmoz] DEBUG: Scraped from <200 http://www.dmoz.org/Computers/Programming/Languages/Python/Books/> {‘desc‘: [u‘ - By Sean McGrath; Prentice Hall PTR, 2000, ISBN 0130211192, has CD-ROM. Methods to build XML applications fast, Python tutorial, DOM and SAX, new Pyxie open source XML processing library. [Prentice Hall PTR]\n‘], ‘link‘: [u‘http://www.informit.com/store/product.aspx?isbn=0130211192‘], ‘title‘: [u‘XML Processing with Python‘]}
保存爬取到的數據
scrapy crawl dmoz -o items.json
該命令將采用 JSON 格式對爬取的數據進行序列化,生成 items.json
文件。
Scrapy 框架 入門教程