Scrapy

Scrapy概述

Scrapy 是一個(gè)基于 Twisted 的異步處理框架,是純 Python 實(shí)現(xiàn)的爬蟲框架,其架構(gòu)清晰, 模塊之間的耦合程度低,可擴(kuò)展性極強(qiáng),可以靈活完成各種需求。 我們只需要定制開發(fā)幾個(gè)模塊就可以輕松實(shí)現(xiàn)一個(gè)爬蟲。它可以用來抓取Web站點(diǎn)并從頁面中提取結(jié)構(gòu)化的數(shù)據(jù),被廣泛的用于數(shù)據(jù)挖掘、數(shù)據(jù)監(jiān)測(cè)和自動(dòng)化測(cè)試等領(lǐng)域。下圖展示了Scrapy的基本架構(gòu),其中包含了主要組件和系統(tǒng)的數(shù)據(jù)處理流程(圖中帶數(shù)字的紅色箭頭)。

流程圖

組件

  1. Scrapy引擎(Engine):Scrapy引擎是用來控制整個(gè)系統(tǒng)的數(shù)據(jù)處理流程。(數(shù)據(jù)流處理、觸發(fā)事物、核心
  2. 調(diào)度器(Scheduler):調(diào)度器從Scrapy引擎接受請(qǐng)求并排序列入隊(duì)列,并在Scrapy引擎發(fā)出請(qǐng)求后返還給它們。
  3. 下載器(Downloader):下載器的主要職責(zé)是抓取網(wǎng)頁并將網(wǎng)頁內(nèi)容返還給蜘蛛(Spiders)。
  4. 蜘蛛(Spiders):蜘蛛是有Scrapy用戶自定義的用來解析網(wǎng)頁并抓取特定URL返回的內(nèi)容的類,每個(gè)蜘蛛都能處理一個(gè)域名或一組域名,簡(jiǎn)單的說就是用來定義特定網(wǎng)站的抓取和解析規(guī)則。(負(fù)責(zé)解析響應(yīng),生成提取結(jié)果和新的請(qǐng)求)
  5. 條目管道(Item Pipeline):條目管道的主要責(zé)任是負(fù)責(zé)處理有蜘蛛從網(wǎng)頁中抽取的數(shù)據(jù)條目,它的主要任務(wù)是清理、驗(yàn)證和存儲(chǔ)數(shù)據(jù)。當(dāng)頁面被蜘蛛解析后,將被發(fā)送到條目管道,并經(jīng)過幾個(gè)特定的次序處理數(shù)據(jù)。每個(gè)條目管道組件都是一個(gè)Python類,它們獲取了數(shù)據(jù)條目并執(zhí)行對(duì)數(shù)據(jù)條目進(jìn)行處理的方法,同時(shí)還需要確定是否需要在條目管道中繼續(xù)執(zhí)行下一步或是直接丟棄掉不處理。條目管道通常執(zhí)行的任務(wù)有:清理HTML數(shù)據(jù)、驗(yàn)證解析到的數(shù)據(jù)(檢查條目是否包含必要的字段)、檢查是不是重復(fù)數(shù)據(jù)(如果重復(fù)就丟棄)、將解析到的數(shù)據(jù)存儲(chǔ)到數(shù)據(jù)庫(kù)(關(guān)系型數(shù)據(jù)庫(kù)或NoSQL數(shù)據(jù)庫(kù))中。
  6. 中間件(Middlewares):中間件是介于Scrapy引擎和其他組件之間的一個(gè)鉤子框架,主要是為了提供自定義的代碼來拓展Scrapy的功能,包括下載器中間件和蜘蛛中間件。

數(shù)據(jù)處理流程

Scrapy的整個(gè)數(shù)據(jù)處理流程由Scrapy引擎進(jìn)行控制,通常的運(yùn)轉(zhuǎn)流程包括以下的步驟:

  1. 引擎詢問蜘蛛需要處理哪個(gè)網(wǎng)站,并讓蜘蛛將第一個(gè)需要處理的URL交給它。

  2. 引擎讓調(diào)度器將需要處理的URL放在隊(duì)列中。

  3. 引擎從調(diào)度那獲取接下來進(jìn)行爬取的頁面。

  4. 調(diào)度將下一個(gè)爬取的URL返回給引擎,引擎將它通過下載中間件發(fā)送到下載器。

  5. 當(dāng)網(wǎng)頁被下載器下載完成以后,響應(yīng)內(nèi)容通過下載中間件被發(fā)送到引擎;如果下載失敗了,引擎會(huì)通知調(diào)度器記錄這個(gè)URL,待會(huì)再重新下載。

  6. 引擎收到下載器的響應(yīng)并將它通過蜘蛛中間件發(fā)送到蜘蛛進(jìn)行處理。

  7. 蜘蛛處理響應(yīng)并返回爬取到的數(shù)據(jù)條目,此外還要將需要跟進(jìn)的新的URL發(fā)送給引擎。

  8. 引擎將抓取到的數(shù)據(jù)條目送入條目管道,把新的URL發(fā)送給調(diào)度器放入隊(duì)列中。

上述操作中的2-8步會(huì)一直重復(fù)直到調(diào)度器中沒有需要請(qǐng)求的URL,爬蟲停止工作。

安裝Scrapy

推薦使用Anacinda安裝:

conda install Scrapy

直接在已有的Python環(huán)境中安裝Scrapy:

a. 安裝lxml

pip install lxml

b.安裝pyOpenSSL
下載wheel文件
使用pip install后接下載文件路徑完成安裝

c.安裝Twisted

下載wheel文件:

選擇對(duì)應(yīng)版本

使用pip install后接下載文件路徑完成安裝

d.安裝PyWin32

下載wheel文件
使用pip install后接下載文件路徑完成安裝

也可以嘗試直接使用pip install pywin32命令嘗試,如果能夠成功便無須下載wheel文件

e.執(zhí)行pip install scrapy

簡(jiǎn)單使用

創(chuàng)建項(xiàng)目

scrapy startproject book
創(chuàng)建演示

創(chuàng)建爬蟲

scrapy genspider douban book.douban.com

genspider后的兩個(gè)參數(shù):第一個(gè)表示爬蟲的名稱,第二個(gè)表示網(wǎng)站的域名

創(chuàng)建演示

使用編譯器打開創(chuàng)建的項(xiàng)目

項(xiàng)目結(jié)構(gòu)

添加爬蟲內(nèi)容

爬取目標(biāo):編程類圖書
分析網(wǎng)絡(luò)請(qǐng)求:https://book.douban.com/tag/%E7%BC%96%E7%A8%8B?start=0&type=T(get請(qǐng)求、start后面的數(shù)字表示當(dāng)前頁數(shù)的20倍。通過循環(huán)生成頁數(shù)即可模擬翻頁發(fā)出的請(qǐng)求。因?yàn)閮?nèi)容比較多,本次只爬取前三十頁作為演示)
分析網(wǎng)頁結(jié)構(gòu):每一頁有二十本圖書的信息,每本圖書信息保存在一個(gè)li標(biāo)簽中,所以首先拿到li標(biāo)簽,在進(jìn)行下一步操作。繼續(xù)獲取圖書鏈接,書籍名稱,基本信息及簡(jiǎn)介。
爬取內(nèi)容:圖書鏈接,書籍名稱,基本信息及簡(jiǎn)介。

    def start_requests(self):
        headers = {
            'User-Agent': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)',
            'Accept': 'application/json, text/plain, */*',
            'Accept-Encoding': 'gzip, deflate, sdch',
            'Accept-Language': 'zh-CN,zh;q=0.8,en;q=0.6,ja;q=0.4,zh-TW;q=0.2,mt;q=0.2',
            'Connection': 'keep-alive',
            'X-Requested-With': 'XMLHttpRequest',
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        }
        for i in range(33):
            yield scrapy.Request(url='https://book.douban.com/tag/%E7%BC%96%E7%A8%8B?start={}&type=T'.format(i),
                                 headers=headers,
                                 method='GET',
                                 callback=self.parse,
                                 )

