Scrapy 入門教程###
安裝Scrapy lxml很容易出問題 心赶。
1: 創(chuàng)建一個Scrapy 項(xiàng)目
scrapy starproject tutorial ## tutorial是項(xiàng)目名稱
會自動創(chuàng)建tutorial目錄:
scrapy.cfg : 項(xiàng)目的配置文件
item.py : 項(xiàng)目中的item 文件
pipelines.py : 項(xiàng)目中的piplines 文件
settings.py : 項(xiàng)目中的設(shè)置文件
spiders : 放置spider代碼的目錄
定義 Item
em
是保存爬取到的數(shù)據(jù)的容器柬祠;其使用方法和python字典類似禁炒, 并且提供了額外保護(hù)機(jī)制來避免拼寫錯誤導(dǎo)致的未定義字段錯誤拾稳。
類似在ORM中做的一樣肪跋,您可以通過創(chuàng)建一個 scrapy.Item
類寸宏, 并且定義類型為 scrapy.Field
的類屬性來定義一個Item宁炫。 (如果不了解ORM, 不用擔(dān)心,您會發(fā)現(xiàn)這個步驟非常簡單)
首先根據(jù)需要從dmoz.org獲取到的數(shù)據(jù)對item進(jìn)行建模氮凝。 我們需要從dmoz中獲取名字羔巢,url,以及網(wǎng)站的描述。 對此竿秆,在item中定義相應(yīng)的字段启摄。編輯 tutorial
目錄中的 items.py
文件:
import scrapy
class DmozItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
title = scrapy.Field()
link = scrapy.Field()
desc = scrapy.Field()
```
###編寫一個爬蟲(Spider)###
為了創(chuàng)建一個Spider , 必須繼承`scrapy.Spider`類, 并且定義以下三個屬性:
- `name` : 用于區(qū)別Spider幽钢, 名字需要唯一
- `start_url` : 包含了Spider 啟動的時候需要抓取了url列表歉备,因此,第一個被抓取的頁面將是其中之一匪燕,后續(xù)的URL則從初始的URL獲取到的數(shù)據(jù)提取
- `parse()` : 是spider的一個方法蕾羊。 被調(diào)用時,每個初始URL完成下載后生成的 [Response
](http://scrapy-chs.readthedocs.io/zh_CN/0.24/topics/request-response.html#scrapy.http.Response) 對象將會作為唯一的參數(shù)傳遞給該函數(shù)帽驯。 該方法負(fù)責(zé)解析返回的數(shù)據(jù)(response data)龟再,提取數(shù)據(jù)(生成item)以及生成需要進(jìn)一步處理的URL的 [Request
](http://scrapy-chs.readthedocs.io/zh_CN/0.24/topics/request-response.html#scrapy.http.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)
啟用命令 : scrapy craml 項(xiàng)目名
Scrapy為Spider的 start_urls
屬性中的每個URL創(chuàng)建了 [scrapy.Request
](http://scrapy-chs.readthedocs.io/zh_CN/0.24/topics/request-response.html#scrapy.http.Request) 對象吸申,并將 parse
方法作為回調(diào)函數(shù)(callback)賦值給了Request。
Request對象經(jīng)過調(diào)度享甸,執(zhí)行生成 [scrapy.http.Response
](http://scrapy-chs.readthedocs.io/zh_CN/0.24/topics/request-response.html#scrapy.http.Response) 對象并送回給spider [parse()
](http://scrapy-chs.readthedocs.io/zh_CN/0.24/topics/spiders.html#scrapy.spider.Spider.parse) 方法截碴。
###提取 Item ###
Scrapy 使用基于XPath 和 CSS 表達(dá)機(jī)制, Scrapy Selectors
列XPath 表達(dá)式對應(yīng)了含義:
- `/html/head/title` : 選擇HTML 中`<head>` 標(biāo)簽內(nèi)的`<title>`元素
- `/html/head/title/text()` : 選擇上面提到的`<title>`元素的文字
- `//td` :選擇所有的`<td>`元素
- `//div[@class='mine']` : 選擇所有帶具有`class='mine'` 屬性的`div`元素
為了配合XPath 蛉威, Scrapy 除了`selector` 之外日丹,還提供了方法避免每次response 中提取數(shù)據(jù)生成selector的麻煩。
Selector 有四個基礎(chǔ)方法
- `xpath()` : 傳入xpath表達(dá)式蚯嫌, 返回該表達(dá)式對應(yīng)的所有selector list 列表
- `css()` : 傳入CSS 表達(dá)式哲虾, 返回表達(dá)式內(nèi)所有selector list 列表
- `extract` :序列化該節(jié)點(diǎn)為unicode字符串并返回list
- `re()` : 根據(jù)傳入的正則表達(dá)式對數(shù)據(jù)進(jìn)行提取,返回unicode字符串list列表
### Spider 參數(shù) ###
在運(yùn)行`crawl` 可以添加 `-a ` 可以傳遞Spider參數(shù):
`scrapy crawl <name> -a category=electronics`
Spider在構(gòu)造器(constructor)中獲取參數(shù)
###Spider###
`name` : 定義名稱
`allowed_domains` : 可選择示。包含了spider允許爬取的域名(domain)列表(list)束凑。 當(dāng) [OffsiteMiddleware
](http://scrapy-chs.readthedocs.io/zh_CN/0.24/topics/spider-middleware.html#scrapy.contrib.spidermiddleware.offsite.OffsiteMiddleware) 啟用時, 域名不在列表中的URL不會被跟進(jìn)栅盲。
`start_urls` : URL列表汪诉。當(dāng)沒有制定特定的URL時,spider將從該列表中開始進(jìn)行爬取谈秫。 因此扒寄,第一個被獲取到的頁面的URL將是該列表之一。 后續(xù)的URL將會從獲取到的數(shù)據(jù)中提取拟烫。
`start_requests()`:
該方法必須返回一個可迭代對象(iterable)该编。該對象包含了spider用于爬取的第一個Request。
當(dāng)spider啟動爬取并且未制定URL時硕淑,該方法被調(diào)用课竣。 當(dāng)指定了URL時嘉赎,[make_requests_from_url()
](http://scrapy-chs.readthedocs.io/zh_CN/0.24/topics/spiders.html#scrapy.spider.Spider.make_requests_from_url) 將被調(diào)用來創(chuàng)建Request對象。 該方法僅僅會被Scrapy調(diào)用一次稠氮,因此您可以將其實(shí)現(xiàn)為生成器曹阔。
該方法的默認(rèn)實(shí)現(xiàn)是使用 [start_urls
](http://scrapy-chs.readthedocs.io/zh_CN/0.24/topics/spiders.html#scrapy.spider.Spider.start_urls) 的url生成Request。
如果您想要修改最初爬取某個網(wǎng)站的Request對象隔披,您可以重寫(override)該方法赃份。 例如,如果您需要在啟動時以POST登錄某個網(wǎng)站奢米,你可以這么寫:
def start_requests(self):
return [scrapy.FormRequest("http://www.example.com/login",
formdata={'user': 'john', 'pass': 'secret'},
callback=self.logged_in)]
def logged_in(self, response):
# here you would extract links to follow and return Requests for
# each of them, with another callback
pass
`log(message[, level, componet])`: 日志