前言
Scrapy開門篇寫了一些純理論知識,這第二篇就要直奔主題了。先來講講Scrapy的架構,並從零開始開發一個Scrapy爬蟲程序。
本篇文章主要闡述Scrapy架構,理清開發流程,掌握基本操作。
整體架構
自己動手畫架構圖一張:
這就是Scrapy的整體架構,看起來流程比較復雜,但其實需要開發者參與的部分不多。這里先介紹一下各個部分。
- Spider:要開發的爬蟲程序,用來定義網站入口,實現解析邏輯並發起請求。
- Pipeline:數據管道,可自定義實現數據持久化方式。
- Middleware:中間件,分為兩類。一類是下載器中間件,主要處理請求,用於添加請求頭、代理等;一類是spider中間件,用於處理響應,用的很少。
- Scheduler:調度器,用來存放爬蟲程序的請求。
- Downloader:下載器。對目標網站發起請求,獲取響應內容。
一個完整的爬蟲,開發者需要參與1、2、3部分的開發。甚至最簡單的爬蟲,只需要開發Spider部分即可。
准備工作
安裝Scrapy
Scrapy的安裝和普通模塊相同:
pip3 install scrapy
安裝之后,就會多出一個scrapy命令,我們可以使用此命令來新建項目、新建爬蟲程序、進入shell交互環境等等。
命令說明如下圖:
新建項目
和普通python項目不同的是,Scrapy需要使用命令行新建項目,然后再導入IDE進行開發。
scrapy startproject [ProjectName]
執行上面命令,新建一個新的Scrapy項目。
從項目結構可以看出,一個Scrapy項目分為四大模塊,與架構中各個部分對應。
新建爬蟲程序
將項目導入IDE,spiders包用於存放開發的爬蟲程序。而爬蟲程序的新建也是通過命令行操作。
# domain就是域名,例如百度域名就是www.baidu.com
scrapy genspider [SpiderName] [domin]
在本scrapy項目任何目錄下的命令行中執行此命令,都會在spiders下新建一個爬蟲程序。
爬蟲程序開發
如圖,scrapy爬蟲程序已經生成,在其中實現解析規則代碼即可完成開發。
這里依然以斗羅大陸為例,程序代碼如下。
程序結構
每個Scrapy程序都會有三個模塊:
- name:每個項目中的爬蟲的名稱,作為唯一標識用於爬蟲的啟動
- allowed_domains:主要用於限定運行爬蟲網站的域名
- start_urls::網站入口,起始url
- parse:預設的第一個解析函數
上面說道,start_urls是爬蟲程序的入口,那么它是怎么發起請求,並將Res響應傳給parse解析?作為一個list類型,是否可以有多個入口url?
start_requests()
每個爬蟲程序都繼承了Spider類,里面的start_requests方法用來發起請求,並自動將響應傳遞給parse()。
如圖,我們可以看到,此方法遍歷了start_urls來發起了請求。那么,我就不想傳遞給parse()解析,我就想自定義方法,啷個怎么辦來?
小事莫慌,我們重寫start_requests就好了嘛。
如圖,我們自定義了parse_first解析函數,在發起請求時使用callback來指定回調函數,這里記住:函數名一定不要加括號,加括號表示立即執行此函數,不加代表是引用。
修改后的程序輸出結果和之前相同。
Request
我們使用yield Request發起一個請求,為什么不用return?因為yield不會立即返回,不會終結方法。這里就涉及到了生成器的問題,有興趣的可以去研究一下。
Request使用的參數如下順序排列:
- url:要請求的url
- callback:處理響應的回調函數
- meta:字典,通過響應傳遞kv數據給回調函數
- dont_filter:默認為False,即開啟url去重。如果我們在start_urls寫入兩條一樣的url時,只會輸出一次結果,如果我們修改為True,則輸出兩次。
- method:請求方式,默認為get
- priority:請求優先級,默認為0,數值越大優先級越大
至於cookies、headers參數,我們可以在Request設置,但大多時候都是在下載器middleware中進行設置。
爬蟲程序啟動
Scrapy爬蟲程序的啟動主要有兩種方式。
命令行啟動
第一種就是在scrapy項目目錄下的命令行下啟動。
scrapy crawl [SpiderName]
這種啟動方式的缺點顯而易見,就是無法IDE中使用Debug功能,所以這種方式通常用於生產。
IDE啟動
我們在開發過程中通常使用第二種啟動方式,這也是符合我們常規啟動程序的方式。新建一個python程序,引入命令行工具執行爬蟲啟動命令。
from scrapy.cmdline import execute
if __name__ == "__main__":
execute("scrapy crawl DouLuoDaLu".split(" "))
這樣就可以在IDE中啟動程序,並使用Debug功能。
scrapy shell交互環境
我們可以shell交互環境中進行解析代碼的調試。
scrapy shell https://v.qq.com/detail/m/m441e3rjq9kwpsc.html
輸入命令回車,對斗羅大陸頁面發起請求並進入shell環境。
如圖所示,在進入shell環境后,自動封裝了一些變量,這里我們只關注響應response。
如圖,我們在shell交互環境中對網頁進行了解析。這樣,我們將測試好的解析代碼復制到程序中即可,這樣提高了開發效率。
輸入view(response),敲擊回車,將自動在瀏覽器打開頁面。
結語
在樣例程序中,請求和響應只在架構圖右半邊簡單地流轉,如果想要持久化,還需要定義pipeline等等,而且程序中也只寫了一層解析函數,即parse()。
如果在parse中還要進行深度爬取,我們也要在parse中發起請求,並定義新的callback回調函數來進行解析,一直到我們想要的數據頁面為止。當然,這些后面都會講到。
自Scrapy系列寫了開篇之后,就擱置了很久。一是最近的確挺忙的,二是Scrapy知識點比較多,一時間不知該從何處寫起。不過我還是會繼續寫下去的,雖然可能更新的有點慢,歡迎小伙伴催更、也希望多多提出寶貴的意見。
95后小程序員,寫的都是日常工作中的親身實踐,置身於初學者的角度從0寫到1,詳細且認真。
文章會在公眾號 [入門到放棄之路] 首發,期待你的關注。