不想當(dāng)將軍的士兵不是好士兵,同理,不想當(dāng)主程的程序員不是好程序員~
上一節(jié)我們講了Scrapy的初步用法,我們已經(jīng)學(xué)會了如何創(chuàng)建scrapy工程,如何編寫簡單的爬蟲。
本節(jié)目標
- 學(xué)會Scrapy item的創(chuàng)建及使用
- 使用Scrapy將抓取到的數(shù)據(jù)存入json
- 使用Scrapy Pipeline做數(shù)據(jù)處理
- 學(xué)會暫停工程與重新開始工程
代碼預(yù)覽
- items.py
class TutorialItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
pass
class xianyuItem(scrapy.Item):
title = scrapy.Field()
url = scrapy.Field()
pass
- pipelines.py
import pymongo
class TutorialPipeline(object):
def open_spider(self, spider):
self.client = pymongo.MongoClient('localhost', 27017)
self.test = self.client['test']
self.testData = self.test['testData']
pass
def process_item(self, item, spider):
data = {
'title': item['title'],
'url': item['url']
}
self.testData.insert_one(data)
return item
def close_spider(self, spider):
pass
- spider.py
#coding:utf-8
import scrapy
from bs4 import BeautifulSoup
from ..items import xianyuItem
class testSpider(scrapy.Spider):
name = 'test'
start_urls = ['http://tj.ganji.com/fang1/']
def parse(self, response):
print 'lalala'
for title in response.xpath('//*[contains(concat( " ", @class, " " ), concat( " ", "js-title", " " ))]'):
url = title.xpath('@href').extract()[0]
if url.find('http')==-1:
url = 'http://tj.ganji.com'+url
yield scrapy.Request(url, self.detail)
def detail(self, response):
data = BeautifulSoup(response.body, 'lxml')
title = data.select('div.content.clearfix > div.leftBox > div.col-cont.title-box > h1')
item = xianyuItem()
item['title'] = title[0].get_text()
item['url'] = response.url
return item
- settings.py
ITEM_PIPELINES = {
'tutorial.pipelines.TutorialPipeline': 300,
}
代碼剖析
今天的代碼由三部分主體構(gòu)成,首先來看items.py
class xianyuItem(scrapy.Item):
title = scrapy.Field()
url = scrapy.Field()
pass
其實很好理解力,定義一個我們自己的item結(jié)構(gòu),里面有兩個field,一個是title用來存儲抓來的標題,一個是url用來存儲抓來的url,我們直接跳到使用部分。
看spider.py,首先:
from ..items import xianyuItem
這里需要注意的是,因為items.py和我們的spider.py并不在同級目錄,如果要import需要在前面加上..表示上級目錄,當(dāng)然也可以這樣
from tutorial.items import xianyuItem
但是這樣會在pycharm里面報錯,我個人不喜歡看到紅字~推薦用上面的方式。我們來看detail函數(shù):
def detail(self, response):
data = BeautifulSoup(response.body, 'lxml')
title = data.select('div.content.clearfix > div.leftBox > div.col-cont.title-box > h1')
item = xianyuItem()
item['title'] = title[0].get_text()
item['url'] = response.url
return item
我們先創(chuàng)建一個xianyuItem對象,然后給里面每個field賦值,最后return這個對象。這樣,item就會被pipeline抓到。接下來我們用命令把抓來的數(shù)據(jù)導(dǎo)入到j(luò)son文件中。進入tutorial項目跟目錄,執(zhí)行
scrapy crawl test -o test.json -t json
-o表示文件寫入目錄 -t 表示格式,執(zhí)行完后打開test.json結(jié)果如圖:

這樣就可以把數(shù)據(jù)存入json中,接下來我們看看pipelines.py
def open_spider(self, spider):
def process_item(self, item, spider):
def close_spider(self, spider):
三個函數(shù),第一個open_spider在spider開始的時候執(zhí)行,在這個函數(shù)中我們一般會連接數(shù)據(jù)庫,為數(shù)據(jù)存儲做準備,上面代碼中我連接了mongo數(shù)據(jù)庫。process_item函數(shù)在捕捉到item的時候執(zhí)行,一般我們會在這里做數(shù)據(jù)過濾并且把數(shù)據(jù)存入數(shù)據(jù)庫。close_spider在spider結(jié)束的時候執(zhí)行,一般用來斷開數(shù)據(jù)庫連接或者做數(shù)據(jù)收尾工作。
寫好pipeline之后我們需要到settings.py中開啟pipeline:
ITEM_PIPELINES = {
'tutorial.pipelines.TutorialPipeline': 300,
}
找到ITEM_PIPELINES 選項,把我們pipeline的路徑配置進去,后面的數(shù)字表示的是pipeline的執(zhí)行順序,我們可以寫多個pipeline用來過濾數(shù)據(jù)。執(zhí)行結(jié)果如下:

至此,我們本次代碼解析完畢。你們應(yīng)該已經(jīng)會使用item和pipeline了吧。如果還有困惑可以去看官方文檔~
小技巧
當(dāng)我們一個爬蟲項目量非常大時候,我們可能不能一次執(zhí)行完畢,需要分好幾次執(zhí)行,這時候,我們只需要在啟動爬蟲的時候鍵入命令
scrapy crawl xxx -s JOBDIR=job1
這時候我們可以看到任務(wù)開始執(zhí)行了,當(dāng)我們想要暫停的時候按下ctrl+c。當(dāng)我們想要恢復(fù)的時候鍵入:
scrapy crawl xxx -s JOBDIR=job1
這樣就可以繼續(xù)執(zhí)行了~~
這樣,我們今天所有的目標都達成了,鼓掌~~
寫在最后
這一章我們學(xué)習(xí)了一些進階技巧,那么下一章我們還是Scrapy,下一章我們會講如何使用CrawlSpider做多網(wǎng)頁扒取,同時也會講一些小技巧,比如,如何動態(tài)更改User-Agent進行反扒,如何設(shè)置扒取間隔等等~
有興趣的同學(xué)可以加群498945822一起交流學(xué)習(xí)哦~~
發(fā)現(xiàn)問題的同學(xué)歡迎指正,直接說就行,不用留面子,博主臉皮厚!