一、Scrapy爬蟲框架結構
1、Scrapy不是一個函式功能庫,而是一個爬蟲框架
爬蟲框架是實作爬蟲功能的一個軟體結構和功能組件集合
爬蟲框架是一個半成品,能夠幫助用戶實作專業網路爬蟲
2、“5+2”結構

(1)Engine(不需要用戶修改)
控制所有模塊之間的資料流
根據條件觸發事件
(2)Downloader(不需要用戶修改)
根據請求下載網頁
Scheduler(不需要用戶修改)
對所有爬取請求進行調度管理
(3)Downloader Middleware
目的:實施Engine、Scheduler、和Downloader之間進行用戶可配置的控制
功能:修改、丟棄、新增請求或回應
用戶可以撰寫配置代碼
(4)Spider
決議Downloader回傳的回應(Response)
產生爬取項(scrapy item)
產生額外的爬取請求(Request)
需要用戶撰寫配置代碼
(5)Item Pipelines
以流水線方式處理Spider產生的爬取項
由一組操作順序組成,類似流水線,每個操作是一個Item Pipelines型別
可能操作包括:清理、檢驗和查重爬取項中的HTML資料、將資料存盤到資料庫
(6)Spider Middleware
目的:對請求和爬取項的再處理
功能:修改、丟棄、新增請求或爬取項
用戶可以撰寫配置代碼
二、Request庫與Scrapy爬蟲的比較
1、相同點
兩者都可以進行頁面請求和爬取,Python爬蟲的兩個重要技術路線
兩者可用性都好,檔案豐富,入門簡單
兩者都沒有處理JS、提交表單、應對驗證碼等功能(可擴展)
2、不同點
| Request | Scrapy |
| 頁面級爬蟲 | 網站級爬蟲 |
| 功能庫 | 框架 |
| 并發性考慮不足,性能較差 | 并發性好,性能較高 |
| 重點在于頁面下載 | 重點在于爬蟲結構 |
| 定制靈活 | 一般定制靈活,深度定制困難 |
| 上手十分簡單 | 入門稍難 |
三、Scrapy命令列
Scrapy是為持續運行設計的專業爬蟲框架,提供操作的Scrapy命令列
1、命令列格式
1 scrapy <command> [options] [args]
2、Scrapy常用命令
| 命令 | 說明 | 格式 |
| startproject | 創建一個新工程 | scrapy startproject<name>[dir] |
| genspider | 創建一個爬蟲 | scrapy genspider[options]<name><domain> |
| settings | 獲取爬蟲配置資訊 | scrapy settings[options] |
| crawl | 運行一個爬蟲 | scrapy crawl<spider> |
| list | 列出工程中所有爬蟲 | scrapy list |
| shell | 啟動URL調式命令列 | scrapy shell[url] |
四、實體
1、建立一個scrapy爬蟲工程
命令列陳述句
1 scrapy startproject python123demo #新建一個“python123demo”工程名的爬蟲工程
工程目錄為D:\Codes\Python>
1 D:\Codes\Python>scrapy startproject python123demo 2 New Scrapy project 'python123demo', using template directory 'd:\codes\python\venv\lib\site-packages\scrapy\templates\project', created in: 3 D:\Codes\Python\python123demo 4 5 You can start your first spider with: 6 cd python123demo 7 scrapy genspider example example.com

python123demo/ 外層目錄

scrapy.cfg 部署Scrapy爬蟲的組態檔
python123demo/ Scrapy框架的用戶自定義Python代碼

_init_.py 初始化腳本
Items.py Items代碼模板(繼承類)
middlewares.py Middlewares代碼模板(繼承類)
pipelines.py Pipelines代碼模板(繼承類)
settings.py Scrapy爬蟲的組態檔
spiders/ Spiders代碼模板目錄(繼承類)

_init_.py 初始檔案,無需修改
_pycache_/ 快取目錄,無需修改
2、在工程中產生一個Scrapy爬蟲
命令列陳述句
1 1 cd python123demo #打開python123demo檔案夾 2 2 scrapy genspider demo python123.io #創建爬蟲
先打開檔案目錄,再進行產生爬蟲
1 D:\Codes\Python>cd python123demo 2 3 (venv) D:\Codes\Python\python123demo>scrapy genspider demo python123.io 4 Created spider 'demo' using template 'basic' in module: 5 python123demo.spiders.demo
此時在spiders檔案夾下會生成一個demo.py檔案

