Scrapy——基本用法(命令行工具、Item、Spiders)
命令行工具
創(chuàng)建項目
scrapy startproject myproject該命令經(jīng)會在myproject目錄中創(chuàng)建一個Scrapy項目。進入到項目根目錄,就可以使用scrapy命令來管理和控制你的項目了。
控制項目
有些Scrapy命令要求在Scrapy項目中運行。另外注意,有些命令在項目里運行時的效果有些區(qū)別。
查看所有可用命令
scrapy -hScrapy提供了兩種類型的命令。一種是必須在scrapy項目中運行,另一種則不與需要。
全局命令:
| startproject | scrapy startproject [project_name] | 創(chuàng)建項目 |
| settings | scrapy settings [options] | 在項目中運行時,該命令將會輸出醒目的設(shè)定值,否則輸出Scrapy默認(rèn)設(shè)定 |
| runspider | scrapy runspider spider_file.py | 在未創(chuàng)建項目的情況下,運行一個在Python文件中的spider |
| shell | scrapy shell [url] | 以給定的URL或者空啟動Scrapy |
| fetch | scrapy fetch [url] | 使用Scrapy下載器下載給定的URL,并將獲取到的內(nèi)容送到標(biāo)準(zhǔn)輸出。 |
| view | scrapy view [url] | 在瀏覽器中打開給定的URL,并以Scrapy spider獲取到的形式展現(xiàn),可以用來檢查spider所獲取到的頁面 |
| version | scrapy version [-v] | 輸出scrapy版本,配合-v運行時,該命令將同時輸出python,Twisted以及平臺的信息,方便bug提交 |
項目命令 |命令|語法|功能| |-|-| |crawl|`scrapy crawl `|使用spider進行爬取| |check|`scrapy check [-l] `|運行contract檢查| |list|scrapy list|列出當(dāng)前項目種所有可用的spider| |edit|`scrapy edit `|使用EDITOR種設(shè)定的編輯器給定的spider| |parse|`scrapy parse [options]`|獲取給定的URL并使用響應(yīng)的spider分析處理。| |genspider|`scrapy genspider [-t template] `|僅僅是創(chuàng)建spider的一種快捷方法。該方法可以用提前定義好的模板來生成spider,也可以自己創(chuàng)建spider的源碼文件| |deploy|`scrapy deploy [ | -l | -L ]`|將項目部署到Scrapyd服務(wù)| |bench|`scrapy bench`|運行benchmark測試|
parse命令參數(shù)選項
- –spider=SPIDER:跳過自動檢測spider并強制使用特定的spider;
- –a NAME=VALUE:設(shè)置spider的參數(shù)
- –callback-cspider中用于解析返回的回調(diào)函數(shù)
- –pipelines:在pipeline中處理item
- –rules-r:使用CrawlSpider規(guī)則來發(fā)現(xiàn)用來解析返回的回調(diào)函數(shù)
- –noitems不顯示爬取道的item
- –nolinks不顯示爬取到的鏈接
- –nocolour避免使用pygments對輸出著色
- –depth-d指定跟進鏈接誒請求的層數(shù)默認(rèn)為1
- –verbose-v顯示每個請求的詳細(xì)信息
Items
爬取的主要目的就是從非結(jié)構(gòu)性的數(shù)據(jù)源提取結(jié)構(gòu)性數(shù)據(jù)。Scrapy提供Item類來滿足這樣的需求。Item對象是種簡單的容器,保存了爬取到的數(shù)據(jù)。其提供了類似于字典的API以及用于聲明可用字段的簡單語法。
聲明Item
Item字段
Field對象指明了每個字段的元數(shù)據(jù)。你可以為每個字段指明任何類型的元數(shù)據(jù)。設(shè)置Field對象的主要目的就是在一個地方定義好所有的元數(shù)據(jù)。
與Item配合
創(chuàng)建item
獲取字段值
>>> product['name'] Desktop PC >>> product.get('name') Desktop PC>>> product['price'] 1000>>> product['last_updated'] Traceback (most recent call last):... KeyError: 'last_updated'>>> product.get('last_updated', 'not set') not set>>> product['lala'] # getting unknown field Traceback (most recent call last):... KeyError: 'lala'>>> product.get('lala', 'unknown field') 'unknown field'>>> 'name' in product # is name field populated? True>>> 'last_updated' in product # is last_updated populated? False>>> 'last_updated' in product.fields # is last_updated a declared field? True>>> 'lala' in product.fields # is lala a declared field? False設(shè)置字段值
>>> product['last_updated'] = 'today' >>> product['last_updated'] today>>> product['lala'] = 'test' # setting unknown field Traceback (most recent call last):... KeyError: 'Product does not support field: lala'獲取所有獲取到的值
print product.keys()# ['price', 'name']print product.items()# [('price', 1000), ('name', 'Desktop PC')]復(fù)制item
product2=Product(product)print product2 # {'name': 'Desktop PC', 'price': 1000}product3=product2.copy()print product3 # {'name': 'Desktop PC', 'price': 1000}根據(jù)item創(chuàng)建字典
print dict(product)# {'price': 1000, 'name': 'Desktop PC'}根據(jù)字典創(chuàng)建item
print Product({'name': 'Laptop PC', 'price': 1500}) # {'name': 'Laptop PC', 'price': 1500}擴展Item
可以通過繼承原始的Item來擴展item
也可以通過使用原字段的元數(shù)據(jù),添加新的值或修改原來的值來擴展字段元數(shù)據(jù)。
class SpecificProduct(Product):name = scrapy.Field(Product.fields['name'], serializer=my_serializer)Item對象
class scrapy.item.Item([arg])返回一個根據(jù)給定參數(shù)可選初始化的item,Item讀值了標(biāo)準(zhǔn)的dict API。包括初始化函數(shù)也相同,為以額外添加的屬性是:field,一個包含了所有聲明的字段的字典,而不僅僅是貨渠道的字段。
Spiders
Spider類定義了如何爬取某個網(wǎng)站,包括了爬取的動作以及如何從網(wǎng)頁的內(nèi)容中提取結(jié)構(gòu)化數(shù)據(jù)。還句話說,Spider就是你定義爬取的動作及分析某個網(wǎng)頁的地方。
- 以初始的URL初始化Request,并設(shè)置回調(diào)函數(shù)。當(dāng)該request下載完畢并返回時,將生成response,并作為參數(shù)傳給該回調(diào)函數(shù)。start_requests()讀取start_urls中的URL,并以parse為回調(diào)函數(shù)生成Request.
- 在回調(diào)函數(shù)內(nèi)分析返回的網(wǎng)頁內(nèi)容,返回Item對象或者Request或者一個包含二者的可迭代容器。返回的Request對象之后回經(jīng)過Scrapy處理,下載相應(yīng)的內(nèi)容,并調(diào)用設(shè)置的callback函數(shù)。
- 在回調(diào)函數(shù)內(nèi),你可以使用選擇器來分析網(wǎng)頁內(nèi)容,并根據(jù)分析的數(shù)據(jù)生成item。
- 最后,由spider返回的item將被存到數(shù)據(jù)庫或使用Feed exports存到文件中。
Spider參數(shù)
Spider可以通過接收參數(shù)來修改其功能。spider參數(shù)一般用來定義初始URL或者指定先值爬取網(wǎng)站的部分。
在運行crawl時添加-a可以傳遞Spider參數(shù):
Spider在構(gòu)造器中獲取參數(shù)。
import scrapyclass MySpider(Spider):name = 'myspider'def __init__(self, category=None, *args, **kwargs):super(MySpider, self).__init__(*args, **kwargs)self.start_urls = ['http://www.example.com/categories/%s' % category]# ...Spider
class scrapy.spider.SpiderSpider是最簡單的spider。每個器它的spider必須繼承自該類。Spider僅僅請求給定的
start_urls/start_requests,并根據(jù)返回的結(jié)果(resulting/responses)調(diào)用spider的parse方法。
- **name:**定義spider名字的字符串。定義了Scrapy如何定位spider,必須是唯一的。不過可以生成多個相同的spider實例。
如果該spider爬取單個網(wǎng)站,一個常見的做法是以該網(wǎng)站來命名spider。 - **allowed_domains:**可選,包含了spider允許爬取的域名列表。當(dāng)offsiteMiddleware啟用時,域名不在列表中的URL不會被跟進。
- **start_urls:**URL列表,當(dāng)沒有制定特定的URL時,spider將從該列表中來時進行爬取。因此,第一個被獲取到的頁面的URL將是該列表之一。后續(xù)的URL將會從獲取到的數(shù)據(jù)中提取。
- **start_requests()?*該方法必須返回一個可迭代對象。該對象包含了spider用于爬取的第一個Request。當(dāng)spider啟動爬取并且未指定URL時,該方法被調(diào)用。當(dāng)指定了URL時,make_requests_from_url()將被調(diào)用來創(chuàng)建Request對象。僅近乎uibei調(diào)用一次,可視為生成器。該方法默認(rèn)使用start_urls的url生成Reqest。如果你想修改最初爬取某個網(wǎng)站的Request對象,可以重寫該方法。
- **make_requests_from_url(url)?*該方法接收一個URL并返回用于爬取的Request對象。在初始化時被start_requests()調(diào)用,也用于轉(zhuǎn)化url為request。默認(rèn)未被復(fù)寫的情況下該方法返回的Request對象中,parse()作為回調(diào)函數(shù),dont_filter參數(shù)也被設(shè)置為開啟。
- **parse(respone)?*當(dāng)response沒有指定回調(diào)函數(shù)時,該方法時Scapy處理下載的response的默認(rèn)方法。
parse負(fù)責(zé)處理respones并返回處理的數(shù)據(jù)以及跟進的URL。
Spider對其他的Request及Item的可迭代的對象。 - **log(message[,level,component]):*使用scrapy.log.msg()方法記錄message。log中自動帶上該spider的name屬性。
- **closed(reason)?*當(dāng)spider關(guān)閉時,該函數(shù)被調(diào)用。該方法提供了一個提到調(diào)用signals.connect()來監(jiān)聽spider_closed信號的快捷方式。
樣例
CrawlSpider
class scrapy.contrib.spiders.CrawlSpider爬取一般網(wǎng)站常用的spider。其定義了一些規(guī)則來提供跟link的方便機制。除了繼承過來的屬性外,其提供了一個新的屬性。
- **rules:**一個包含一個或多個Rule對象的集合。每個Rule對爬取網(wǎng)站的動作定義了特定的表現(xiàn)。如果rule匹配了相同的鏈接,則根據(jù)它們在本屬性中被定義的順序,第一個會被使用。
- **parse_start_url(response)?*當(dāng)start_url的請求返回時,該方法被調(diào)用。該方法分析最初的返回值并必須返回一個 Item 對象或者 一個 Request 對象或者 一個可迭代的包含二者對象。
爬取規(guī)則(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。從link_extractor中每獲取到鏈接時將調(diào)用該函數(shù)。該回調(diào)函數(shù)接受一個response作為其第一個參數(shù),并返回一個包含Itm以及Request對象的列表。
- cb_kwargs:包含傳遞給回調(diào)函數(shù)的參數(shù)的字典。
- follow是一個布爾值,指定了根據(jù)該規(guī)則從response提取的鏈接是否需要跟進。如果callback為None,follow默認(rèn)設(shè)置為True,否則默認(rèn)為False。
- process_link是一個callable或string。主要用來過濾。
- process_reqeust是一個callable或string。該規(guī)則提取到每個request時都會調(diào)用該函數(shù)。該函數(shù)必須返回一個request或None.
該spider將從example.com的首頁開始爬取,獲取category以及item的鏈接并對后者使用parse_item方法。當(dāng)item獲得返回時,將使用XPath處理HTML并生成一些數(shù)據(jù)填入Item中。
XMLFeedSpider
XMLFeedSpider被設(shè)計用于通過迭代各個節(jié)點來分析XML源。迭代其可以從iternodes,xml,html選擇。鑒于xml以及html迭代器需要先讀取所有DOM再分析而引起的性能問題,一般還是推薦使用iternodes。
你必須定義下列類屬性來設(shè)置迭代器以及標(biāo)簽名:
**iterator:**用于確定使用哪個迭代器,
- iternodes-一個高性能的基于正則表達式的迭代器;
- html'-使用selector的迭代器。使用DOM進行分析,其需要將所有的DOM載入內(nèi)存,當(dāng)數(shù)據(jù)量大的時候會產(chǎn)生問題。
- xml-和html一樣。
默認(rèn)值為iternodes。
itertag一個包含開始迭代的節(jié)點名的sring。
namespaces一個由(prefix,url)元組所組成的list。其定義了在該文檔中會被spider處理的可用的namespace。prefix及url會被自動調(diào)用redister_namespace()生成namespace。可以通過itertag屬性中制定節(jié)點的namespace。
**adapt_response(response)**該方法在spider分析response前被調(diào)用。可以在response被分析前使用該函數(shù)來修改內(nèi)容。
**parse_node(response, selector)**當(dāng)節(jié)點符合提供的標(biāo)簽名時itertag該方法被調(diào)用。接收到的response以及相應(yīng)的Selector作為參數(shù)傳遞給該方法。該方法返回一個Item對象或者Request對象或者一個包含二者的可迭代對象。
**process_results(response, results)**當(dāng)spider返回結(jié)果時該方法被調(diào)用。設(shè)定該方法的目的是在結(jié)果返回給框架核心之前作最后的處理。
CSVFeedSpider
用來爬取CSV文件網(wǎng)頁
該spider除了其按行遍歷而不是節(jié)點之外其他和XMLFeedSpider十分類似,而每次迭代時調(diào)用的是parse_row().
delimiter在CSV文件中用于區(qū)分字段的分隔符。類型為string。默認(rèn)為’,’;
headers在CSV文件中包含的用來提取字段的行的列表。
**parse_row(response,row)**該方法接收一個response對象及一個以提供或檢測出來的header為鍵的字典。該spider中,你可以覆蓋adapt_response及process_results方法來進行預(yù)處理及后處理。
SitemapSpider
class scrapy.contrib.spiders.SitemapSpiderSitemapSpider使你爬取網(wǎng)站時可以通過Sitemaps來發(fā)現(xiàn)爬取的URL。其支持嵌套的sitemap,并能從robots.txt會獲取sitemap的url。
sitemap_urls包含你要爬取的url的sitemap的url列表。也可以指定為一個robots.txt,spider會從中分析并提取url。
sitemap_rules一個包含(regex,callback)元組的列表。
- regex是一個用于匹配從sitemap提供的url的正則表達式;可以是一個字符串或者編譯的正則對象。
- callback指定了匹配正則表達式的url的處理函數(shù)。可以是一個字符串或者callale。規(guī)則按順序進行匹配,之后第一個匹配才會被應(yīng)用。如果忽略該屬性,sitemap中發(fā)現(xiàn)的所有url將會被parse函數(shù)處理。
- sitemap_follow一個用于匹配要跟進的sitemap的正則表達式的列表。其僅僅被應(yīng)用在使用Sitemap index files來指向其他sitemap文件的站點。默認(rèn)情況下所有的sitemap都回被跟進。
- sitemap_alternate_links指定當(dāng)一個url又可選的鏈接時,是否跟進。有些非英文網(wǎng)站會在一個url塊內(nèi)提供其他語言的網(wǎng)站鏈接。
當(dāng) sitemap_alternate_links 設(shè)置時,兩個URL都會被獲取。 當(dāng) sitemap_alternate_links 關(guān)閉時,只有 http://example.com/ 會被獲取。默認(rèn) sitemap_alternate_links 關(guān)閉。
樣例
使用parse處理通過sitemap發(fā)現(xiàn)的所有url:
用特定的函數(shù)處理某些url,其他的使用另外的callback:
from scrapy.contrib.spiders import SitemapSpiderclass MySpider(SitemapSpider):sitemap_urls = ['http://www.example.com/sitemap.xml']sitemap_rules = [('/product/', 'parse_product'),('/category/', 'parse_category'),]def parse_product(self, response):pass # ... scrape product ...def parse_category(self, response):pass # ... scrape category ...跟進robots.txt文件定義的sitemap并只跟進包含有…sitemap_shop的url:
from scrapy.contrib.spiders import SitemapSpiderclass MySpider(SitemapSpider):sitemap_urls = ['http://www.example.com/robots.txt']sitemap_rules = [('/shop/', 'parse_shop'),]sitemap_follow = ['/sitemap_shops']def parse_shop(self, response):pass # ... scrape shop here ...在SitemapSpider中使用其他url:
from scrapy.contrib.spiders import SitemapSpiderclass MySpider(SitemapSpider):sitemap_urls = ['http://www.example.com/robots.txt']sitemap_rules = [('/shop/', 'parse_shop'),]other_urls = ['http://www.example.com/about']def start_requests(self):requests = list(super(MySpider, self).start_requests())requests += [scrapy.Request(x, self.parse_other) for x in self.other_urls]return requestsdef parse_shop(self, response):pass # ... scrape shop here ...def parse_other(self, response):pass # ... scrape other here ...總結(jié)
以上是生活随笔為你收集整理的Scrapy——基本用法(命令行工具、Item、Spiders)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 现代公司理论在线考试习题
- 下一篇: 使用Arduino的自动药物提醒