Scrapy 爬蟲框架學習筆記(未完,持續更新)

Scrapy 爬蟲框架

Scrapy 是一個用 Python 寫的 Crawler Framework 。它使用 Twisted 這個異步網絡庫來處理網絡通信。

Scrapy 框架的主要架構

根據它官網上的設計架構圖,一個完整的 Spider 主要分成 7 個部分:Scrapy EngineSchedulerDownloaderSpiderItem PipelineDownloader middlewaresSpider middlewares

Scrapy 引擎( Engine ):負責控制數據流在系統種所有組件中流動,並在相應動作時觸發事件。

調度器( Scheduler ) :調度器從引擎中接收 Request 並將它們入隊,以便之後引擎請求 Request 時提供給引擎。

下載器( Downloader ):下載器負責獲取頁面數據並提供給引擎。

Spider :是 Scrapy 用戶用於分析 Response 並提取 Item 或者額外跟進 URL 的類。每個 Spider 負責處理特定(或一些)網站。

Item Pipeline :負責處理被 Spider 提取出來的 Item 。例如數據持久化。

Downloader middlewares 下載中間件:是引擎與下載器之間特定的鉤子,處理 Downloader 傳遞給引擎的 Response 。

Spider 中間件( Spider middlewares ):是引擎和 Spider 之間的特定鉤子,處理 Spider 的輸入( Response )和輸出( Items 和 Response )。

這些模塊的之間的數據流向可以清楚地反應 Scrapy 的工作流程,具體如下:

  1. 引擎打開一個網站,找到處理該網站的 Spider 並向該 Spider 請求第一個要爬取的 URL 。
  2. 引擎從 Spider 中獲取第一個要爬取的 URL 並通過調度器以 Request 進行調度。
  3. 引擎向調度器請求下一個要爬取的 URL 。
  4. 調度器返回下一個要爬取的 URL 給引擎,引擎將 URL 通過下載中間件轉發給下載器。
  5. 一旦頁面下載完成,下載器生成一個該頁面的 Response ,並將器通過下載中間件發送給引擎。
  6. 引擎從下載器中接收到 Response 並通過 Spider 中間件發送給 Spider 處理。
  7. Spider 處理 Response 並返回爬取到的 Item 及新的 Request 給引擎。
  8. 引擎將爬取到的 Item 給 Item Pipeline ,將 Request 給調度器。
  9. 重複直到調度器中沒有更多的 Request ,引擎關閉該網站。

這和之前學習的普通的爬蟲思路架構是很像的。

安裝 Scrapy 框架

我用的 WSL2 ,直接安裝即可。

pip install scrapy

Scrapy, Hello World!

創建一個新的文件夾做項目的根路徑。然後運行命令創建項目:

scrapy startproject cnblogsSpider

然後他就會生成如下的項目目錄。

.
└── cnblogSpider
    ├── cnblogSpider => 該項目的 python 模塊
    │   ├── __init__.py
    │   ├── items.py => Item 文件
    │   ├── middlewares.py => 中間件
    │   ├── pipelines.py => Pipeline 文件
    │   ├── settings.py => 配置文件
    │   └── spiders => 放置 Spider 文件的文件夾
    │       └── __init__.py
    └── scrapy.cfg => 項目部署文件

在 Spiders 文件夾下創建一個文件 cnblogs_spider.py 然後編寫如下代碼:

import scrapy


class CnblogsSpider(scrapy.Spider):

    # * 爬蟲的名字,必須唯一
    name = "cnblogs"
    allowed_domains = ["cnblogs.com"]
    
    # * 爬取入口 URL 列表,將會首先爬取這裏面的 URL 
    start_urls = [
        "http://www.cnblogs.com/qiyeboy/default.html?page=1"
    ]

    # * 用來解析返回的 Response 數據的方法
    # * 每個 URL 相應後的 Response 都會傳遞給這個方法
    # * 進行提取 item 以及 URL Request 對象
    def parse(self, response):
        pass

