創建一個新的Scrapy項目
定義提取的Item
寫一個Spider用來爬行站點,並提取Items
寫一個Item Pipeline用來存儲提取出的Items
新建工程
在抓取之前,你需要新建一個Scrapy工程。進入一個你想用來保存代碼的目錄,然后執行:scrapy startproject tutorial
這個命令會在當前目錄下創建一個新目錄tutorial,它的結構如下:
- T:.
- │ scrapy.cfg
- │
- └─tutorial
- │ items.py
- │ pipelines.py
- │ settings.py
- │ __init__.py
- │
- └─spiders
- __init__.py
這些文件主要是:
scrapy.cfg: 項目配置文件
tutorial/: 項目python模塊, 呆會代碼將從這里導入
tutorial/items.py: 項目items文件
tutorial/pipelines.py: 項目管道文件
tutorial/settings.py: 項目配置文件
tutorial/spiders: 放置spider的目錄
定義Item
Items是將要裝載抓取的數據的容器,它工作方式像python里面的字典,但它提供更多的保護,比如對未定義的字段填充以防止拼寫錯誤。
它通過創建一個scrapy.item.Item類來聲明,定義它的屬性為scrpiy.item.Field對象,就像是一個對象關系映射(ORM).
我們通過將需要的item模型化,來控制從dmoz.org獲得的站點數據,比如我們要獲得站點的名字,url和網站描述,我們定義這三種屬性的域。要做到這點,我們編輯在tutorial目錄下的items.py文件,我們的Item類將會是這樣
- from scrapy.item import Item, Field
- class DmozItem(Item):
- title = Field()
- link = Field()
- desc = Field()
剛開始看起來可能會有些困惑,但是定義這些item能讓你用其他Scrapy組件的時候知道你的 items到底是什么。
第一個爬蟲(Spider)
Spider是用戶編寫的類,用於從一個域(或域組)中抓取信息。
他們定義了用於下載的URL的初步列表,如何跟蹤鏈接,以及如何來解析這些網頁的內容用於提取items。
要建立一個Spider,你必須為scrapy.spider.BaseSpider創建一個子類,並確定三個主要的、強制的屬性:
name:爬蟲的識別名,它必須是唯一的,在不同的爬蟲中你必須定義不同的名字.
start_urls:爬蟲開始爬的一個URL列表。爬蟲從這里開始抓取數據,所以,第一次下載的數據將會從這些URLS開始。其他子URL將會從這些起始URL中繼承性生成。
parse():爬蟲的方法,調用時候傳入從每一個URL傳回的Response對象作為參數,response將會是parse方法的唯一的一個參數,
這個方法負責解析返回的數據、匹配抓取的數據(解析為item)並跟蹤更多的URL。
下面是我們第一個爬蟲代碼,創建 ./tutorial/spiders/dmoz_spider.py
import scrapy
from scrapy.spiders import Spider
from scrapy.selector import Selector
from tutorial.items import DmozItem
class DmozSpider(scrapy.Spider):
name = "dmoz"
allowed_domains = ["dmoz.org"]
start_urls = [
"http://club.jd.com/review/1601991-1-1-0.html/",
"http://club.jd.com/review/1601991-1-2-0.html"
]
def parse(self, response):
sel = Selector(response)
sites = sel.xpath('//ul/li')
items = []
for i in range(0, 1 + 1):
divs = response.xpath('//div[@id="' + str(i) + '"]')
for zz in divs.xpath('.//dl'):
item = DmozItem()
item['prodid'] = '1601991'
item['userid'] = 'userid'
item['type'] = zz.xpath('.//dt/text()').extract_first().replace("\r\n", '')
item['desc'] = zz.xpath('.//dd/text()').extract_first().replace("\r\n", '')
items.append(item)
return items
為了讓我們的爬蟲工作,我們返回項目主目錄執行以下命令
.\tutorial>scrapy crawl dmoz
crawl dmoz 命令從dmoz.org域啟動爬蟲。 你將會獲得如下類似輸出
D:\python\one>scrapy crawl dmoz
2016-06-06 20:19:43 [scrapy] INFO: Scrapy 1.1.0 started (bot: tutorial)
2016-06-06 20:19:43 [scrapy] INFO: Overridden settings: {'SPIDER_MODULES': ['tutorial.spiders'], 'ROBOTST
XT_OBEY': True, 'NEWSPIDER_MODULE': 'tutorial.spiders', 'BOT_NAME': 'tutorial'}
2016-06-06 20:19:43 [scrapy] INFO: Enabled extensions:
['scrapy.extensions.corestats.CoreStats', 'scrapy.extensions.logstats.LogStats']
2016-06-06 20:19:44 [scrapy] INFO: Enabled downloader middlewares:
['scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware',
'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware',
'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware',
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware',
'scrapy.downloadermiddlewares.retry.RetryMiddleware',
'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware',
'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware',
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware',
'scrapy.downloadermiddlewares.redirect.RedirectMiddleware',
'scrapy.downloadermiddlewares.cookies.CookiesMiddleware',
'scrapy.downloadermiddlewares.chunked.ChunkedTransferMiddleware',
'scrapy.downloadermiddlewares.stats.DownloaderStats']
2016-06-06 20:19:44 [scrapy] INFO: Enabled spider middlewares:
['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware',
'scrapy.spidermiddlewares.offsite.OffsiteMiddleware',
'scrapy.spidermiddlewares.referer.RefererMiddleware',
'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware',
'scrapy.spidermiddlewares.depth.DepthMiddleware']
2016-06-06 20:19:44 [scrapy] INFO: Enabled item pipelines:
[]
2016-06-06 20:19:44 [scrapy] INFO: Spider opened
2016-06-06 20:19:44 [scrapy] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min
)
2016-06-06 20:19:45 [scrapy] DEBUG: Redirecting (302) to <GET http://www.jd.com/error2.aspx> from <G
ET http://club.jd.com/robots.txt>
2016-06-06 20:19:45 [scrapy] DEBUG: Crawled (200) <GET http://www.jd.com/error2.aspx> (referer: None
)
2016-06-06 20:19:45 [scrapy] DEBUG: Redirecting (302) to <GET http://www.jd.com/error2.aspx> from <G
ET http://club.jd.com/review/1601991-1-1-0.html/>
2016-06-06 20:19:45 [scrapy] DEBUG: Crawled (200) <GET http://www.jd.com/robots.txt> (referer: None)
2016-06-06 20:19:45 [scrapy] DEBUG: Crawled (200) <GET http://www.jd.com/error2.aspx> (referer: None
)
2016-06-06 20:19:45 [scrapy] DEBUG: Crawled (200) <GET http://club.jd.com/review/1601991-1-2-0.html>
(referer: None)
2016-06-06 20:19:45 [scrapy] INFO: Closing spider (finished)
2016-06-06 20:19:45 [scrapy] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 1344,
'downloader/request_count': 6,
'downloader/request_method_count/GET': 6,
'downloader/response_bytes': 29868,
'downloader/response_count': 6,
'downloader/response_status_count/200': 4,
'downloader/response_status_count/302': 2,
'finish_reason': 'finished',
'finish_time': datetime.datetime(2016, 6, 6, 12, 19, 45, 573034),
'log_count/DEBUG': 6,
'log_count/INFO': 7,
'response_received_count': 4,
'scheduler/dequeued': 3,
'scheduler/dequeued/memory': 3,
'scheduler/enqueued': 3,
'scheduler/enqueued/memory': 3,
'start_time': datetime.datetime(2016, 6, 6, 12, 19, 44, 968801)}
2016-06-06 20:19:45 [scrapy] INFO: Spider closed (finished)
注意包含 [dmoz]的行 ,那對應着我們的爬蟲。你可以看到start_urls中定義的每個URL都有日志行。因為這些URL是起始頁面,所以他們沒有引用(referrers),所以在每行的末尾你會看到 (referer: <None>).
在我們的 parse 方法的作用下,兩個文件被創建:分別是 Books 和 Resources,這兩個文件中有URL的頁面內容。
發生了什么事情?
Scrapy為爬蟲的 start_urls屬性中的每個URL創建了一個 scrapy.http.Request 對象 ,並將爬蟲的parse 方法指定為回調函數。
這些 Request首先被調度,然后被執行,之后通過parse()方法,scrapy.http.Response 對象被返回,結果也被反饋給爬蟲。
要開始shell,首先進入項目頂層目錄,然后輸入
T:\tutorial>scrapy shell http://club.jd.com/review/1601991-1-1-0.html
保存抓取的數據
保存信息的最簡單的方法是通過Feed exports,命令如下:
T:\tutorial>scrapy crawl dmoz -o items.json -t json
所有抓取的items將以JSON格式被保存在新生成的items.json 文件中
如果想用抓取的items做更復雜的事情,你可以寫一個 Item Pipeline(條目管道)。因為在項目創建的時候,一個專門用於條目管道的占位符文件已經隨着items一起被建立,目錄在tutorial/pipelines.py。如果你只需要存取這些抓取后的items的話,就不需要去實現任何的條目管道。
結束語
本教程簡要介紹了Scrapy的使用,但是許多其他特性並沒有提及。
深入了解,請訪問 初窺Scrapy — Scrapy 0.24.1 文檔 http://scrapy-chs.readthedocs.io/zh_CN/latest/intro/overview.html#intro-overview-item
部分參考於
Python抓取框架Scrapy入門教程 http://developer.51cto.com/art/201207/348012.htm
使用Python Scrapy抓取京東商城上商品評論 https://ask.hellobi.com/blog/seng/3216