前一篇文章介紹了很多關(guān)于scrapy的進階知識,不過說歸說,只有在實際應(yīng)用中才能真正用到這些知識。所以這篇文章就來嘗試利用scrapy爬取各種網(wǎng)站的數(shù)據(jù)。
爬取百思不得姐
首先一步一步來,我們先從爬最簡單的文本開始。這里爬取的就是百思不得姐的的段子,都是文本。
首先打開段子頁面,用F12工具查看元素。然后用下面的命令打開scrapyshell。
scrapy shell http://www.budejie.com/text/
稍加分析即可得到我們要獲取的數(shù)據(jù),在介紹scrapy的第一篇文章中我就寫過一次了。這次就給上次那個爬蟲加上一個翻頁功能。
要獲取的是用戶名和對應(yīng)的段子,所以在items.py中新建一個類。
class BudejieItem(scrapy.Item): username = scrapy.Field() content = scrapy.Field()
爬蟲本體就這樣寫,唯一需要注意的就是段子可能分為好幾行,這里我們要統(tǒng)一合并成一個大字符串。選擇器的extract()方法默認會返回一個列表,哪怕數(shù)據(jù)只有一個也是這樣。所以如果數(shù)據(jù)是單個的,使用extract_first()方法。
import scrapyfrom scrapy_sample.items import BudejieItemclass BudejieSpider(scrapy.Spider): """百思不得姐段子的爬蟲""" name = 'budejie' start_urls = ['http://www.budejie.com/text/'] total_page = 1 def parse(self, response): current_page = int(response.css('a.z-crt::text').extract_first()) lies = response.css('div.j-r-list >ul >li') for li in lies: username = li.css('a.u-user-name::text').extract_first() content = '/n'.join(li.css('div.j-r-list-c-desc a::text').extract()) yield BudejieItem(username=username, content=content) if current_page < self.total_page: yield scrapy.Request(self.start_urls[0] + f'{current_page+1}')導(dǎo)出到文件
利用scrapy內(nèi)置的Feed功能,我們可以非常方便的將爬蟲數(shù)據(jù)導(dǎo)出為XML、JSON和CSV等格式的文件。要做的只需要在運行scrapy的時候用-o參數(shù)指定導(dǎo)出文件名即可。
scrapy crawl budejie -o f.jsonscrapy crawl budejie -o f.csvscrapy crawl budejie -o f.xml
如果出現(xiàn)導(dǎo)出漢字變成Unicode編碼的話,需要在配置中設(shè)置導(dǎo)出編碼。
FEED_EXPORT_ENCODING = 'utf-8'
保存到MongoDB
有時候爬出來的數(shù)據(jù)并不想放到文件中,而是存在數(shù)據(jù)庫中。這時候就需要編寫管道來處理數(shù)據(jù)了。一般情況下,爬蟲只管爬取數(shù)據(jù),數(shù)據(jù)是否重復(fù)是否有效都不是爬蟲要關(guān)心的事情。清洗數(shù)據(jù)、驗證數(shù)據(jù)、保存數(shù)據(jù)這些活,都應(yīng)該交給管道來處理。當然爬個段子的話,肯定是用不到清洗數(shù)據(jù)這些步驟的。這里用的是pymongo,所以首先需要安裝它。
pip install pymongo
代碼其實很簡單,用scrapy官方文檔的例子稍微改一下就行了。由于MongoDB的特性,所以這部分代碼幾乎是無縫遷移的,如果希望保存其他數(shù)據(jù),只需要改一下配置就可以了,其余代碼部分幾乎不需要更改。
新聞熱點
疑難解答