之前的文章我們介紹了幾種可以爬取網站資訊的模組,並根據這些模組爬取了《糗事百科》的糗百內容,本章我們來看一下用於專門爬取網站資訊的框架 Scrapy。
Scrapy是用純Python實現一個為了爬取網站資料、提取結構性資料而編寫的應用框架,用途非常廣泛。Scrapy 使用了 Twisted['twɪstɪd]
(其主要對手是Tornado)非同步網路框架來處理網路通訊,可以加快我們的下載速度,不用自己去實現非同步框架,並且包含了各種中介軟體介面,可以靈活的完成各種需求。
Scrapy架構圖
-
Scrapy Engine(引擎)
: 負責Spider
、ItemPipeline
、Downloader
、Scheduler
中間的通訊,訊號、資料傳遞等。 -
Scheduler(排程器)
: 它負責接受引擎
傳送過來的Request請求,並按照一定的方式進行整理排列,入隊,當引擎
需要時,交還給引擎
。 -
Downloader(下載器)
:負責下載Scrapy Engine(引擎)
傳送的所有Requests請求,並將其獲取到的Responses交還給Scrapy Engine(引擎)
,由引擎
交給Spider
來處理, -
Spider(爬蟲)
:它負責處理所有Responses,從中分析提取資料,獲取Item欄位需要的資料,並將需要跟進的URL提交給引擎
,再次進入Scheduler(排程器)
, -
Item Pipeline(管道)
:它負責處理Spider
中獲取到的Item,並進行進行後期處理(詳細分析、過濾、儲存等)的地方. -
Downloader Middlewares(下載中介軟體)
:你可以當作是一個可以自定義擴充套件下載功能的元件。 -
Spider Middlewares(Spider中介軟體)
:你可以理解為是一個可以自定擴充套件和操作引擎
和Spider
中間通訊
的功能元件(比如進入Spider
的Responses;和從Spider
出去的Requests)
Scrapy框架官方網址:http://doc.scrapy.org/en/latest
Scrapy中文維護站點:http://scrapy-chs.readthedocs.io/zh_CN/latest/index.html
我們可以通過 pip install scrapy 進行 scrapy 框架的下載安裝。
接下來我們就來建立一個簡單的爬蟲目錄並對其中的目錄結構進行說明。
首先我們進入我們的工作目錄,然後在終端執行 scrapy startproject qiushi ,這樣我們就建立了一個叫 qiushi 的基於 scrapy 框架構建的爬蟲專案,目錄結構如下:
下面來簡單介紹一下各個主要檔案的作用:
scrapy.cfg :專案的配置檔案
qiushi/ :專案的Python模組,將會從這裡引用程式碼
qiushi/items.py :專案的目標檔案
qiushi/middlewares/ :專案的中介軟體
qiushi/pipelines.py :專案的管道檔案
qiushi/settings.py :專案的設定檔案
對於目錄中的 __init__.py 檔案,是一個空檔案,我們可以不去管理,但是也不能刪除,否則專案將無法執行。
items.py 使我們要寫程式碼邏輯的檔案,相關的爬取程式碼在這裡面寫。
middlewares.py 是一箇中介軟體檔案,可以將一些自寫的中介軟體在這裡面寫。
pipelines.py 是一個管道檔案,我們爬取資訊的處理可以在這裡面寫。
settings.py 是一個設定檔案,裡面是我們爬取資訊的一些相關資訊,我們可以根據需要對其進行球蓋,當然也可以按照裡面給定的預設設定。
接下來我們就來爬取一下之前我們爬取過的糗百的內容。
我們要爬取的網站是 https://www.qiushibaike.com/text/page/1/ 。
我們通過 Xpath Helper 的谷歌外掛經過分析獲取到我們想要的內容為: //div[contains(@id,"qiushi_tag")]
我們要爬取的是釋出糗百的 作者,頭像和糗事內容。
我們開啟 items.py,然後將其改為如下程式碼:
1 import scrapy 2 3 class QiushiItem(scrapy.Item): 4 # define the fields for your item here like: 5 name = scrapy.Field() # 作者 6 imgUrl = scrapy.Field() # 頭像 7 content = scrapy.Field() # 內容
然後我們在 qiushi/qiushi/spiders 資料夾下建立一個 qiushiSpider.py 的檔案,程式碼如下:
1 import scrapy 2 from ..items import QiushiItem 3 4 5 class QiushiSpider(scrapy.Spider): 6 # 爬蟲名 7 name = "qiubai1" 8 # 允許爬蟲作用的範圍,不能越界 9 allowd_domains = ["https://www.qiushibaike.com/"] 10 # 爬蟲起始url 11 start_urls = ["https://www.qiushibaike.com/text/page/1/"] 12 13 # 我們無需再像之前利用 urllib 庫那樣去請求地址返回資料,在 scrapy 框架中直接利用下面的 parse 方法進行資料處理即可。 14 def parse(self, response): 15 # 通過 scrayy 自帶的 xpath 匹配想要的資訊 16 qiushi_list = response.xpath('//div[contains(@id,"qiushi_tag")]') 17 for site in qiushi_list: 18 # 例項化從 items.py 匯入的 QiushiItem 類 19 item = QiushiItem() 20 # 根據查詢發現匿名使用者和非匿名使用者的標籤不一樣 21 try: 22 # 非匿名使用者 23 username = site.xpath('./div/a/img/@alt')[0].extract() # 作者 24 imgUrl = site.xpath('./div/a/img/@src')[0].extract() # 頭像 25 except Exception: 26 # 匿名使用者 27 username = site.xpath('./div/span/img/@alt')[0].extract() # 作者 28 imgUrl = site.xpath('./div/span/img/@src')[0].extract() # 頭像 29 content = site.xpath('.//div[@class="content"]/span[1]/text()').extract() 30 item['username'] = username 31 item['imgUrl'] = "https:" + imgUrl 32 item['content'] = content 33 34 # 將獲取的資料交給 pipeline 管道檔案 35 yield item
接下來我們開啟 settings.py,settings.py 內可以根據我們的需求自己去修改,由於內容過多,在後續的章節如果有需要用到的我們單獨再說。
參考文件:https://scrapy-chs.readthedocs.io/zh_CN/1.0/topics/settings.html#topics-settings-ref
在該案例中我們需要做的修改如下:
1 # Crawl responsibly by identifying yourself (and your website) on the user-agent 2 USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36' 3 # Configure item pipelines 4 # See https://doc.scrapy.org/en/latest/topics/item-pipeline.html 5 ITEM_PIPELINES = { 6 'qiushi.pipelines.QiushiPipeline': 300, 7 }
在上面的程式碼中,我們加入了請求報頭,然後注入一個管道檔案,接下來我們開啟 oippelines.py 來完成這個管道檔案,程式碼如下:
1 import json 2 3 4 class QiushiPipeline(object): 5 def __init__(self): 6 self.file = open('qiushi.json', 'a') 7 8 def process_item(self, item, spider): 9 content = json.dumps(dict(item), ensure_ascii=False) + ",\n" 10 self.file.write(content) 11 return item 12 13 def close_spider(self, spider): 14 self.file.close()
這個管道檔案其實就是我們將爬取到的資料儲存到本地一個叫 qiushi.json 的檔案中,其中 def process_item 會接受我們的資料 item,我們就可以對其進行相關操作了。
至此我們就完成了一個簡單的爬取糗百的爬蟲,可以看出我們不需要再像之前那樣考慮太多操作時的細節,scrapy 框架會自動為我們處理,我們只需要按照相應的流程對我們的資料做處理就行了。
在控制檯輸入 scrapy crawl qiubai 即可執行改程式,其中“qiubai” qiushiSpider.py 中為我們定義的 name 名,最終結果如下: