您好,登錄后才能下訂單哦!
這篇“scrapy爬蟲框架怎么使用”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“scrapy爬蟲框架怎么使用”文章吧。
在編寫爬蟲的時候,如果我們使用 requests、aiohttp 等庫,需要從頭至尾把爬蟲完整地實現一遍,比如說異常處理、爬取調度等,如果寫的多了,的確會比較麻煩。利用現有的爬蟲框架,可以提高編寫爬蟲的效率,而說到 Python 的爬蟲框架,Scrapy 當之無愧是最流行最強大的爬蟲框架了。
scrapy介紹
Scrapy 是一個基于 Twisted 的異步處理框架,是純 Python 實現的爬蟲框架,其架構清晰,模塊之間的耦合程度低,可擴展性極強,可以靈活完成各種需求。我們只需要定制開發幾個模塊就可以輕松實現一個爬蟲。
它有如下幾個部分:
Scrapy Engine(引擎):用來處理整個系統的數據流處理、觸發事務,是整個框架的核心。
Item(項目):定義了爬取結果的數據結構,爬取的數據會被賦值成該對象。
Scheduler(調度器):用來接受引擎發過來的請求并加入隊列中,并在引擎再次請求的時候提供給引擎。
Item Pipeline(項目管道):負責處理由蜘蛛從網頁中抽取的項目,它的主要任務是清洗、驗證和存儲數據。
Downloader(下載器):用于下載網頁內容,并將網頁內容返回給Spiders。
Spiders(蜘蛛):其內定義了爬取的邏輯和網頁的解析規則,它主要負責解析響應并生成提取結果和新的請求。
Downloader Middlewares(下載器中間件):位于引擎和下載器之間的鉤子框架,主要是處理引擎與下載器之間的請求及響應。
Spider Middlewares(Spiders中間件):位于引擎和蜘蛛之間的鉤子框架,主要工作是處理蜘蛛輸入的響應和輸出的結果及新的請求。
Scrapy數據流機制
scrapy 中的數據流由引擎控制,其過程如下:
Engine 首先打開一個網站,找到處理該網站的 Spider 并向該 Spider 請求第一個要爬取的 URL。
Engine 從 Spider 中獲取到第一個要爬取的 URL 并通過 Scheduler 以 Request 的形式調度。
Engine 向 Scheduler 請求下一個要爬取的 URL。
Scheduler 返回下一個要爬取的 URL 給 Engine,Engine 將 URL 通過 Downloader Middlewares 轉發給 Downloader 下載。
一旦頁面下載完畢, Downloader 生成一個該頁面的 Response,并將其通過 Downloader Middlewares 發送給 Engine。
Engine 從下載器中接收到 Response 并通過 Spider Middlewares 發送給 Spider 處理。
Spider 處理 Response 并返回爬取到的 Item 及新的 Request 給 Engine。
Engine 將 Spider 返回的 Item 給 Item Pipeline,將新的 Request 給 Scheduler。
重復第二步到最后一步,直到 Scheduler 中沒有更多的 Request,Engine 關閉該網站,爬取結束。
通過多個組件的相互協作、不同組件完成工作的不同、組件很好地支持異步處理,scrapy 最大限度地利用了網絡帶寬,大大提高了數據爬取和處理的效率。
pip install Scrapy -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
安裝方法參考官方文檔:https://docs.scrapy.org/en/latest/intro/install.html
安裝完成之后,如果可以正常使用 scrapy 命令,那就是安裝成功了。
Scrapy是框架,已經幫我們預先配置好了很多可用的組件和編寫爬蟲時所用的腳手架,也就是預生成一個項目框架,我們可以基于這個框架來快速編寫爬蟲。
Scrapy框架是通過命令行來創建項目的,創建項目的命令如下:
scrapy startproject practice
命令執行后,在當前運行目錄下便會出現一個文件夾,叫作practice,這就是一個Scrapy 項目框架,我們可以基于這個項目框架來編寫爬蟲。
project/ __pycache__ spiders/ __pycache__ __init__.py spider1.py spider2.py ... __init__.py items.py middlewares.py pipelines.py settings.py scrapy.cfg
各個文件的功能描述如下:
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 來抓取站點和處理數據。
通過命令行運行,將抓取的內容導出。
目標URL:http://quotes.toscrape.com/
創建項目
創建一個 scrapy 項目,項目文件可以直接用 scrapy 命令生成,命令如下所示:
scrapy startproject practice
創建Spider
Spider是自己定義的類,scrapy用它從網頁里抓取內容,并解析抓取的結果。這個類必須繼承 Scrapy 提供的Spider類scrapy.Spider,還要定義Spider的名稱和起始請求,以及怎樣處理爬取后的結果的方法。
使用命令行創建一個Spider,命令如下:
cd practice scrapy genspider quotes quotes.toscrape.com
切換路徑到剛才創建的practice文件夾,然后執行genspider命令。第一個參數是Spider的名稱,第二個參數是網站域名。執行完畢之后,spiders 文件夾中多了一個quotes.py,它就是剛剛創建的Spider,內容如下:
import scrapy class QuotesSpider(scrapy.Spider): name = "quotes" allowed_domains = ["quotes.toscrape.com"] start_urls = ['http://quotes.toscrape.com/'] def parse(self, response): pass
可以看到quotes.py里有三個屬性——name、allowed_domains 和 start_urls,還有一個方法 parse。
name:它是每個項目唯一的名字,用來區分不同的 Spider。
allowed_domains:它是允許爬取的域名,如果初始或后續的請求鏈接不是這個域名下的,則請求鏈接會被過濾掉。
start_urls:它包含了 Spider 在啟動時爬取的 url 列表,初始請求是由它來定義的。
parse:它是 Spider 的一個方法。默認情況下,被調用時 start_urls 里面的鏈接構成的請求完成下載執行后,返回的響應就會作為唯一的參數傳遞給這個函數。該方法負責解析返回的響應、提取數據或者進一步生成要處理的請求。
創建 Item
Item 是保存爬取數據的容器,它的使用方法和字典類似。不過,相比字典,Item 多了額外的保護機制,可以避免拼寫錯誤或者定義字段錯誤。
創建 Item 需要繼承 scrapy.Item 類,并且定義類型為 scrapy.Field 的字段。觀察目標網站,我們可以獲取到的內容有 text、author、tags。
定義Item,此時進入items.py修改如下:
import scrapy class QuoteItem(scrapy.Item): text = scrapy.Field() author = scrapy.Field() tags = scrapy.Field()
定義了三個字段,并將類的名稱修改為QuoteItem,接下來爬取時會使用到這個 Item。
解析 Response
parse 方法的參數 response 是 start_urls 里面的鏈接爬取后的結果。所以在 parse 方法中,我們可以直接對 response 變量包含的內容進行解析,比如瀏覽請求結果的網頁源代碼,或者進一步分析源代碼內容,或者找出結果中的鏈接而得到下一個請求。
可以看到網頁中既有想要提取的數據,又有下一頁的鏈接,這兩部分內容都可以進行處理。
首先看看網頁結構,如圖所示。每一頁都有多個 class 為 quote 的區塊,每個區塊內都包含 text、author、tags。那么我們先找出所有的 quote,然后提取每一個 quote 中的內容。
提取數據的方式可以是 CSS 選擇器 或 XPath 選擇器
使用 Item
上文定義了 Item,接下來就要使用它了。Item 可以理解為一個字典,不過在聲明的時候需要實例化。然后依次用剛才解析的結果賦值 Item 的每一個字段,最后將 Item 返回即可。
import scrapy from practice.items import QuoteItem class QuotesSpider(scrapy.Spider): name = 'quotes' allowed_domains = ['quotes.toscrape.com'] start_urls = ['http://quotes.toscrape.com/'] def parse(self, response, **kwargs): quotes = response.css('.quote') for quote in quotes: item = QuoteItem() item['text'] = quote.css('.text::text').extract_first() item['author'] = quote.css('.author::text').extract_first() item['tags'] = quote.css('.tags .tag::text').extract() yield item
后續 Request
上面的操作實現了從初始頁面抓取內容。實現翻頁爬取,這就需要從當前頁面中找到信息來生成下一個請求,然后在下一個請求的頁面里找到信息再構造下一個請求。這樣循環往復迭代,從而實現整站的爬取。
查看網頁源代碼,可以發現下一頁的鏈接是 /page/2/
,但實際上全鏈接為:http://quotes.toscrape.com/page/2/ ,通過這個鏈接就可以構造下一個請求。
構造請求時需要用到 scrapy.Request
。這里我們傳遞兩個參數—— url 和 callback,這兩個參數的說明如下:
url:它是請求鏈接
callback:它是回調函數。當指定了該回調函數的請求完成之后,獲取到響應,引擎會將該響應作為參數傳遞給這個回調函數。回調函數進行解析或生成下一個請求,回調函數如上文的 parse()
所示。
由于 parse 就是解析 text、author、tags 的方法,而下一頁的結構和剛才已經解析的頁面結構是一樣的,所以我們可以再次使用 parse 方法來做頁面解析。
""" @Author :葉庭云 @Date :2020/10/2 11:40 @CSDN :https://blog.csdn.net/fyfugoyfa """ import scrapy from practice.items import QuoteItem class QuotesSpider(scrapy.Spider): name = 'quotes' allowed_domains = ['quotes.toscrape.com'] start_urls = ['http://quotes.toscrape.com/'] def parse(self, response, **kwargs): quotes = response.css('.quote') for quote in quotes: item = QuoteItem() item['text'] = quote.css('.text::text').extract_first() item['author'] = quote.css('.author::text').extract_first() item['tags'] = quote.css('.tags .tag::text').extract() yield item next_page = response.css('.pager .next a::attr("href")').extract_first() next_url = response.urljoin(next_page) yield scrapy.Request(url=next_url, callback=self.parse)
運行接下來,進入目錄,運行如下命令:
scrapy crawl quotes -o quotes.csv
命令運行后,項目內多了一個 quotes.csv
文件,文件包含了剛才抓取的所有內容。
輸出格式還支持很多種,例如 json、xml、pickle、marshal 等,還支持 ftp、s3 等遠程輸出,另外還可以通過自定義 ItemExporter 來實現其他的輸出。
scrapy crawl quotes -o quotes.json scrapy crawl quotes -o quotes.xml scrapy crawl quotes -o quotes.pickle scrapy crawl quotes -o quotes.marshal scrapy crawl quotes -o ftp://user:pass@ftp.example.com/path/to/quotes.csv
其中,ftp 輸出需要正確配置用戶名、密碼、地址、輸出路徑,否則會報錯。
通過 scrapy 提供的 Feed Exports,我們可以輕松地輸出抓取結果到文件,對于一些小型項目來說,這應該足夠了。不過如果想要更復雜的輸出,如輸出到數據庫等,可以靈活使用 Item Pileline 來完成。
目標URL:http://sc.chinaz.com/tupian/dangaotupian.html
創建項目
scrapy startproject get_img cd get_img scrapy genspider img_spider sc.chinaz.com
構造請求
img_spider.py
中定義 start_requests()
方法,比如爬取這個網站里的蛋糕圖片,爬取頁數為 10,生成 10 次請求,如下所示:
def start_requests(self): for i in range(1, 11): if i == 1: url = 'http://sc.chinaz.com/tupian/dangaotupian.html' else: url = f'http://sc.chinaz.com/tupian/dangaotupian_{i}.html' yield scrapy.Request(url, self.parse)
編寫 items.py
import scrapy class GetImgItem(scrapy.Item): img_url = scrapy.Field() img_name = scrapy.Field()
編寫 img_spider.pySpider 類定義了如何爬取某個(或某些)網站,包括了爬取的動作(例如:是否跟進鏈接)以及如何從網頁的內容中提取結構化數據(抓取item)
""" @Author :葉庭云 @Date :2020/10/2 11:40 @CSDN :https://blog.csdn.net/fyfugoyfa """ import scrapy from get_img.items import GetImgItem class ImgSpiderSpider(scrapy.Spider): name = 'img_spider' def start_requests(self): for i in range(1, 11): if i == 1: url = 'http://sc.chinaz.com/tupian/dangaotupian.html' else: url = f'http://sc.chinaz.com/tupian/dangaotupian_{i}.html' yield scrapy.Request(url, self.parse) def parse(self, response, **kwargs): src_list = response.xpath('//div[@id="container"]/div/div/a/img/@src2').extract() alt_list = response.xpath('//div[@id="container"]/div/div/a/img/@alt').extract() for alt, src in zip(alt_list, src_list): item = GetImgItem() # 生成item對象 # 賦值 item['img_url'] = src item['img_name'] = alt yield item
編寫管道文件 pipelines.py
Scrapy 提供了專門處理下載的 Pipeline,包括文件下載和圖片下載。下載文件和圖片的原理與抓取頁面的原理一樣,因此下載過程支持異步和多線程,十分高效。
from scrapy.pipelines.images import ImagesPipeline # scrapy圖片下載器 from scrapy import Request from scrapy.exceptions import DropItem class GetImgPipeline(ImagesPipeline): # 請求下載圖片 def get_media_requests(self, item, info): yield Request(item['img_url'], meta={'name': item['img_name']}) def item_completed(self, results, item, info): # 分析下載結果并剔除下載失敗的圖片 image_paths = [x['path'] for ok, x in results if ok] if not image_paths: raise DropItem("Item contains no images") return item # 重寫file_path方法,將圖片以原來的名稱和格式進行保存 def file_path(self, request, response=None, info=None): name = request.meta['name'] # 接收上面meta傳遞過來的圖片名稱 file_name = name + '.jpg' # 添加圖片后綴名 return file_name
在這里實現了 GetImagPipeline,繼承 Scrapy 內置的 ImagesPipeline,重寫了下面幾個方法:
get_media_requests()。它的第一個參數 item 是爬取生成的 Item 對象。我們將它的 url 字段取出來,然后直接生成 Request 對象。此 Request 加入調度隊列,等待被調度,執行下載。
item_completed(),它是當單個 Item 完成下載時的處理方法。因為可能有個別圖片未成功下載,所以需要分析下載結果并剔除下載失敗的圖片。該方法的第一個參數 results 就是該 Item 對應的下載結果,它是一個列表形式,列表每一個元素是一個元組,其中包含了下載成功或失敗的信息。這里我們遍歷下載結果找出所有成功的下載列表。如果列表為空,那么說明該 Item 對應的圖片下載失敗了,隨即拋出異常DropItem,該 Item 忽略。否則返回該 Item,說明此 Item 有效。
file_path(),它的第一個參數 request 就是當前下載對應的 Request 對象。這個方法用來返回保存的文件名,接收上面meta傳遞過來的圖片名稱,將圖片以原來的名稱和定義格式進行保存。
配置文件 settings.py
# setting.py BOT_NAME = 'get_img' SPIDER_MODULES = ['get_img.spiders'] NEWSPIDER_MODULE = 'get_img.spiders' # Crawl responsibly by identifying yourself (and your website) on the user-agent USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36' # Obey robots.txt rules ROBOTSTXT_OBEY = False # Configure maximum concurrent requests performed by Scrapy (default: 16) CONCURRENT_REQUESTS = 32 # Configure a delay for requests for the same website (default: 0) # See https://docs.scrapy.org/en/latest/topics/settings.html#download-delay # See also autothrottle settings and docs DOWNLOAD_DELAY = 0.25 # Configure item pipelines # See https://docs.scrapy.org/en/latest/topics/item-pipeline.html ITEM_PIPELINES = { 'get_img.pipelines.GetImgPipeline': 300, } IMAGES_STORE = './images' # 設置保存圖片的路徑 會自動創建
運行程序:
# 切換路徑到img_spider的目錄 scrapy crawl img_spider
scrapy框架爬蟲一邊爬取一邊下載,下載速度非常快。
查看本地 images 文件夾,發現圖片都已經成功下載
以上就是關于“scrapy爬蟲框架怎么使用”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。