scrapy 框架入門
執行流程
官網:https://docs.scrapy.org/en/latest/intro/overview.html
流程圖如下:
元件
1、引擎(EGINE):負責控制系統所有元件之間的資料流,並在某些動作發生時觸發事件。有關詳細資訊,請參見上面的資料流部分;
2、排程器(SCHEDULER):用來接受引擎發過來的請求, 壓入佇列中, 並在引擎再次請求的時候返回. 可以想像成一個URL的優先順序佇列, 由它來決定下一個要抓取的網址是什麼, 同時去除重複的網址;
3、下載器(DOWLOADER):用於下載網頁內容,並將網頁內容返回給EGINE,下載器是建立在twisted這個高效的非同步模型上的;
4、爬蟲(SPIDERS):SPIDERS是開發人員自定義的類,用來解析responses,並且提取items,或者傳送新的請求;
5、專案管道(ITEM PIPLINES):在items被提取後負責處理它們,主要包括清理、驗證、持久化(比如存到資料庫)等操作;
6、下載器中介軟體(Downloader Middlewares):位於Scrapy引擎和下載器之間,主要用來處理從EGINE傳到DOWLOADER的請求request,以及從DOWNLOADER傳到EGINE的響應response,可用該中介軟體做以下幾件事:
1、process a request just before it is sent to the Downloader (i.e. right before Scrapy sends the request to the website);
2、change received response before passing it to a spider;
3、send a new Request instead of passing received response to a spider;
4、pass response to a spider without fetching a web page;
5、silently drop some requests.
7、爬蟲中介軟體(Spider Middlewares):位於EGINE和SPIDERS之間,主要工作是處理SPIDERS的輸入(即responses)和輸出(即requests)
安裝
# Linux平臺
pip3 install scrapy
命令引數
# 檢視幫助 scrapy -h scrapy <command> -h Global commands: # 全域性命令 startproject # 建立專案,會在當前目錄下建立專案資料夾 genspider # cd 進入專案目錄,建立爬蟲程式 scrapy genspider baidu_spider www.baidu.com # 就會在spider目錄下生成 baidu_spider.py 檔案 settings # 如果是在專案目錄下,則得到的是該專案的配置 > scrapy settings --get=SPIDER_MODULES ['first_crawl.spiders'] runspider # 執行一個獨立的python檔案,不必建立專案 ROBOTSTXT_OBEY = False scrapy runspider baidu_spider.py的絕對路徑 shell # scrapy shell url地址 在互動式除錯,如選擇器規則正確與否 scrapy shell https://www.baidu.com/ # 進入互動環境後,可執行命令: response.text # 文字內容 response.body # 二進位制內容 view(response) # 開啟瀏覽器檢視響應頁面,已下載到本地 response.css('a') # 查詢所有a標籤 response.xpath('//a') # 查詢所有a標籤 quit() # 退出互動環境 fetch # 獨立於程單純地爬取一個頁面,可以拿到請求頭 scrapy fetch https://www.baidu.com/ # 直接獲取所有資訊,類似shell但沒有互動除錯 view # 下載完畢後直接彈出瀏覽器,以此可以分辨出哪些資料是ajax請求 version # scrapy version 檢視scrapy的版本 scrapy version # -v檢視scrapy依賴庫的版本 Project-only commands: # 必須切到專案資料夾下才能執行 crawl # 執行爬蟲,必須建立專案才行,確保配置檔案中ROBOTSTXT_OBEY=False scrapy crawl baidu_spider # 此處爬蟲名稱為name屬性對應的爬蟲 check # 檢測專案中有無語法錯誤 list # 列出專案中所包含的爬蟲名 parse # scrapy parse url地址 --callback 回撥函式,以此可以驗證我們的回撥函式是否正確 bench # scrapy bentch壓力測試,檢測每分鐘能爬取的網頁數 # 官網連結 https://docs.scrapy.org/en/latest/topics/commands.html
專案結構
project_name/
scrapy.cfg
project_name/
__init__.py
items.py
pipelines.py
settings.py
spiders/
__init__.py
爬蟲1.py
爬蟲2.py
爬蟲3.py
- 檔案說明:
- scrapy.cfg:專案的主配置資訊,用來部署scrapy時使用,爬蟲相關的配置資訊在·settings.py·檔案中;
- items.py:設定資料儲存模板,用於結構化資料,如:Django的Model;
- pipelines:資料處理行為,如:一般結構化的資料持久化
- settings.py:配置檔案,如:遞迴的層數、併發數,延遲下載等。強調:配置檔案的選項必須大寫否則視為無效,正確寫法USER_AGENT='xxxx';
- spiders:爬蟲目錄,如:建立檔案,編寫爬蟲規則。
選擇器xpath & css
測試網址:https://doc.scrapy.org/en/latest/_static/selectors-sample1.html
目標頁面內容:
<html>
<head>
<base href='http://example.com/' />
<title>Example website</title>
</head>
<body>
<div id='images'>
<a href='image1.html'>Name: My image 1 <br /><img src='image1_thumb.jpg' /></a>
<a href='image2.html'>Name: My image 2 <br /><img src='image2_thumb.jpg' /></a>
<a href='image3.html'>Name: My image 3 <br /><img src='image3_thumb.jpg' /></a>
<a href='image4.html'>Name: My image 4 <br /><img src='image4_thumb.jpg' /></a>
<a href='image5.html'>Name: My image 5 <br /><img src='image5_thumb.jpg' /></a>
</div>
</body>
</html>
進入互動環境測試選擇器使用:
scrapy shell https://doc.scrapy.org/en/latest/_static/selectors-sample1.html
# 進入互動環境
# response.selector.css()或.xpath返回的是selector物件,再呼叫extract()和extract_first()從selector物件中解析出內容。
獲取標籤物件 // & /
/
僅限於子標籤:
# 查詢目標頁面所有a標籤下的img子標籤
>>> response.xpath('//a/img').extract()
['<img src="image1_thumb.jpg">', '<img src="image2_thumb.jpg">',
'<img src="image3_thumb.jpg">', '<img src="image4_thumb.jpg">', '<img src="image5_thumb.jpg">']
>>> response.css('a img').extract() # 返回物件列表
>>> response.css('a img').extract_first() # 返回第一個標籤物件
'<img src="image1_thumb.jpg">'
//
在子孫標籤中查詢:
# 查詢目標頁面所有的div標籤內容的所有img標籤
>>> response.xpath('//div//img').extract()
['<img src="image1_thumb.jpg">', '<img src="image2_thumb.jpg">', '<img src="image3_thumb.jpg">', '<img src="image4_thumb.jpg">', '<img src="image5_thumb.jpg">']
獲取標籤中的文字text
>>> response.css('a::text').extract()
['Name: My image 1 ', 'Name: My image 2 ', 'Name: My image 3 ', 'Name: My image 4 ', 'Name: My image 5 ']
>>> response.xpath('//div/a/text()').extract()
['Name: My image 1 ', 'Name: My image 2 ', 'Name: My image 3 ',
'Name: My image 4 ', 'Name: My image 5 ']
獲取標籤屬性
# xpath獲取a標籤內的所有img的src屬性
>>> response.xpath('//a//img/@src').extract()
['image1_thumb.jpg', 'image2_thumb.jpg', 'image3_thumb.jpg', 'image4_thumb.jpg', 'image5_thumb.jpg']
## css獲取屬性
>>> response.css('img::attr(src)').extract()
['image1_thumb.jpg', 'image2_thumb.jpg', 'image3_thumb.jpg', 'image4_thumb.jpg', 'image5_thumb.jpg']
巢狀查詢
>>> response.xpath('//div').css('a').xpath('@href').extract_first()
'image1.html'
設定預設值
>>> response.xpath("//div[@id='asas']").extract_first(default='not found')
'not found'
按照屬性查詢
# 查詢所有包含[href='image2.html']的標籤
>>> response.xpath("//*[@href='image2.html']").extract_first()
'<a href="image2.html">Name: My image 2 <br><img src="image2_thumb.jpg"></a>'
>>> response.css('#images [href="image2.html"]').extract_first()
'<a href="image2.html">Name: My image 2 <br><img src="image2_thumb.jpg"></a>'
模糊匹配
>>> response.css('#images [href*="image2"]').extract_first()
'<a href="image2.html">Name: My image 2 <br><img src="image2_thumb.jpg"></a>'
>>> response.xpath('//a[contains(@href,"image1")]').extract_first()
'<a href="image1.html">Name: My image 1 <br><img src="image1_thumb.jpg"></a>'
>>> response.xpath('//*[contains(@href,"image1")]').extract_first()
'<a href="image1.html">Name: My image 1 <br><img src="image1_thumb.jpg"></a>'
正則表示式
# 先找到所有a標籤的文字selecor物件,然後逐個用re進行匹配,直到找到匹配的
>>> response.xpath('//a').re(".*My image 1 ")[0]
'<a href="image1.html">Name: My image 1 '