Python之srcapy介紹
Scrapy是一個健壯的爬蟲框架,可以從網站中提取需要的數據。是一個快速、簡單、並且可擴展的方法。Scrapy使用了異步網絡框架來處理網絡通訊,可以獲得較快的下載速度,因此,我們不需要去自己實現異步框架。並且,Scrapy包含了各種中間件接口,可以靈活的完成各種需求。所以我們只需要定製開發幾個模塊就可以輕鬆的實現一個爬蟲,用來抓取網頁上的各種內容。
Scrapy爬蟲的優點很多:
內建的css選擇器和xpath表達式。基於IPython交互shell,方便編寫爬蟲和debug。健壯的編碼支持。擴展性強,可使用signals和api(中間件,插件,管道)添加自定義功能。多用於session,cookies,http認證,user-agent,robots.txt,抓取深度限制的中間件和插件。scrapy內建teinet console,可用於debug。一張圖解釋Scrapy爬蟲的工作原理:
Scrapy爬蟲分為以下幾個部分來協同工作:
引擎(Scrapy Engine):用來處理整個系統的數據流, 觸發事務,是整個框架的核心。通過他的處理,來實現整個框架的正常工作。調度器(Scheduler):用來接受引擎發過來的請求, 傳入隊列中, 並在引擎再次請求的時候返回. 可以想像成一個URL(抓取網頁的網址或者說是連結)的優先隊列, 由它來決定下一個要抓取的網址是什麼, 同時比較強大的功能就是:可以對以前已經抓取過得連結進去重。下載器(Downloader):用於下載網頁內容, 並將網頁內容返回給Spider(Scrapy下載器是建立在twisted這個高效的異步模型上的),其實是將抓取的內容返回給引擎,引擎然後將網站的內容返回給spider。spider將內容進行解析。提取有用的數據或者進行下一步的抓取,或者將數據結構化給pipeline。爬蟲(Spiders):爬蟲是主要幹活的, 用於從特定的網頁中提取自己需要的信息, 即所謂的實體(Item)。用戶也可以從中提取出連結(new_url),讓Scrapy繼續抓取下一個頁面。從start_urls 開始,Scheduler 會將其交給 Downloader 進行下載,下載之後會交給 Spider 進行分析,Spider 分析出來的結果有兩種:一種是需要進一步抓取的連結,例如之前分析的「下一頁」的連結,這些東西會被傳回 Scheduler ;另一種是需要保存的數據,它們則被送到 Item Pipeline 那裡,那是對數據進行後期處理(詳細分析、過濾、存儲等)的地方。另外,在數據流動的通道裡還可以安裝各種中間件,進行必要的處理。
安裝scrapy,創建scrapy工程
pip install --default-timeout=5000 scrapyscrapy startproject 工程名字
創建工程之後,會生成一個固定的文件目錄,結構如下:
├── mySpider 爬蟲總目錄│———— __init__.py│———— items.py 項目文件│————middlewares.py 中間件文件|———— pipelines.py 管道文件 |———— __pycache__ |———— settings.py 設置文件│————spider 爬蟲文件|——————__init__.py|——————__pycache__└── scrapy.cfg 配置文件
在Scrapy爬蟲的工程目錄中,存在有以下幾個文件以及各部分組件的工作:
管道文件夾:負責處理爬蟲從網頁中抽取的實體,主要的功能是持久化實體、驗證實體的有效性、清除不需要的信息。當頁面被爬蟲解析後,將被發送到項目管道,並經過幾個特定的次序處理數據。中間件文件:包含爬蟲中間件和下載器中間件。設置文件(配置文件):爬蟲文件:scrapy shell
scrapy shell是一個scrapy的交互終端,我們可以在未啟動爬蟲spider的情況下,嘗試以及調試代碼,也可以用來測試xpath或css表達式,查看特們的輸出信息,方便我們提取到準確的數據。
scrapy命令整理
1.創建一個新的爬蟲項目scrapy startproject 項目名2.生成爬蟲scrapy genspider 文件名網址3.運行爬蟲文件scrapy crawl 爬蟲名稱scrapy crawl 爬蟲名-o 文件名.json #保存json文件到本地4.check檢查錯誤scrapy check5.list返回項目所有的爬蟲spider名稱scrapy list6.view,存儲,打開網頁scrapy view 網址7.進入scrapy shell終端scrapy shell 網址
Scrapy Shell深入理解
Scrapy shell是一個交互終端,我們可以在未啟動spider爬蟲的情況下嘗試及調試代碼,也可以用來測試XPath表達式是否正確。
response.url #當前響應的url地址response.request.url #當前響應對應的請求的urlresponse.headers #響應頭response.body #響應體,就是html代碼,類型為byte字節類型,可以decode()轉換response.requests.headers #當前響應的請求頭
Scrapy深入理解DEBUG
通常我們啟動一個爬蟲,是會輸出以下信息的(我刪掉了日期):
[scrapy.utils.log] INFO:Scrapy1.6.0 started (bot: myspider)[scrapy.utils.log] INFO:Versions: lxml 4.3.3.0, libxml2 2.9.5, cssselect 1.0.3, parsel 1.5.1, w3lib 1.20.0,Twisted 19.2.1,Python3.7.3,PlatformWindows-7-6.1.7601-SP1[scrapy.crawler] INFO:Overridden settings:{'BOT_NAME':'myspider','NEWSPIDER_MODULE':'myspider.spiders','ROBOTSTXT_OBEY':True,'SPIDER_MODULES':['myspider.spiders']}#重啟一些設置,settings中的配置[scrapy.middleware] INFO:Enabled extensions:#已啟用的插件擴展['scrapy.extensions.corestats.CoreStats','scrapy.extensions.telnet.TelnetConsole',#控制臺,調試程序'scrapy.extensions.logstats.LogStats'][scrapy.middleware] INFO:Enabled downloader middlewares:#已啟用的下載程序中間件['scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware','scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware','scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware','scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware','scrapy.downloadermiddlewares.useragent.UserAgentMiddleware','scrapy.downloadermiddlewares.retry.RetryMiddleware','scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware','scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware','scrapy.downloadermiddlewares.redirect.RedirectMiddleware','scrapy.downloadermiddlewares.cookies.CookiesMiddleware','scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware','scrapy.downloadermiddlewares.stats.DownloaderStats'][scrapy.middleware] INFO:Enabled spider middlewares:#啟用的蜘蛛爬蟲中間件['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware','scrapy.spidermiddlewares.offsite.OffsiteMiddleware','scrapy.spidermiddlewares.referer.RefererMiddleware','scrapy.spidermiddlewares.urllength.UrlLengthMiddleware','scrapy.spidermiddlewares.depth.DepthMiddleware'][scrapy.middleware] INFO:Enabled item pipelines:......[scrapy.core.engine] INFO:Spider opened[scrapy.extensions.logstats] INFO:Crawled0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)[scrapy.extensions.telnet] INFO:Telnet console listening on 127.0.0.1:6023[scrapy.downloadermiddlewares.redirect] DEBUG:Redirecting(302) to <GET xxx.com/robots.txt>from<GET xxx.com/robots.txt>[scrapy.core.engine] DEBUG:Crawled(200)<GET xxx.com/robots.txt>(referer:None)[scrapy.downloadermiddlewares.redirect] DEBUG:Redirecting(302) to <GET ...>from<GET ...>[scrapy.core.engine] DEBUG:Crawled(200)<GET https://sz.esf.fang.com/> (referer: None)[scrapy.core.engine] INFO:Closing spider (finished)[scrapy.statscollectors] INFO:DumpingScrapy stats:{'downloader/request_bytes':876,'downloader/request_count':4,'downloader/request_method_count/GET':4,'downloader/response_bytes':52832,'downloader/response_count':4,'downloader/response_status_count/200':2,'downloader/response_status_count/302':2,'finish_reason':'finished','finish_time': datetime.datetime(2020,3,8,5,37,12,513124),'log_count/DEBUG':4,'log_count/INFO':9,'response_received_count':2,'robotstxt/request_count':1,'robotstxt/response_count':1,'robotstxt/response_status_count/200':1,'scheduler/dequeued':2,'scheduler/dequeued/memory':2,'scheduler/enqueued':2,'scheduler/enqueued/memory':2,'start_time': datetime.datetime(2020,3,8,5,37,10,613015)}[scrapy.core.engine] INFO:Spider closed (finished)
我們需要關注的主要是DEBUG信息,特會顯示一些錯誤信息,比方說,遇到robots.txt文件(網站的robots禁止爬蟲),或者過濾filtered offsite 請求(通常是因為爬取的域名不在可允許的範圍)。那麼我們在剛開始的時候不要在settings
Scrapy之深入理解settings文件
為什麼需要配置文件?
配置文件存放一些公共的變量(比如資料庫的地址,帳號密碼等)。方便自己和別人修改,一般用全大寫字母命名變量名。MONGODB_TABLE
settings文件中的配置信息包含:
......#通過在用戶代理上標識您自己(和您的網站)負責任地爬行##默認的user-agent是關閉的,是個scrapy爬蟲,你也可以開啟試試,或者在這裡替換user-agent也可以#USER_AGENT = 'myspider (+)'# Obey robots.txt rules#遵守robots.txt規則 默認遵守,基本都會修改為FalseROBOTSTXT_OBEY =True# Configure maximum concurrent requests performed by Scrapy (default: 16)#配置Scrapy執行的最大並發請求數(默認值:16),打開注釋為32個#CONCURRENT_REQUESTS = 32# Configure a delay for requests for the same website (default: 0)#為同一網站的請求配置延遲(默認值:0)理解為對於一個相同的url是否需要建立連接#DOWNLOAD_DELAY = 3# The download delay setting will honor only one of:#下載延遲設置將僅支持以下選項之一#CONCURRENT_REQUESTS_PER_DOMAIN = 16#CONCURRENT_REQUESTS_PER_IP = 16# Disable cookies (enabled by default)#禁用Cookie(默認情況下已啟用)#COOKIES_ENABLED = False# Disable Telnet Console (enabled by default)#禁用Telnet控制臺(默認啟用)#TELNETCONSOLE_ENABLED = False# Override the default request headers:#重寫默認請求頭#DEFAULT_REQUEST_HEADERS = {# 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',# 'Accept-Language': 'en',#}# Enable or disable spider middlewares#啟用或禁用爬蟲中間件#SPIDER_MIDDLEWARES = {# 'myspider.middlewares.MyspiderSpiderMiddleware': 543,#}# Enable or disable downloader middlewares#啟用或禁用下載程序中間件#DOWNLOADER_MIDDLEWARES = {# 'myspider.middlewares.MyspiderDownloaderMiddleware': 543,#}# Enable or disable extensions#啟用或禁用擴展插件#EXTENSIONS = {# 'scrapy.extensions.telnet.TelnetConsole': None,#}# Configure item pipelines#配置項管道#ITEM_PIPELINES = {# 'myspider.pipelines.MyspiderPipeline': 300,#}# Enable and configure the AutoThrottle extension (disabled by default)# 啟用並配置AutoThrottle擴展(默認情況下禁用)#AUTOTHROTTLE_ENABLED = True# The initial download delay#初始下載延遲#AUTOTHROTTLE_START_DELAY = 5# The maximum download delay to be set in case of high latencies#在高延遲情況下設置的最大下載延遲#AUTOTHROTTLE_MAX_DELAY = 60# The average number of requests Scrapy should be sending in parallel to# each remote server# Scrapy應並行發送到每個遠程伺服器的平均請求數#AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0# Enable showing throttling stats for every response received:#啟用顯示接收到的每個響應的限制狀態,是否可以向遠程伺服器發送請求#AUTOTHROTTLE_DEBUG = False# Enable and configure HTTP caching (disabled by default)# 啟用和配置HTTP緩存(默認情況下禁用)#httpcache-middleware-settings#緩存的過期時間,緩存的文件夾路徑,忽略那些http響應碼#HTTPCACHE_ENABLED = True#HTTPCACHE_EXPIRATION_SECS = 0#HTTPCACHE_DIR = 'httpcache'#HTTPCACHE_IGNORE_HTTP_CODES = []#HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'
在spider中settings能夠通過self.settings的方式獲取到:
classMySpider(scrapy,Spider):...def parse(self,response):print("Existing settings: %s "%self.settings.attributes.keys())
在pipelines中使用spider.settings.get()的方式獲取到:
classMyspiderPipeline(object):def open_spider(self, item, spider):print(spider.settings.get("MONGO_TABLE",None))
那麼又有個新的疑問,open_spider是幹什麼的