Scrapy:运行爬虫程序的方式
Windows 10家庭中文版,Python 3.6.4,Scrapy 1.5.0,
在創建了爬蟲程序后,就可以運行爬蟲程序了。Scrapy中介紹了幾種運行爬蟲程序的方式,列舉如下:
-命令行工具之scrapy runspider(全局命令)
-命令行工具之scrapy crawl(項目級命令)
-scrapy.crawler.CrawlerProcess
-scrapy.crawler.CrawlerRunner
注意,當系統中同時存在Python 2、Python 3時,孤的電腦直接執行scrapy命令使用的是Python 2,此時,需要在scrapy命令前添加“python3 -m”才可以使用Python 3,因此,請使用virtualenv建立虛擬環境運行scrapy等各種程序。
方式一:scrapy runspider命令(全局)
語法:scrapy runspider <spider_file.py>
還有一些配置項,可以使用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%了!而且沒帶充電器!~
總結
以上是生活随笔為你收集整理的Scrapy:运行爬虫程序的方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎无线联结两个小米路由器两个小米无线路由
- 下一篇: 主数据管理的概念和基本实施案例