使用Python的Scrapy框架編寫web爬蟲的簡單示例
在這個教材中,我們假定你已經(jīng)安裝了Scrapy。假如你沒有安裝,你可以參考這個安裝指南。
我們將會用開放目錄項目(dmoz)作為我們例子去抓取。
這個教材將會帶你走過下面這幾個方面:
- 創(chuàng)造一個新的Scrapy項目
- 定義您將提取的Item
- 編寫一個蜘蛛去抓取網(wǎng)站并提取Items。
- 編寫一個Item Pipeline用來存儲提出出來的Items
Scrapy由Python寫成。假如你剛剛接觸Python這門語言,你可能想要了解這門語言起,怎么最好的利用這門語言。假如你已經(jīng)熟悉其它類似的語言,想要快速地學(xué)習Python,我們推薦這種深入方式學(xué)習Python。假如你是新手,想從開始使用Python學(xué)習,可以嘗試去看看非程序員Python資源列表。
創(chuàng)造一個項目
在你要抓取之前,首先要建立一個新的Scrapy項目。然后進去你的存放代碼目錄,執(zhí)行如下命令。
scrapy startproject tutorial
它將會創(chuàng)建如下的向?qū)夸?
scrapy.cfg
tutorial/
__init__.py
items.py
pipelines.py
settings.py
spiders/
__init__.py
...
這是一些基本信息:
- scrapy.cfg: 項目的配置文件。
- tutorial/: 項目的python模塊, 在這里稍后你將會導(dǎo)入你的代碼。
- tutorial/items.py: 項目items文件。
- tutorial/pipelines.py: 項目管道文件。
- tutorial/settings.py: 項目配置文件。
- tutorial/spiders/: 你將要放入你的spider到這個目錄中。
定義我們的Item
Items是裝載我們抓取數(shù)據(jù)的容器。它們工作像簡單的Python字典,它提供更多的保護,比如對未定義的字段提供填充功能防止出錯。
它們通過創(chuàng)建scrapy.item.Item類來聲明并定義它們的屬性作為scrapy.item.Field 對象,就像是一個對象關(guān)系映射(假如你不熟悉ORMs,你將會看見它是一個簡單的任務(wù)).
我們將需要的item模塊化,來控制從demoz.org網(wǎng)站獲取的數(shù)據(jù),比如我們將要去抓取網(wǎng)站的名字,url和描述信息。我們定義這三種屬性的域。我們編輯items.py文件,它在向?qū)夸浿?。我們Item類看起來像這樣。
from scrapy.item import Item, Field class DmozItem(Item): title = Field() link = Field() desc = Field()
這個看起來復(fù)雜的,但是定義這些item能讓你用其他Scrapy組件的時候知道你的item到底是什么
我們第一個Spider
Spiders是用戶寫的類,它用來去抓取一個網(wǎng)站的信息(或者一組網(wǎng)站) 。
我們定義一個初始化的URLs列表去下載,如何跟蹤鏈接,如何去解析這些頁面的內(nèi)容去提取 items.創(chuàng)建一個Spider,你必須是scrapy.spider.BaseSpider的子類, 并定義三個主要的,強制性的屬性。
名字: Spider的標識. 它必須是唯一的, 那就是說,你不能在不同的Spiders中設(shè)置相同的名字。
開始鏈接:Spider將會去爬這些URLs的列表。所以剛開始的下載頁面將要包含在這些列表中。其他子URL將會從這些起始URL中繼承性生成。
parse() 是spider的一個方法, 調(diào)用時候傳入從每一個URL傳回的Response對象作為參數(shù)。response是方法的唯一參數(shù)。
這個方法負責解析response數(shù)據(jù)和提出抓取的數(shù)據(jù)(作為抓取的items),跟蹤URLs
parse()方法負責處理response和返回抓取數(shù)據(jù)(作為Item對象) 和跟蹤更多的URLs(作為request的對象)
這是我們的第一個Spider的代碼;它保存在moz/spiders文件夾中,被命名為dmoz_spider.py:
from scrapy.spider import BaseSpider class DmozSpider(BaseSpider): 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] open(filename, 'wb').write(response.body)
爬
為了使你的spider工作, 到項目的頂級目錄讓后運行:
scrapy crawl dmoz
crawl dmoz命令使spider去爬dmoz.org網(wǎng)站的信息。你將會得到如下類似的信息:
2008-08-20 03:51:13-0300 [scrapy] INFO: Started project: dmoz 2008-08-20 03:51:13-0300 [tutorial] INFO: Enabled extensions: ... 2008-08-20 03:51:13-0300 [tutorial] INFO: Enabled downloader middlewares: ... 2008-08-20 03:51:13-0300 [tutorial] INFO: Enabled spider middlewares: ... 2008-08-20 03:51:13-0300 [tutorial] INFO: Enabled item pipelines: ... 2008-08-20 03:51:14-0300 [dmoz] INFO: Spider opened 2008-08-20 03:51:14-0300 [dmoz] DEBUG: Crawled <http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/> (referer: <None>) 2008-08-20 03:51:14-0300 [dmoz] DEBUG: Crawled <http://www.dmoz.org/Computers/Programming/Languages/Python/Books/> (referer: <None>) 2008-08-20 03:51:14-0300 [dmoz] INFO: Spider closed (finished)
注意那些行包含[dmoz], 它和我們的spider相關(guān)。你能夠看見每行初始化的URL日志信息。因為這些URLs是起始頁面,所以他們沒有引用referrers。 所以在每行的末尾部門,你能看見(referer: <None>).
但是有趣的是,在我們的parse方法作用下,兩個文件被創(chuàng)建: Books and Resources, 它保航兩個URLs的內(nèi)容
剛剛發(fā)生了什么事情?
Scrapy為每一個start_urls創(chuàng)建一個scrapy.http.Request對象,并將爬蟲的parse 方法指定為回調(diào)函數(shù)。
這些Request首先被調(diào)度,然后被執(zhí)行,之后通過parse()方法,將scrapy.http.Response對象被返回,結(jié)果也被反饋給爬蟲。
提取Items
選擇器介紹
我們有多種方式去提取網(wǎng)頁中數(shù)據(jù)。Scrapy 使用的是XPath表達式,通常叫做XPath selectors。如果想了解更多關(guān)于選擇器和提取數(shù)據(jù)的機制,可以看看如下教程XPath selectors documentation.
這里有一些表達式的例子和它們相關(guān)的含義:
- /html/head/title: 選擇<title>元素,在HTML文檔的<head>元素里
- /html/head/title/text(): 選擇<title>元素里面的文本
- //td: 選擇所有的<td>元素
- //div[@class="mine"]: 選擇所有的div元素里面class屬性為mine的
這里有許多的例子關(guān)于怎么使用XPath,可以說XPath表達式是非常強大的。如果你想要學(xué)習更多關(guān)于XPath,我們推薦如下教程this XPath tutorial.
為了更好使用XPaths, Scrapy提供了一個XPathSelector類,它有兩種方式, HtmlXPathSelector(HTML相關(guān)數(shù)據(jù))和XmlXPathSelector(XML相關(guān)數(shù)據(jù))。如果你想使用它們,你必須實例化一個Response對象.
你能夠把selectors作為對象,它代表文件結(jié)構(gòu)中的節(jié)點。所以,第1個實例的節(jié)點相當于root節(jié)點,或者稱為整個文檔的節(jié)點。
選擇器有三種方法(點擊方法你能夠看見完整的API文檔)。
- select(): 返回選擇器的列表,每一個select表示一個xpath表達式選擇的節(jié)點。
- extract(): 返回一個unicode字符串 ,該字符串XPath選擇器返回的數(shù)據(jù)。
- re() : 返回unicode字符串列表,字符串作為參數(shù)由正則表達式提取出來。
在Shell里面使用選擇器
為了更加形象的使用選擇器,我們將會使用Scrapy shell,它同時需要你的系統(tǒng)安裝IPython (一個擴展的Python控制臺)。
如果使用shell,你必須到項目的頂級目錄上,讓后運行如下命令:
scrapy shell http://www.dmoz.org/Computers/Programming/Languages/Python/Books/
shell將會顯示如下的信息
[ ... Scrapy log here ... ] [s] Available Scrapy objects: [s] 2010-08-19 21:45:59-0300 [default] INFO: Spider closed (finished) [s] hxs <HtmlXPathSelector (http://www.dmoz.org/Computers/Programming/Languages/Python/Books/) xpath=None> [s] item 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] spider <BaseSpider 'default' at 0x1b6c2d0> [s] xxs <XmlXPathSelector (http://www.dmoz.org/Computers/Programming/Languages/Python/Books/) xpath=None> [s] Useful shortcuts: [s] shelp() Print this help [s] fetch(req_or_url) Fetch a new request or URL and update shell objects [s] view(response) View response in a browser In [1]:
當shell裝載之后,你將會得到一個response的本地變量。所以你輸入reponse.body,你能夠看見response的body部分或者你能夠輸入response.headers,你能夠看見reponse.headers部分。
shell同樣實例化了兩個選擇器,一個是HTML(在hvx變量里),一個是XML(在xxs變量里)。所以我們嘗試怎么使用它們:
In [1]: hxs.select('//title') Out[1]: [<HtmlXPathSelector (title) xpath=//title>] In [2]: hxs.select('//title').extract() Out[2]: [u'<title>Open Directory - Computers: Programming: Languages: Python: Books</title>'] In [3]: hxs.select('//title/text()') Out[3]: [<HtmlXPathSelector (text) xpath=//title/text()>] In [4]: hxs.select('//title/text()').extract() Out[4]: [u'Open Directory - Computers: Programming: Languages: Python: Books'] In [5]: hxs.select('//title/text()').re('(\w+):') Out[5]: [u'Computers', u'Programming', u'Languages', u'Python']
提取數(shù)據(jù)Extracting the data
現(xiàn)在我們開始嘗試在這幾個頁面里提取真正的信息。
你能夠在控制臺里面輸入response.body,檢查源代碼里面的XPaths是否與預(yù)期相同。然而,檢查原始的HTML代碼是一件非常枯燥乏味的事情。假如你想讓你的工作變的簡單,你使用Firefox擴展的插件例如Firebug來做這項任務(wù)。更多關(guān)于介紹信息請看Using Firebug for scraping和Using Firefox for scraping。
當你檢查了頁面源代碼之后,你將會發(fā)現(xiàn)頁面的信息放在一個<ul>元素里面,事實上,確切地說是第二個<ul>元素。
所以我們選擇每一個<li>元素使用如下的代碼:
hxs.select('//ul/li')
網(wǎng)站的描述信息可以使用如下代碼:
hxs.select('//ul/li/text()').extract()
網(wǎng)站的標題:
hxs.select('//ul/li/a/text()').extract()
網(wǎng)站的鏈接:
hxs.select('//ul/li/a/@href').extract()
如前所述,每個select()調(diào)用返回一個selectors列表,所以我們可以結(jié)合select()去挖掘更深的節(jié)點。我們將會用到這些特性,所以:
sites = hxs.select('//ul/li') for site in sites: title = site.select('a/text()').extract() link = site.select('a/@href').extract() desc = site.select('text()').extract() print title, link, desc Note
如果想了解更多的嵌套選擇器,可以參考Nesting selectors和Working with relative XPaths相關(guān)的Selectors文檔
將代碼添加到我們spider中:
from scrapy.spider import BaseSpider from scrapy.selector import HtmlXPathSelector class DmozSpider(BaseSpider): 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): hxs = HtmlXPathSelector(response) sites = hxs.select('//ul/li') for site in sites: title = site.select('a/text()').extract() link = site.select('a/@href').extract() desc = site.select('text()').extract() print title, link, desc
現(xiàn)在我們再次抓取dmoz.org,你將看到站點在輸出中被打印 ,運行命令:
scrapy crawl dmoz
使用我們的 item
Item對象是自定義python字典;使用標準字典類似的語法,你能夠訪問它們的字段(就是以前我們定義的屬性)
>>> item = DmozItem() >>> item['title'] = 'Example title' >>> item['title'] 'Example title'
Spiders希望將抓取的數(shù)據(jù)放在 Item對象里。所以,為了返回我們抓取的數(shù)據(jù),最終的代碼要如下這么寫 :
from scrapy.spider import BaseSpider from scrapy.selector import HtmlXPathSelector from tutorial.items import DmozItem class DmozSpider(BaseSpider): 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): hxs = HtmlXPathSelector(response) sites = hxs.select('//ul/li') items = [] for site in sites: item = DmozItem() item['title'] = site.select('a/text()').extract() item['link'] = site.select('a/@href').extract() item['desc'] = site.select('text()').extract() items.append(item) return itemsNote
你能夠找到完整功能的spider在dirbot項目里,同樣你可以訪問https://github.com/scrapy/dirbot
現(xiàn)在重新抓取dmoz.org網(wǎng)站:
[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']}
存儲抓取的數(shù)據(jù)
最簡單的方式去存儲抓取的數(shù)據(jù)是使用Feed exports,使用如下的命令:
scrapy crawl dmoz -o items.json -t json
它將會產(chǎn)生一個items.json文件,它包含所有抓取的items(序列化的JSON)。
在一些小的項目里(例如我們的教程中),那就足夠啦。然而,假如你想要執(zhí)行更多復(fù)雜的抓取items,你能夠?qū)懸粋€ Item Pipeline。 因為在項目創(chuàng)建的時候,一個專門用于Item Pipelines的占位符文件已經(jīng)隨著項目一起被建立,目錄在tutorial/pipelines.py。如果你只需要存取這些抓取后的items的話,就不需要去實現(xiàn)任何的條目管道。
- Python爬蟲框架Scrapy安裝使用步驟
- 零基礎(chǔ)寫python爬蟲之使用Scrapy框架編寫爬蟲
- 使用scrapy實現(xiàn)爬網(wǎng)站例子和實現(xiàn)網(wǎng)絡(luò)爬蟲(蜘蛛)的步驟
- scrapy爬蟲完整實例
- 深入剖析Python的爬蟲框架Scrapy的結(jié)構(gòu)與運作流程
- 講解Python的Scrapy爬蟲框架使用代理進行采集的方法
- Python使用Scrapy爬蟲框架全站爬取圖片并保存本地的實現(xiàn)代碼
- Python的Scrapy爬蟲框架簡單學(xué)習筆記
- 實踐Python的爬蟲框架Scrapy來抓取豆瓣電影TOP250
- python爬蟲框架scrapy實戰(zhàn)之爬取京東商城進階篇
- 淺析python實現(xiàn)scrapy定時執(zhí)行爬蟲
- Scrapy爬蟲多線程導(dǎo)致抓取錯亂的問題解決
相關(guān)文章
Python3基礎(chǔ)之基本數(shù)據(jù)類型概述
這篇文章主要介紹了Python3的基本數(shù)據(jù)類型,需要的朋友可以參考下2014-08-08python如何用matplotlib創(chuàng)建三維圖表
這篇文章主要介紹了python如何在matplotlib中創(chuàng)建三維圖表,幫助大家更好的利用python進行數(shù)據(jù)分析,感興趣的朋友可以了解下2021-01-01python 實現(xiàn)文件的遞歸拷貝實現(xiàn)代碼
今天翻電腦時突然發(fā)現(xiàn)有個存了很多照片和視頻的文件夾,想起來是去年換手機(流行的小5)時拷出來的??戳藥讖堈掌?,往事又一幕幕的浮現(xiàn)在腦海,好吧,我是個感性的人2012-08-08用Python監(jiān)控你的朋友都在瀏覽哪些網(wǎng)站?
今天教各位小伙伴一個黑科技,用Python監(jiān)控你的朋友都在瀏覽哪些網(wǎng)站,文中有非常詳細的介紹,對正在學(xué)習python的小伙伴們很有幫助,需要的朋友可以參考下2021-05-05