內容為
1 # -*- coding: utf-8 -*- 2 import scrapy 3 4 5 class DemoSpider(scrapy.Spider): 6 name = 'demo' 7 allowed_domains = ['python123.io'] 8 start_urls = ['http://python123.io/'] 9 10 def parse(self, response): 11 pass
parse()用于處理回應,決議內容形成字典,發現新的URL爬取請求
3、配置產生的spider爬蟲
修改demo.py內容
1 # -*- coding: utf-8 -*- 2 import scrapy 3 4 5 class DemoSpider(scrapy.Spider): 6 name = 'demo' 7 #allowed_domains = ['python123.io'] 8 start_urls = ['http://python123.io/ws/demo.html'] 9 10 def parse(self, response): 11 fname = response.url.split('/')[-1] 12 with open(fname,'wb') as f: 13 f.write(response.body) #將回傳的內容保存為檔案 14 self.log('Saved file %s.'% fname)
4、運行爬蟲,獲取網頁
命令列
1 scrapy crawl demo
運行爬蟲
1 D:\Codes\Python\python123demo>scrapy crawl demo 2 2020-03-19 11:25:40 [scrapy.utils.log] INFO: Scrapy 2.0.0 started (bot: python123demo) 3 2020-03-19 11:25:40 [scrapy.utils.log] INFO: Versions: lxml 4.5.0.0, libxml2 2.9.5, cssselect 1.1.0, parsel 1.5.2, w3lib 1.21.0, Twisted 19.10.0, Python 3.8.1 (tags/v3.8.1:1b293b6, Dec 18 2019, 22:39:24) [MSC v.1916 32 bit (Intel)], pyOpenSSL 19.1.0 (OpenSSL 1.1.1d 4 10 Sep 2019), cryptography 2.8, Platform Windows-10-10.0.18362-SP0 5 2020-03-19 11:25:40 [scrapy.utils.log] DEBUG: Using reactor: twisted.internet.selectreactor.SelectReactor 6 2020-03-19 11:25:41 [scrapy.crawler] INFO: Overridden settings: 7 {'BOT_NAME': 'python123demo', 8 'NEWSPIDER_MODULE': 'python123demo.spiders', 9 'ROBOTSTXT_OBEY': True, 10 'SPIDER_MODULES': ['python123demo.spiders']} 11 2020-03-19 11:25:41 [scrapy.extensions.telnet] INFO: Telnet Password: dbe958957137573b 12 2020-03-19 11:25:41 [scrapy.middleware] INFO: Enabled extensions: 13 ['scrapy.extensions.corestats.CoreStats', 14 'scrapy.extensions.telnet.TelnetConsole', 15 'scrapy.extensions.logstats.LogStats'] 16 2020-03-19 11:25:42 [scrapy.middleware] INFO: Enabled downloader middlewares: 17 ['scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware', 18 'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware', 19 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware', 20 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware', 21 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware', 22 'scrapy.downloadermiddlewares.retry.RetryMiddleware', 23 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware', 24 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware', 25 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware', 26 'scrapy.downloadermiddlewares.cookies.CookiesMiddleware', 27 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware', 28 'scrapy.downloadermiddlewares.stats.DownloaderStats'] 29 2020-03-19 11:25:42 [scrapy.middleware] INFO: Enabled spider middlewares: 30 ['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware', 31 'scrapy.spidermiddlewares.offsite.OffsiteMiddleware', 32 'scrapy.spidermiddlewares.referer.RefererMiddleware', 33 'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware', 34 'scrapy.spidermiddlewares.depth.DepthMiddleware'] 35 2020-03-19 11:25:42 [scrapy.middleware] INFO: Enabled item pipelines: 36 [] 37 2020-03-19 11:25:42 [scrapy.core.engine] INFO: Spider opened 38 2020-03-19 11:25:42 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min) 39 2020-03-19 11:25:42 [scrapy.extensions.telnet] INFO: Telnet console listening on 127.0.0.1:6023 40 2020-03-19 11:25:42 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (301) to <GET https://python123.io/robots.txt> from <GET http://python123.io/robots.txt> 41 2020-03-19 11:25:42 [scrapy.core.engine] DEBUG: Crawled (404) <GET https://python123.io/robots.txt> (referer: None) 42 2020-03-19 11:25:42 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (301) to <GET https://python123.io/ws/demo.html> from <GET http://python123.io/ws/demo.html> 43 2020-03-19 11:25:42 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://python123.io/ws/demo.html> (referer: None) 44 2020-03-19 11:25:42 [demo] DEBUG: Saved file demo.html. 45 2020-03-19 11:25:42 [scrapy.core.engine] INFO: Closing spider (finished) 46 2020-03-19 11:25:42 [scrapy.statscollectors] INFO: Dumping Scrapy stats: 47 {'downloader/request_bytes': 892, 48 'downloader/request_count': 4, 49 'downloader/request_method_count/GET': 4, 50 'downloader/response_bytes': 1901, 51 'downloader/response_count': 4, 52 'downloader/response_status_count/200': 1, 53 'downloader/response_status_count/301': 2, 54 'downloader/response_status_count/404': 1, 55 'elapsed_time_seconds': 0.644698, 56 'finish_reason': 'finished', 57 'finish_time': datetime.datetime(2020, 3, 19, 3, 25, 42, 983695), 58 'log_count/DEBUG': 5, 59 'log_count/INFO': 10, 60 'response_received_count': 2, 61 'robotstxt/request_count': 1, 62 'robotstxt/response_count': 1, 63 'robotstxt/response_status_count/404': 1, 64 'scheduler/dequeued': 2, 65 'scheduler/dequeued/memory': 2, 66 'scheduler/enqueued': 2, 67 'scheduler/enqueued/memory': 2, 68 'start_time': datetime.datetime(2020, 3, 19, 3, 25, 42, 338997)} 69 2020-03-19 11:25:42 [scrapy.core.engine] INFO: Spider closed (finished)
捕獲的頁面存盤在demo.html中

五、代碼理解
1、demo.py完整版代碼
1 import scrapy 2 3 class DemoSpider(scrapy.Spider): 4 name = 'demo' 5 6 def start_requests(self): 7 urls = [ 8 'http://python123.io/ws/demo.html' 9 ] 10 for url in urls: 11 yield scrapy.Request(url = url,callback = self.parse) 12 13 def parse(self, response): 14 fname = response.url.split('/')[-1] 15 with open(fname,'wb') as f: 16 f.write(response.body) 17 self.log('Saved file %s.'% fname)
start_requests(self)函式是一個生成器,當url數過多時,可以帶來較好的資源占用
2、yield關鍵字
yield<--->生成器
生成器是一個不斷產生值得函式
包含yield陳述句的函式是一個生成器
生成器每次產生一個值(yield陳述句),函式被凍結,被喚醒后再產生一個值
生成器寫法
1 def gen(n): #定義gen()函式 2 for i in range(n): 3 yield i**2 4 5 for i in gen(5): 6 print(i," ",end = "") 7 0 1 4 9 16
生成器相比一次列出所有內容來說,更節省存盤空間、回應更迅速、使用更靈活
普通寫法
1 def square(n): #定義square()函式 2 ls = [i**2 for i in range(n)] 3 return ls 4 5 for i in range(5): 6 print(i," ",end = "") 7 0 1 2 3 4
普通寫法將所有結果都存入一個串列中,占用空間大且耗時,不利于程式運行
六、Scrapy爬蟲框架總結
1、Scrapy爬蟲的使用步驟
(1)創建一個工程和Spider模板
(2)撰寫Spider
(3)撰寫Item Pipeline
(4)配置策略
2、Scrapy爬蟲的資料型別
(1)Request類
class scrapy.http.Request()
Request物件表示一個HTTP請求
由Spider生成,由Downloader執行
| 屬性或方法 | 說明 |
| .url | Request對應的請求URL地址 |
| .method | 對應的請求方法,’GET’’POST’等 |
| .headers | 字典型別風格的請求頭 |
| .body | 請求內容主體,字串型別 |
| .meta | 用戶添加的擴展資訊,在Scrapy內部模塊間傳遞資訊使用 |
| .copy() | 復制該請求 |
(2)Response類
class scrapy.http.Response()
Response物件表示一個HTTP回應
由Downloader生成,由Spider處理
| 屬性或方法 | 說明 |
| .url | Response對應的URL地址 |
| .status | HTTP狀態碼,默認是200 |
| .headers | Response對應的頭部資訊 |
| .body | Response對應的內容資訊,字串型別 |
| .flags | 一組標記 |
| .request | 產生Response型別對應的Request物件 |
| .copy() | 復制該回應 |
(3)Item類
class scrapy.item.Item()
Item物件表示一個HTML頁面中提取的資訊內容
由Spider生成,由Item Pipeline處理
Item型別字典型別,可以按照字典型別操作
3、Scrapy爬蟲提取資訊的方法
Scrapy爬蟲支持多種HTML資訊提取方法
Beautiful Soup
lxml
re
XPath Selector
CSS Selector
CSS Selector的基本使用
1 <HTML>.css(‘a::attr(href)’).extract()
CSS Selector由W3C組織維護并規范
資料來源:《Python網路爬蟲與資訊提取》——嵩天,北京理工大學,MOOC
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/170794.html
標籤:Python
下一篇:python工程編譯成EXE
