之前的文章我們介紹了幾種可以爬取網站資訊的子產品,并根據這些子產品爬取了《糗事百科》的糗百内容,本章我們來看一下用于專門爬取網站資訊的架構 Scrapy。
Scrapy是用純Python實作一個為了爬取網站資料、提取結構性資料而編寫的應用架構,用途非常廣泛。Scrapy 使用了 Twisted
['twɪstɪd]
(其主要對手是Tornado)異步網絡架構來處理網絡通訊,可以加快我們的下載下傳速度,不用自己去實作異步架構,并且包含了各種中間件接口,可以靈活的完成各種需求。
Scrapy架構圖
-
: 負責Scrapy Engine(引擎)
、Spider
、ItemPipeline
、Downloader
中間的通訊,信号、資料傳遞等。Scheduler
-
: 它負責接受Scheduler(排程器)
發送過來的Request請求,并按照一定的方式進行整理排列,入隊,當引擎
需要時,交還給引擎
。引擎
-
:負責下載下傳Downloader(下載下傳器)
發送的所有Requests請求,并将其擷取到的Responses交還給Scrapy Engine(引擎)
,由Scrapy Engine(引擎)
交給引擎
來處理,Spider
-
:它負責處理所有Responses,從中分析提取資料,擷取Item字段需要的資料,并将需要跟進的URL送出給Spider(爬蟲)
,再次進入引擎
,Scheduler(排程器)
-
:它負責處理Item Pipeline(管道)
中擷取到的Item,并進行進行後期處理(詳細分析、過濾、存儲等)的地方.Spider
-
:你可以當作是一個可以自定義擴充下載下傳功能的元件。Downloader Middlewares(下載下傳中間件)
-
:你可以了解為是一個可以自定擴充和操作Spider Middlewares(Spider中間件)
和引擎
中間Spider
的功能元件(比如進入通信
的Responses;和從Spider
出去的Requests)Spider
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 名,最終結果如下: