Scrapy:運行爬蟲程序的方式

Windows 10家庭中文版,Python 3.6.4,Scrapy 1.5.0,html

 

在建立了爬蟲程序後,就能夠運行爬蟲程序了。Scrapy中介紹了幾種運行爬蟲程序的方式,列舉以下:python

-命令行工具之scrapy runspider(全局命令)react

-命令行工具之scrapy crawl(項目級命令)編程

-scrapy.crawler.CrawlerProcess多線程

-scrapy.crawler.CrawlerRunnerdom

 

注意,當系統中同時存在Python 二、Python 3時,孤的電腦直接執行scrapy命令使用的是Python 2,此時,須要在scrapy命令前添加「python3 -m」纔可使用Python 3,所以,請使用virtualenv創建虛擬環境運行scrapy等各類程序。異步

 

方式一:scrapy runspider命令(全局)scrapy

語法:scrapy runspider <spider_file.py>async

還有一些配置項,可使用scrapy runspider -h查看。分佈式

示例程序:文件名爲baidu_com.py

 1 # -*- coding: utf-8 -*-
 2 import scrapy
 3 
 4 class BaiduComSpider(scrapy.Spider):
 5     name = 'baidu.com'
 6     allowed_domains = ['www.baidu.com']
 7     start_urls = ['https://www.baidu.com/']
 8 
 9     def parse(self, response):
10         yield {
11             'title': response.xpath('//title/text()').extract_first()
12         }

parse函數使用response.xpath獲取網頁<title>的文本:

 

方式二:scrapy crawl(項目級)

crawl是項目級命令,所以只能在某個Scrapy項目中使用。那麼,首先建立項目test070401:

使用tree命令查看建立的項目的結構:

剛剛建立的Scrapy項目的spiders目錄中只有__init__.py文件,那麼,將以前建立的baidu_com.py拷貝到此文件中:

如今,能夠在項目test070401中使用crawl命令執行爬蟲程序了。且慢,先看看crawl的語法:

scrapy crawl <spider>

 

注意,是<spider>而不是runspider命令的<spider_file.py>,準確的說<spider>是一個 爬蟲程序的名稱——爬蟲類裏面的name屬性(必須required,且在項目中具備惟一性unique)。

 

baidu_com.py裏面的爬蟲類的名稱是什麼呢?baidu.com

 

疑問:一個爬蟲文件裏面是否能夠創建多個爬蟲類呢?

 

那麼,執行下面的命令便可運行baidu_com.py裏面的爬蟲程序了:

scrapy crawl baidu.com

 

{

很尷尬,第一次執行竟然失敗了,沒找到!

嚴重懷疑是拷貝的問題,拷貝過來後 還須要作一些配置吧?配置在……settings.py裏面看看!

參考其它在項目裏面創建的爬蟲程序,發現settings.py中沒有其配置;spiders包下面的__init__.py文件呢?也沒發現其配置!

噩耗!怎麼辦?應該是能夠執行的啊!

暈~字母拼寫錯誤:baidu.com 拼寫成 badu.com!嚴重警告一次!

}

 

從新執行正確的命令:仍然沒有獲取到須要的數據,由於,robots協議的存在,程序被拒絕了!

 

警示:因此,抓取數據不必定會成功,由於還會被網站拒絕!可是,開發爬蟲程序時,必需要遵循相應的道德(規範)!

 

更多思考:

但是,爲什麼以前使用runspider抓取數據成功了呢?

再次使用runspider命令執行baidu_com.py:結果, 成功!

 

爲什麼如此 區別對待呢?

檢查二者啓動時的scrapy.crawler發現了不一樣:其中的crawl命令裏面包含ROBOTSTXT_OBEY爲True,代表其遵照站點的robots.txt協議

 

那麼,測試中的站點的robots.txt是怎樣的呢?它幾乎拒絕了全部的爬蟲程序——Disallow!固然,baidu.com原本就是爬蟲了,怎麼會容許其它爬蟲爬取它呢?爬蟲爬取爬蟲,好奇怪!

 

固然,Scrapy項目是否遵照robots.txt協議,是能夠在settings.py中配置的,請參考官文Settings

 

疑問:runspider、crawl命令是否能夠執行多個爬蟲程序呢?請測試!

 

------分割線------

 

學習Scrapy之初一直有一個困惑,爬蟲程序只能使用命令行來執行嗎?不能寫程序來執行嗎?固然能夠!

直到看了官文 Common Practices,此文中還介紹了一點關於分佈式爬取(Distributed crawls)的內容,但本篇博客不涉及。

 

方式三:CrawlerProcess

使用CrawlerProcess執行上面的baidu_com.py中的爬蟲類,程序runcp.py以下:

1 import scrapy
2 from scrapy.crawler import CrawlerProcess
3 from baidu_com import BaiduComSpider
4 
5 # 建立一個CrawlerProcess對象
6 process = CrawlerProcess() # 括號中能夠添加參數
7 
8 process.crawl(BaiduComSpider)
9 process.start()

執行程序runcp.py:成功,抓取到了須要的數據。

 

 

孤是在virtualenv中執行,因此,直接輸入runrc.py就能夠運行程序,不然,請使用python -m runrc.py

 

注意,上面的程序是在Scrapy項目外執行的,若是是在項目內執行,

-可使用get_project_settings()函數獲取項目的一個Settings實例做爲CrawlerProcess的參數;

-傳遞給crawl(...)函數的能夠是項目內爬蟲程序的name屬性的值;

 

疑問,在項目內執行時,是否能夠 混合使用項目內外的爬蟲程序執行呢?既使用項目內的,也能夠經過導入使用項目外的。

 

疑問:

是否能夠執行多個爬蟲程序呢?按理說 能夠;(實際上也是能夠的,官文有介紹)

是否能夠定時執行爬蟲程序呢?按理說 能夠;(本文未介紹)

 

關於第一個「執行多個」的問題,在官文 Common Practices中有介紹,示例以下(仍然是在Scrapy項目外):

 1 import scrapy
 2 from scrapy.crawler import CrawlerProcess
 3 from baidu_com import BaiduComSpider
 4 from msn_com import MsnComSpider
 5 
 6 # 建立一個CrawlerProcess對象
 7 process = CrawlerProcess() # 括號中能夠添加參數
 8 
 9 process.crawl(BaiduComSpider)
10 process.crawl(MsnComSpider)
11 process.start()

執行結果:不過,注意日誌顯示的抓取順序和代碼中相反

 

方式四:CrawlerRunner

官文對CrawlerRunner有更詳細的介紹,還涉及到Twisted模塊中的Reactor、Deferred等,而孤對Twisted模塊的用法還不熟悉,只是昨天看了Deferred的參考文檔。

可是,本文的目的是使用CrawlerRunner來編寫腳本運行爬蟲程序,那麼,關於Twisted能夠稍候詳細瞭解,須要精通

 

本節包括下面的程序(均爲Scrapy項目外):

-運行單個爬蟲程序

-運行多個爬蟲程序

-使用inlineCallbacks的方式運行爬蟲程序(多個)

 

運行單個爬蟲程序

 1 from twisted.internet import reactor
 2 import scrapy
 3 from scrapy.crawler import CrawlerRunner
 4 from scrapy.utils.log import configure_logging
 5 from baidu_com import BaiduComSpider
 6 
 7 # 必須執行下面的,不然命令行中沒有數據輸出,555,
 8 configure_logging({'LOG_FORMAT': '%(levelname)s: %(message)s'})
 9 
10 # 建立一個CrawlerRunner對象
11 runner = CrawlerRunner()
12 
13 d = runner.crawl(BaiduComSpider) # 返回一個Twisted中的Deferred對象
14 d.addBoth(lambda _: reactor.stop()) # addBoth參考Derrerred的文檔
15 reactor.run()

執行結果:獲取數據成功,,不過,第一次執行什麼也沒有輸出到命令行中,由於沒有執行configure_logging,爲什麼這樣?

 

運行多個爬蟲程序

 1 from twisted.internet import reactor
 2 import scrapy
 3 from scrapy.crawler import CrawlerRunner
 4 from scrapy.utils.log import configure_logging
 5 from baidu_com import BaiduComSpider
 6 from techmeme_com import TechmemeComSpider
 7 
 8 configure_logging()
 9 
10 # 建立一個CrawlerRunner對象
11 runner = CrawlerRunner()
12 
13 runner.crawl(BaiduComSpider)
14 runner.crawl(TechmemeComSpider)
15 d = runner.join() # 在多線程編程中見到過此函數,這裏是?
16 d.addBoth(lambda _: reactor.stop()) # addBoth參考Derrerred的文檔
17 reactor.run()

執行結果:獲取數據成功,不過,techmeme.com的抓取結果 沒有「一瞬間」顯示出來,而是延遲了2~3秒。

 

注意,其獲取網頁的順序和程序中添加的一致,固然,也多是由於延遲問題。

 

使用inlineCallbacks的方式運行爬蟲程序(多個)

須要懂Twisted的Dererred才能理解的!孤目前懂了10%吧?程序以下:

 1 from twisted.internet import reactor, defer
 2 
 3 from scrapy.crawler import CrawlerRunner
 4 from scrapy.utils.log import configure_logging
 5 
 6 from baidu_com import BaiduComSpider
 7 from techmeme_com import TechmemeComSpider
 8 
 9 configure_logging()
10 
11 # 建立一個CrawlerRunner對象
12 runner = CrawlerRunner()
13 
14 # 關鍵點來了!
15 @defer.inlineCallbacks
16 def crawl():
17     yield runner.crawl(BaiduComSpider)
18     yield runner.crawl(TechmemeComSpider)
19     reactor.stop()
20 
21 # 調用crawl()
22 crawl()
23 
24 reactor.run()

執行結果:執行成功(就不展現截圖了,和前面一個程序的結果同樣)!

 

總結

經過本文,孤對運行爬蟲程序的方式有了更全面的瞭解了,讀者您呢?

不過會有些不足,那就是對Twisted的reactor、Deferred不瞭解,而且本身對Python的裝飾器使用沒有達到精通級別,因此,看到裝飾器會有些發怵!

本文沒有 定時執行爬蟲程序 的方法,由於水平不足,不過,既然都能在程序執行了,那麼,離完成 定時執行爬蟲程序 的目標還遠嗎?

沒有寫 分佈式爬蟲 的問題,孤本身懂了再寫唄!

在看Twisted的文檔時會遇到不少「新東西」,這就是困難了,心中對本身的指望應該是——讀一遍就能夠了,本身很聰明,但是呢?本身不過是個不如想象中聰明的普通人,一遍,是遠遠不夠的,要不少遍!同時結合多練習,這也是孤最近學習東西時發現的一個問題——把本身的學習能力「想象」的太厲害了,而當顯示出現差距時,本身就會感受挫折,產生負面情緒。不過,如今認識到這一點了,能更好地理解本身了,因此,不會以爲學不會,只是以爲一遍學不會而已,不會再對本身這我的產生懷疑。

 

對了,下面是Twisted的一些連接(學習Twisted還須要懂的異步、同步、阻塞、非阻塞IO,更別說Python的裝飾器、協程等基礎知識和最新的async/awati關鍵字的使用了):

Twisted官網

Introduction to Deferred

Deferred Reference

Reactor Overview

 

P.S.又寫了一篇,感受本身棒棒噠!幸好吃了那個小蛋糕!~今天的筆記本電量消耗好快啊(5個半小時),剩餘36%了!並且沒帶充電器!~

相關文章
相關標籤/搜索