前文傳送門: 小白學(xué) Python 爬蟲(2):前置準(zhǔn)備(一)基本類庫(kù)的安裝 小白學(xué) Python 爬蟲(3):前置準(zhǔn)備(二)Linux基礎(chǔ)入門 小白學(xué) Python 爬蟲(4):前置準(zhǔn)備(三)Docker基礎(chǔ)入門 小白學(xué) Python 爬蟲(5):前置準(zhǔn)備(四)數(shù)據(jù)庫(kù)基礎(chǔ) 小白學(xué) Python 爬蟲(6):前置準(zhǔn)備(五)爬蟲框架的安裝 小白學(xué) Python 爬蟲(7):HTTP 基礎(chǔ) 小白學(xué) Python 爬蟲(8):網(wǎng)頁(yè)基礎(chǔ) 小白學(xué) Python 爬蟲(9):爬蟲基礎(chǔ) 小白學(xué) Python 爬蟲(10):Session 和 Cookies 小白學(xué) Python 爬蟲(11):urllib 基礎(chǔ)使用(一) 小白學(xué) Python 爬蟲(12):urllib 基礎(chǔ)使用(二) 小白學(xué) Python 爬蟲(13):urllib 基礎(chǔ)使用(三) 小白學(xué) Python 爬蟲(14):urllib 基礎(chǔ)使用(四) 小白學(xué) Python 爬蟲(15):urllib 基礎(chǔ)使用(五) 小白學(xué) Python 爬蟲(16):urllib 實(shí)戰(zhàn)之爬取妹子圖 小白學(xué) Python 爬蟲(17):Requests 基礎(chǔ)使用 小白學(xué) Python 爬蟲(18):Requests 進(jìn)階操作 小白學(xué) Python 爬蟲(19):Xpath 基操 小白學(xué) Python 爬蟲(20):Xpath 進(jìn)階 小白學(xué) Python 爬蟲(21):解析庫(kù) Beautiful Soup(上) 小白學(xué) Python 爬蟲(22):解析庫(kù) Beautiful Soup(下) 小白學(xué) Python 爬蟲(23):解析庫(kù) pyquery 入門 小白學(xué) Python 爬蟲(24):2019 豆瓣電影排行 小白學(xué) Python 爬蟲(26):為啥買不起上海二手房你都買不起 小白學(xué) Python 爬蟲(27):自動(dòng)化測(cè)試框架 Selenium 從入門到放棄(上) 小白學(xué) Python 爬蟲(28):自動(dòng)化測(cè)試框架 Selenium 從入門到放棄(下) 小白學(xué) Python 爬蟲(29):Selenium 獲取某大型電商網(wǎng)站商品信息 小白學(xué) Python 爬蟲(30):代理基礎(chǔ) 小白學(xué) Python 爬蟲(31):自己構(gòu)建一個(gè)簡(jiǎn)單的代理池 小白學(xué) Python 爬蟲(32):異步請(qǐng)求庫(kù) AIOHTTP 基礎(chǔ)入門 小白學(xué) Python 爬蟲(33):爬蟲框架 Scrapy 入門基礎(chǔ)(一) 引言在上一篇文章 小白學(xué) Python 爬蟲(33):爬蟲框架 Scrapy 入門基礎(chǔ)(一) 中,我們簡(jiǎn)單的使用了 Spider 抓取到了我們需要的信息,我們簡(jiǎn)單的將我所需要的信息通過(guò) 在我們實(shí)際使用爬蟲的過(guò)程中,我們更多的是需要將數(shù)據(jù)保存起來(lái),并不是直接輸出至控制臺(tái),本篇文章接著講我們?nèi)绾螌?Spider 抓取到的信息保存起來(lái)。 ItemItem 的主要目的是從非結(jié)構(gòu)化源(通常是網(wǎng)頁(yè))中提取結(jié)構(gòu)化數(shù)據(jù)。 Scrapy Spider可以將提取的數(shù)據(jù)作為Python字典返回。Python字典雖然方便且熟悉,但缺乏結(jié)構(gòu):很容易在字段名稱中輸入錯(cuò)誤或返回不一致的數(shù)據(jù),尤其是在具有許多蜘蛛的大型項(xiàng)目中。 為了定義常見(jiàn)的輸出數(shù)據(jù)格式, Scrapy 提供了 Item 該類。 Item 對(duì)象是用于收集抓取數(shù)據(jù)的簡(jiǎn)單容器。它們提供了類似于字典的 API ,具有方便的語(yǔ)法來(lái)聲明其可用字段。 接下來(lái),我們來(lái)創(chuàng)建一個(gè) Item 。 創(chuàng)建 Item 需要繼承 scrapy.Item 類,并且定義類型為 scrapy.Field 的字段。 在前面一篇文章中,我們的目的想要獲取的字段有 text 、 author 、 tags 。 那么,我們定義的 Item 類如下,這里直接修改 items.py 文件: import scrapy class QuoteItem(scrapy.Item): text = scrapy.Field() author = scrapy.Field() tags = scrapy.Field() 接下來(lái)就是我們?nèi)绾我?first_scrapy 項(xiàng)目中使用這個(gè) Item 了,修改之前的 QuotesSpider 如下: import scrapy from first_scrapy.items import QuoteItem class QuotesSpider(scrapy.Spider): name = 'quotes' allowed_domains = ['quotes.'] start_urls = ['http://quotes./'] def parse(self, response): quotes = response.css('.quote') for quote in quotes: item = QuoteItem() item['text'] = quote.css('.text::text').extract_first() item['author'] = quote.css('.author::text').extract_first() item['tags'] = quote.css('.tags .tag::text').extract() yield item 接下來(lái),我們可以通過(guò)最簡(jiǎn)單的命令行將我們剛才獲取到的數(shù)據(jù)保存為 json 文件,命令如下: scrapy crawl quotes -o quotes.json 執(zhí)行后可以看到在當(dāng)前目錄下生成了一個(gè)名為 輸出格式還支持很多種,例如 csv、xml、pickle、marshal 等,常見(jiàn)的輸出語(yǔ)句如下: scrapy crawl quotes -o quotes.csv scrapy crawl quotes -o quotes.xml scrapy crawl quotes -o quotes.pickle scrapy crawl quotes -o quotes.marshal 直到這里,我們簡(jiǎn)單的將獲取到的數(shù)據(jù)導(dǎo)出成了 json 文件,這就結(jié)束了么? 當(dāng)然沒(méi)有,前一篇文章我們只是簡(jiǎn)單的獲取了當(dāng)前頁(yè)面的內(nèi)容,如果我們想抓取后續(xù)頁(yè)面的內(nèi)容怎么做呢? 當(dāng)然,第一步我們需要先觀察后面一頁(yè)的鏈接:http://quotes./page/2 。 接下來(lái),我們需要構(gòu)造一個(gè)訪問(wèn)下一頁(yè)的請(qǐng)求,這時(shí)我們可以使用 scrapy.Request 。 這里我們使用
那么接下來(lái)我們要做的就是使用選擇器得到下一頁(yè)鏈接并生成請(qǐng)求,使用 scrapy.Request 訪問(wèn)此鏈接,進(jìn)行新一輪的數(shù)據(jù)抓取。 添加的代碼如下: next = response.css('.pager .next a::attr("href")').extract_first() url = response.urljoin(next) yield scrapy.Request(url=url, callback=self.parse) 現(xiàn)在,改動(dòng)后的 Spider 類整體代碼如下: # -*- coding: utf-8 -*- import scrapy from first_scrapy.items import QuoteItem class QuotesSpider(scrapy.Spider): name = 'quotes' allowed_domains = ['quotes.'] start_urls = ['http://quotes./'] def parse(self, response): quotes = response.css('.quote') for quote in quotes: item = QuoteItem() item['text'] = quote.css('.text::text').extract_first() item['author'] = quote.css('.author::text').extract_first() item['tags'] = quote.css('.tags .tag::text').extract() yield item next = response.css('.pager .next a::attr("href")').extract_first() url = response.urljoin(next) yield scrapy.Request(url=url, callback=self.parse) 再次使用命令執(zhí)行這個(gè) Spider ,得到的結(jié)果如下(注意,如果前面生成過(guò) json 文件,記得刪除后再運(yùn)行,否則會(huì)直接追加寫): 可以看到,數(shù)據(jù)增加了許多,說(shuō)明我們抓取后續(xù)頁(yè)面的數(shù)據(jù)成功。 到這里就結(jié)束了么?怎么可能,我們這里只是簡(jiǎn)單的將數(shù)據(jù)保存在了 json 文件中,并不方便我們的取用,這里我們可以將數(shù)據(jù)保存在我們所需要的數(shù)據(jù)庫(kù)中。 Item Pipeline當(dāng)我們想將數(shù)據(jù)保存在數(shù)據(jù)庫(kù)中時(shí),可以使用 Item Pipeline ,Item Pipeline 為項(xiàng)目管道。 這個(gè)管道的典型用途有:
本示例選擇保存的數(shù)據(jù)為 MongoDB ,接下來(lái),我們會(huì)將前面查詢出來(lái)的數(shù)據(jù)保存在 MongoDB 中。 emmmmmmmmmm,如果要問(wèn)小編 MongoDB 怎么安裝的話,簡(jiǎn)單來(lái)講,直接使用 Docker 進(jìn)行安裝,只需幾個(gè)簡(jiǎn)單的命令即可: docker pull mongo (拉取鏡像 默認(rèn)最新版本) docker images (查看鏡像) docker run -p 27017:27017 -td mongo (啟動(dòng)鏡像) docker ps (查看啟動(dòng)的鏡像) 如果不出意外,以上這幾句話執(zhí)行一下就可以了。連接工具可以使用 Navicat 。 這里我們直接修改 pipelines.py 文件,之前使用命令自動(dòng)生成的內(nèi)容可以全都刪掉,寫入以下內(nèi)容: # -*- coding: utf-8 -*- from scrapy.exceptions import DropItem class TextPipeline(object): def process_item(self, item, spider): if item['text']: return item else: return DropItem('Missing Text') 這里我們實(shí)現(xiàn)了 process_item() 方法,其參數(shù)是 item 和 spider。 這里簡(jiǎn)單判斷了當(dāng)前的 text 是否存在,如果不存在則直接拋出 DropItem 異常,如果存在則直接返回 item 。 接下來(lái),我們將處理后的 item 存入 MongoDB,定義另外一個(gè) Pipeline。同樣在 pipelines.py 中,我們實(shí)現(xiàn)另一個(gè)類 MongoPipeline,內(nèi)容如下所示: import pymongo class MongoPipeline(object): def __init__(self, mongo_uri, mongo_db): self.mongo_uri = mongo_uri self.mongo_db = mongo_db @classmethod def from_crawler(cls, crawler): return cls(mongo_uri=crawler.settings.get('MONGO_URI'), mongo_db=crawler.settings.get('MONGO_DB') ) def open_spider(self, spider): self.client = pymongo.MongoClient(self.mongo_uri) self.db = self.client[self.mongo_db] def process_item(self, item, spider): name = item.__class__.__name__ self.db[name].insert(dict(item)) return item def close_spider(self, spider): self.client.close() MongoPipeline 類實(shí)現(xiàn)了 API 定義的另外幾個(gè)方法。
定義好 TextPipeline 和 MongoPipeline 這兩個(gè)類后,我們需要在 settings.py 中使用它們。MongoDB 的連接信息還需要定義。 在 settings.py 中加入如下內(nèi)容: ITEM_PIPELINES = { 'first_scrapy.pipelines.TextPipeline': 300, 'first_scrapy.pipelines.MongoPipeline': 400, } MONGO_URI='localhost' MONGO_DB='first_scrapy' 再次執(zhí)行爬取命令: scrapy crawl quotes 執(zhí)行結(jié)果如下: 可以看到,在 MongoDB 中創(chuàng)建了一個(gè) QuoteItem 的表,表中保存了我們剛才抓取到的數(shù)據(jù)。 示例代碼本系列的所有代碼小編都會(huì)放在代碼管理倉(cāng)庫(kù) Github 和 Gitee 上,方便大家取用。 參考https://docs./en/latest/topics/request-response.html |
|
來(lái)自: 易禪浮屠 > 《小白學(xué)爬蟲系列》