之前的文章我們介紹了幾種可以爬取網站信息的模塊,並根據這些模塊爬取了《糗事百科》的糗百內容,本章我們來看一下用於專門爬取網站信息的框架 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 名,最終結果如下: