1. 事前準(zhǔn)備:
- 閱讀[scrapy官方文檔] [scrapy doc]至少一次
- 了解scrapy的基本命令及弄懂scrapy文檔中例子的項(xiàng)目結(jié)構(gòu)等基本信息
下文將假設(shè)大家已經(jīng)有了以上準(zhǔn)備墩划, 對(duì)一些細(xì)節(jié)不會(huì)詳細(xì)闡述拇厢, 如有不懂可以先翻翻文檔或留言詢問(wèn) - 下載本例子源碼(文章末尾)
2. 豆瓣頁(yè)面分析
我們準(zhǔn)備'下手'的是豆瓣推理小說(shuō)的數(shù)據(jù)德挣,截圖如下
目前(2015-4-16)豆瓣共有629頁(yè)的推理小說(shuō)悄晃, 每頁(yè)有15本書锈至,一共9000多本書
我們來(lái)用chrome審查元素功能看看
scrapy爬取的是html網(wǎng)頁(yè)源代碼隧膏,審查元素看的是經(jīng)過(guò)js處理后的頁(yè)面斗幼,有些html頁(yè)是由js輸出的愚战,有些會(huì)與html網(wǎng)頁(yè)源代碼不一樣盯串,這里豆瓣的書籍信息不是經(jīng)過(guò)js輸出的氯檐,所以可以放心這樣干
稍加分析,并可以知道這些書都放在一個(gè)class='mod book-list'的div內(nèi)体捏,在這個(gè)div內(nèi)分別用dl, dt這樣的標(biāo)簽裝載書籍的信息冠摄, 在寫爬蟲的時(shí)候我們可以直接用xpath,或css取出這些信息的標(biāo)簽.
3.開始寫爬蟲
首先執(zhí)行兩個(gè)命令
scrapy startproject db_spider
在創(chuàng)建的目錄下,即xxx/db_pisder/下執(zhí)行
scrapy genspider -t crawl douban douban.com
現(xiàn)在的項(xiàng)目目錄結(jié)構(gòu)如下圖所示
關(guān)于scrapy的這幾個(gè)文件是什么意思我就不詳細(xì)介紹了,相信看過(guò)文檔的人應(yīng)該也有所了解译打。
接下來(lái)我們?cè)趇tems.py里定義我們的數(shù)據(jù)對(duì)象
要抓取的東西如圖所示耗拓,按照從上到下,從左到右分別在items.py里定義為如下字段
接下來(lái)奏司, 我們要在spiders/douban.py寫關(guān)于爬蟲的東西
這些配置的意思是乔询,從http://www.douban.com/tag/推理/book?start=0 這個(gè)頁(yè)面開始, 遇到域名為douban.com且符合'start=\d+$'的鏈接則調(diào)用parse_item解析頁(yè)面并跟進(jìn)這個(gè)鏈接查找是否有符合規(guī)則的鏈接韵洋。
接下來(lái)我們要寫parse_item函數(shù),在分析頁(yè)面的時(shí)候竿刁,我們已經(jīng)確定要爬取哪些信息』拼福現(xiàn)在在parse_item里寫的就是從頁(yè)面里獲取這些信息, 并存在items中食拜。
我們可以先在db_spider目錄下執(zhí)行scrapy shell http://www.douban.com/tag/推理/book?start=0
會(huì)得到一個(gè)用于調(diào)試的命令行鸵熟, 如下所示:
我們可以用
view(response)
在瀏覽器中打開這個(gè)鏈接,這個(gè)鏈接看到的頁(yè)面就是爬蟲看到的頁(yè)面了负甸,之前說(shuō)過(guò)了流强,用js輸出的頁(yè)面跟爬蟲看到的頁(yè)面有時(shí)會(huì)不一樣,在爬取時(shí)可能看不到我們要的信息呻待,在爬復(fù)雜的網(wǎng)站時(shí)要注意打月。然后我們可以在這個(gè)命令行內(nèi),對(duì)response進(jìn)行xpath,css操作得到標(biāo)簽蚕捉,比如說(shuō)我們要得到小說(shuō)數(shù)據(jù)圖中的白夜叉這個(gè)書名,我們可以根據(jù)chrome的審查元素右鍵的copy xpath或copy css path功能得到標(biāo)簽的路徑
我們得到的路徑可能是這樣的:
構(gòu)造了一個(gè)之后奏篙,其它就簡(jiǎn)單了, 這里直接給出所有項(xiàng)的代碼迫淹, 如果覺(jué)得xpath和css有困難的話秘通,建議再看一下scrapy文檔里的例子及xpath和css的文檔。
def parse_item(self, response):
items = []
book_list = response.css('div.mod.book-list dl')
for book in book_list:
item = DbSpiderItem()
try:
item['book_name'] = book.xpath('dd/a/text()').extract()[0]
item['book_star'] = book.xpath('dd/div[1]/span[1]/@class').extract()[0][7:]
item['book_rating'] = book.xpath('dd/div[1]/span[2]/text()').extract()[0]
item['book_eval'] = book.xpath('dd/div[1]/span[3]/text()').extract()[0]
desc = book.xpath('dd/div[2]/text()').extract()[0].strip().split('/')
item['book_price'] = desc.pop()
item['book_publish_date'] = desc.pop()
item['book_publish'] = desc.pop()
item['book_author'] = '/'.join(desc)
except:
pass
items.append(item)
return items
這里注意一下代碼里的try,except塊, 這是為了豆瓣的書數(shù)據(jù)的特殊處理敛熬,因?yàn)槎拱陼臄?shù)據(jù)格式并不是全部都一致肺稀,有那么幾本沒(méi)有出版社或者沒(méi)有出版日期,甚至沒(méi)有評(píng)分荸型。如下圖盹靴,我們忽略這些個(gè)例就行了炸茧。
到此,我們的爬蟲就寫完了瑞妇,我們還需要設(shè)置一下settings里的DOWNLOAD_DELAY=2
,這很重要,因?yàn)槿绻麩o(wú)間隔的去爬梭冠,很快會(huì)被豆瓣ban掉的辕狰。
一切準(zhǔn)備完畢,我們可以試一下scrapy crawl douban -o book_data.json
來(lái)爬取數(shù)據(jù)并轉(zhuǎn)化成json格式控漠。
爬蟲孜孜不倦地開始爬數(shù)據(jù)了, 但我們要爬取的只有629頁(yè)蔓倍, 630頁(yè)之后的書都沒(méi)有了,爬蟲卻停不下來(lái)盐捷。怎么辦偶翅?除了用ctrl+c(兩次)
強(qiáng)制停止外,我們可以在Rule里面把正則式改成這樣
最多匹配到999頁(yè)了碉渡,如果還是覺(jué)得不爽聚谁,可以查查scrapy的CloseSpider異常,拋出該異持团担可以暫停/停止爬蟲形导。
最終我們爬取的部分?jǐn)?shù)據(jù)如下环疼,
把json改成{'Record': [{book_data1,book_data2}]}的形式,可以用導(dǎo)入工具(Navicat Premium)導(dǎo)入數(shù)據(jù)庫(kù)中朵耕,當(dāng)然炫隶,你也可以自己寫個(gè)插入語(yǔ)句放入數(shù)據(jù)庫(kù)。
4.總結(jié)
本篇文章到此結(jié)束阎曹, 其實(shí)也就相當(dāng)于scrapy官方文檔的例子的擴(kuò)展伪阶,只是比那個(gè)例子更結(jié)合實(shí)際一點(diǎn),沒(méi)有講什么特別的東西处嫌,我們可以發(fā)現(xiàn)望门,用scrapy定制這個(gè)簡(jiǎn)易爬蟲,其實(shí)不過(guò)100行的代碼锰霜,還是十分的簡(jiǎn)單易用的筹误。
例子源碼請(qǐng)戳:git源碼
[scrapy doc]: http://scrapy-chs.readthedocs.org/zh_CN/latest/index.html "scrapy官方中文文檔"