人生苦短,我用 Python
前文傳送門:
小白學 Python 爬蟲(2):前置准備(一)基本類庫的安裝
小白學 Python 爬蟲(3):前置准備(二)Linux基礎入門
小白學 Python 爬蟲(4):前置准備(三)Docker基礎入門
小白學 Python 爬蟲(6):前置准備(五)爬蟲框架的安裝
小白學 Python 爬蟲(10):Session 和 Cookies
小白學 Python 爬蟲(11):urllib 基礎使用(一)
小白學 Python 爬蟲(12):urllib 基礎使用(二)
小白學 Python 爬蟲(13):urllib 基礎使用(三)
小白學 Python 爬蟲(14):urllib 基礎使用(四)
小白學 Python 爬蟲(15):urllib 基礎使用(五)
小白學 Python 爬蟲(16):urllib 實戰之爬取妹子圖
小白學 Python 爬蟲(17):Requests 基礎使用
小白學 Python 爬蟲(18):Requests 進階操作
小白學 Python 爬蟲(21):解析庫 Beautiful Soup(上)
小白學 Python 爬蟲(22):解析庫 Beautiful Soup(下)
小白學 Python 爬蟲(23):解析庫 pyquery 入門
小白學 Python 爬蟲(26):為啥買不起上海二手房你都買不起
小白學 Python 爬蟲(27):自動化測試框架 Selenium 從入門到放棄(上)
小白學 Python 爬蟲(28):自動化測試框架 Selenium 從入門到放棄(下)
小白學 Python 爬蟲(29):Selenium 獲取某大型電商網站商品信息
小白學 Python 爬蟲(31):自己構建一個簡單的代理池
小白學 Python 爬蟲(32):異步請求庫 AIOHTTP 基礎入門
引言
首先恭喜看到這篇文章的各位同學,從這篇文章開始,整個小白學 Python 爬蟲系列進入最后一部分,小編計划是介紹一些常用的爬蟲框架。
說到爬蟲框架,首先繞不過去的必然是 Scrapy 。
Scrapy 是一個基於 Twisted 的異步處理框架,是純 Python 實現的爬蟲框架,其架構清晰,模塊之間的耦合程度低,可擴展性極強,可以靈活完成各種需求。
當然第一件事兒還是各種官方地址:
Scrapy 官網: https://scrapy.org/
Github:https://github.com/scrapy/scrapy
架構概述
首先看一下 Scrapy 框架的架構體系圖:
從這張圖中,可以看到 Scrapy 分成了很多個組件,每個組件的含義如下:
- Engine 引擎:引擎負責控制系統所有組件之間的數據流,並在發生某些操作時觸發事件。
- Item 項目:它定義了爬取結果的數據結構,爬取的數據會被賦值成該對象。
- Scheduler 調度器:用來接受引擎發過來的請求並加入隊列中,並在引擎再次請求的時候提供給引擎。
- Downloader 下載器:下載器負責獲取網頁並將其饋送到引擎,引擎又將其饋給蜘蛛。
- Spiders 蜘蛛:其內定義了爬取的邏輯和網頁的解析規則,它主要負責解析響應並生成提取結果和新的請求。
- Item Pipeline 項目管道:負責處理由蜘蛛從網頁中抽取的項目,它的主要任務是清洗、驗證和存儲數據。
- Downloader Middlewares 下載器中間件:下載器中間件是位於引擎和Downloader之間的特定掛鈎,它們在從引擎傳遞到Downloader時處理請求,以及從Downloader傳遞到Engine的響應。
- Spider Middlewares 蜘蛛中間件:蜘蛛中間件是位於引擎和蜘蛛之間的特定掛鈎,並且能夠處理蜘蛛的輸入(響應)和輸出(項目和請求)。
上面這張圖的數據流程如下:
- 該引擎獲取從最初請求爬行 蜘蛛。
- 該引擎安排在請求 調度程序和要求下一個請求爬行。
- 該計划返回下一請求的引擎。
- 該引擎發送請求到 下載器,通過 下載器中間件。
- 頁面下載完成后, Downloader會生成一個帶有該頁面的響應,並將其發送到Engine,並通過 Downloader Middlewares。
- 該引擎接收來自響應 下載器並將其發送到所述 蜘蛛進行處理,通過蜘蛛中間件。
- 該蜘蛛處理響應並返回刮下的項目和新的要求(跟隨)的 引擎,通過 蜘蛛中間件。
- 該引擎發送處理的項目,以 項目管道,然后把處理的請求的調度,並要求今后可能請求爬行。
- 重復該過程(從步驟1開始),直到不再有Scheduler的請求為止 。
這張圖的名詞有些多,記不住實屬正常,不過沒關系,后續小編會配合着示例代碼,和各位同學一起慢慢的學習。
基礎示例
先來個最簡單的示例項目,在創建項目之前,請確定自己的環境已經正確安裝了 Scrapy ,如果沒有安裝的同學可以看下前面的文章,其中有介紹 Scrapy 的安裝配置。
首先需要創建一個 Scrapy 的項目,創建項目需要使用命令行,在命令行中輸入以下命令:
scrapy startproject first_scrapy
然后一個名為 first_scrapy
的項目就創建成功了,項目文件結構如下:
first_scrapy/
scrapy.cfg # deploy configuration file
first_scrapy/ # project's Python module, you'll import your code from here
__init__.py
items.py # project items definition file
middlewares.py # project middlewares file
pipelines.py # project pipelines file
settings.py # project settings file
spiders/ # a directory where you'll later put your spiders
__init__.py
- scrapy.cfg:它是 Scrapy 項目的配置文件,其內定義了項目的配置文件路徑、部署相關信息等內容。
- items.py:它定義 Item 數據結構,所有的 Item 的定義都可以放這里。
- pipelines.py:它定義 Item Pipeline 的實現,所有的 Item Pipeline 的實現都可以放這里。
- settings.py:它定義項目的全局配置。
- middlewares.py:它定義 Spider Middlewares 和 Downloader Middlewares 的實現。
- spiders:其內包含一個個 Spider 的實現,每個 Spider 都有一個文件。
到此,我們已經成功創建了一個 Scrapy 項目,但是這個項目目前是空的,我們需要再手動添加一只 Spider 。
Scrapy 用它來從網頁里抓取內容,並解析抓取的結果。不過這個類必須繼承 Scrapy 提供的 Spider 類 scrapy.Spider,還要定義 Spider 的名稱和起始請求,以及怎樣處理爬取后的結果的方法。
創建 Spider 可以使用手動創建,也可以使用命令創建,小編這里演示一下如何使用命令來創建,如下:
scrapy genspider quotes quotes.toscrape.com
將會看到在 spider 目錄下新增了一個 QuotesSpider.py 的文件,里面的內容如下:
# -*- coding: utf-8 -*-
import scrapy
class QuotesSpider(scrapy.Spider):
name = 'quotes'
allowed_domains = ['quotes.toscrape.com']
start_urls = ['http://quotes.toscrape.com/']
def parse(self, response):
pass
可以看到,這個類里面有三個屬性 name
、 allowed_domains
、 start_urls
和一個 parse()
方法。
- name,它是每個項目唯一的名字,用來區分不同的 Spider。
- allowed_domains,它是允許爬取的域名,如果初始或后續的請求鏈接不是這個域名下的,則請求鏈接會被過濾掉。
- start_urls,它包含了 Spider 在啟動時爬取的 url 列表,初始請求是由它來定義的。
- parse,它是 Spider 的一個方法。默認情況下,被調用時 start_urls 里面的鏈接構成的請求完成下載執行后,返回的響應就會作為唯一的參數傳遞給這個函數。該方法負責解析返回的響應、提取數據或者進一步生成要處理的請求。
到這里我們就清楚了, parse()
方法中的 response 是前面的 start_urls
中鏈接的爬取結果,所以在 parse()
方法中,我們可以直接對爬取的結果進行解析。
先看下網頁的 DOM 結構:
接下來要做的事情就比較簡單了,獲取其中的數據,然后將其打印出來。
數據提取的方式可以是 CSS 選擇器也可以是 XPath 選擇器,小編這里使用的是 CSS 選擇器,將我們剛才的 parse()
方法進行一些簡單的改動,如下:
def parse(self, response):
quotes = response.css('.quote')
for quote in quotes:
text = quote.css('.text::text').extract_first()
author = quote.css('.author::text').extract_first()
tags = quote.css('.tags .tag::text').extract()
print("text:", text)
print("author:", author)
print("tags:", tags)
首先是獲取到所有的 class 為 quote 的元素,然后將所有元素進行循環后取出其中的數據,最后對這些數據進行打印。
程序到這里就寫完了,那么接下來的問題是,我們如何運行這只爬蟲?
Scrapy 的運行方式同樣適用適用命令行的,首先要到這個項目的根目錄下,然后執行以下代碼:
scrapy crawl quotes
結果如下:
可以看到,我們剛才 print()
的內容正常的打印在了命令行中。
除了我們 print()
中的內容的打印,還可以看到在 Scrapy 啟動的過程中, Scrapy 輸出了當前的版本號以及正在啟動的項目名稱,並且在爬取網頁的過程中,首先訪問了 http://quotes.toscrape.com/robots.txt 機器人協議,雖然這個協議在當前這個示例中響應了 404的狀態碼,但是 Scrapy 會根據機器人協議中的內容進行爬取。
示例代碼
本系列的所有代碼小編都會放在代碼管理倉庫 Github 和 Gitee 上,方便大家取用。
參考
https://docs.scrapy.org/en/latest/intro/tutorial.html