在 cnBlogsSpider 文件夾下執行:

scrapy crawl cnblogs

第一個爬蟲就成功完成了。

Scrapy 命令行工具

scrapy shell 分爲兩種類型的命令,一種是必須在 Scrapy 項目下運行的,一種是全局命令。

startproject 命令:

語法scrapy startproject myproject

功能就是創建項目。

settings 命令:

語法scrapy settings [options]

在項目運行時,運行這個命令將會輸出項目的設定值,否則就輸出 Scrapy 的默認設定。

scrapy settings --get BOT_NAME
# cnblogSpider
scrapy settings --get DOWNLOAD_DELAY
# 0

runspider 命令:

語法scrapy runspider <spider_file.py>

在沒有創建項目的情況下,運行一個編寫好的 Spider 模塊。

shell 命令:

語法scrapy shell [url]

用於啓動 Scrapy shell , URL 可選。

scrapy shell "http://www.cnblogs.com/qiyeboy/default.html?page=1"

fetch 命令:

語法scrapy fetch <url>

使用 Scrapy 下載器下載給定的 URL ,並將內容送到終端。

如果是在項目內運行,會用項目內下載器的配置,如果不是就會用默認的 Scrapy Downloader 配置。

scrapy fetch --nolog "http://www.cnblogs.com/qiyeboy/default.html?page=1"
scrapy fetch --nolog --headers "http://www.cnblogs.com/qiyeboy/default.html?page=1"

view 命令:

語法scrapy view <url>

在瀏覽器中打開給定的 URL ,並以 Scrapy spider 獲取到的形式展現。

scrapy view "http://www.cnblogs.com/qiyeboy/default.html?page=1"

bench 命令:

語法scrapy bench

測試 Scrapy 在硬件上的效率。

Spider 模塊

Spider 模塊最重要的一個功能就是從 Downloader 中處理好的 Response 數據提取出想要的 Item 或者是新的 URL 。 Scrapy 框架提供了 Selector 來幫助我們提取數據。

在不使用框架的時候,我們使用的是 BeautifulSoup 或者是 XPath 完成網頁數據的提取。而在 Scrapy 的框架下,內置了這些數據提取的工具,讓我們可以直接使用內置的選擇器來完成數據的提取。

Selector 的用法

四個基本用法

xpath(query) :傳入 XPath 表達式,返回表達式對應的所有節點的 selector list 列表。

css(query) :傳入 CSS 表達式,返回表達式對應的所有節點的 selector list 列表。

extract() :序列化節點爲 Unicode 字符串。

re(regex) :根據傳入的正則表達式對數據進行提取

這個是 Scrapy 裏面的 Selector 最常用的 4 個方法。在 Spider 文件裏的 parse(self, response) 方法裏,只要將傳入的 Response 傳入 Selector 裏,就能構建一個 Selector 。

selector = Selector(response)

由於 XPath 和 CSS 查詢非常普遍, Scrapy 在 Request 裏內置了兩個可以直接調用的方法: xpath(query) -> SelectorList ,和 css(query) -> SeletorList 。它們返回的都是選擇器列表。於是我們可以使用這種簡寫方式跳過構造 Selector 。

我們嘗試從 HTML 頁面上提取信息,改寫一下 parse(response) 方法:

def parse(self, response):
    papers = response.xpath(".//*[@class='day']")
    for paper in papers:
        url = paper.xpath(".//*[@class='postTitle']/a/@href").extract()[0]
        title = paper.xpath(".//*[@class='postTitle']/a/span/text()").extract()[0]
        time = paper.xpath(".//*[@class='dayTitle']/a/text()").extract()[0]
        content = paper.xpath(".//*[@class='postCon']/div/text()").extract()[0]
        print(url, title, time, content)

運行 scrapy crawl cnblogs 然後就可以發現成功獲取了數據:

Selector 提取數據

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章