創(chuàng)建對(duì)象

class BookItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    book_link = scrapy.Field()
    book_name = scrapy.Field()
    book_info = scrapy.Field()
    book_explain = scrapy.Field()

解析對(duì)象

   def parse(self, response):
        book_all = response.xpath('//*[@id="subject_list"]/ul/li')
        for book_one in book_all:
            book = BookItem()
            book['book_link'] = book_one.xpath('./div[@class="info"]/h2/a/@href').extract_first().strip()
            book['book_name'] = book_one.xpath('./div[@class="info"]/h2/a/@title').extract_first().strip()
            book['book_info'] = book_one.xpath('./div[@class="info"]/div[@class="pub"]/text()').extract_first().strip()
            book['book_explain'] = book_one.xpath('./div[@class="info"]/p/text()').extract_first().strip()
            yield book

修改配置文件

ROBOTSTXT_OBEY = False

SPIDER_MIDDLEWARES = {
   'book.middlewares.BookSpiderMiddleware': 543,
}

FEED_EXPORT_ENCODING = 'utf-8'

執(zhí)行啟動(dòng)爬蟲的命令,并保存爬取內(nèi)容

scrapy crawl douban -o result.json

爬取內(nèi)容部分展示

爬取結(jié)果——儲(chǔ)存為json文件
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容