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关键字的使用了):
P.S.又写了一篇,感受本身棒棒哒!幸好吃了那个小蛋糕!~今天的笔记本电量消耗好快啊(5个半小时),剩余36%了!并且没带充电器!~