此環節是在MAC OS中進行搭建
安裝scrapy
pip install scrapy 即可快速完成安裝
建立項目:
$ scrapy startproject tutorial
輸出如下:
New Scrapy project 'tutorial', using template directory '/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scrapy/templates/project', created in:
/Users/huilinwang/tutorial
You can start your first spider with:
cd tutorial
scrapy genspider example example.com
該目錄下結構如下:
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()
編寫第一個爬蟲(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.spiders.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)
name屬性很重要,不同spider不能使用相同的name
start_urls是spider抓取網頁的起始點,可以包括多個url
parse方法是spider抓到一個網頁以後預設調用的callback,避免使用這個名字來定義自己的方法。
當spider拿到url的内容以後,會調用parse方法,并且傳遞一個response參數給它,response包含了抓到的網頁的内容,在parse方法裡,你可以從抓到的網頁裡面解析資料。上面的代碼隻是簡單地把網頁内容儲存到檔案。
爬取
進入項目的根目錄,執行下列指令啟動spider:
scrapy crawl dmoz
有兩個包含url所對應的内容的檔案被建立了: Book , Resources 。
Scrapy為Spider的 start_urls 屬性中的每個URL建立了 scrapy.Request 對象,并将 parse 方法作為回調函數(callback)指派給了Request。
Request對象經過排程,執行生成 scrapy.http.Response 對象并送回給spider parse() 方法。
提取Item
從網頁中提取資料有很多方法。Scrapy使用了一種基于 XPath 和 CSS 表達式機制: Scrapy Selectors 。
Selector有四個基本的方法(點選相應的方法可以看到詳細的API文檔):
xpath(): 傳入xpath表達式,傳回該表達式所對應的所有節點的selector list清單 。
css(): 傳入CSS表達式,傳回該表達式所對應的所有節點的selector list清單.
extract(): 序列化該節點為unicode字元串并傳回list。
re(): 根據傳入的正規表達式對資料進行提取,傳回unicode字元串list清單。
在Shell中嘗試Selector選擇器
進入項目的根目錄,執行下列指令來啟動shell:
scrapy shell "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/"
當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)。
提取資料
嘗試從這些頁面中提取些有用的資料
在終端中輸入 response.body 來觀察HTML源碼并确定合适的XPath表達式。不過,這任務非常無聊且不易。您可以考慮使用Firefox的Firebug擴充來使得工作更為輕松。
檢視了網頁的源碼後,您會發現網站的資訊是被包含在 第二個 <ul> 元素中。
我們可以通過這段代碼選擇該頁面中網站清單裡所有 <li> 元素:
在我們的spider中加入這段代碼:
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):
for sel in response.xpath('//ul/li'):
title = sel.xpath('a/text()').extract()
link = sel.xpath('a/@href').extract()
desc = sel.xpath('text()').extract()
print title, link, desc
現在嘗試再次爬取dmoz.org,您将看到爬取到的網站資訊被成功輸出
/ul/li表示選擇所有的ul标簽下的li标簽
a/@href表示選擇所有a标簽的href屬性
a/text()表示選擇a标簽文本
a[@href="abc" target="_blank" rel="external nofollow" ]表示選擇所有href屬性是abc的a标簽
儲存爬取到的資料
最簡單存儲爬取的資料的方式是使用 Feed exports:
scrapy crawl dmoz -o items.json
該指令将采用 JSON 格式對爬取的資料進行序列化,生成 items.json 檔案。