如果手机上显示代码错乱,请分享到QQ或者其他地方,用电脑查看!!!
python能干的东西有很多,这里不再过多叙述,直接重点干货。
Python爬虫大战
爬虫与发爬虫的厮杀,一方为了拿到数据,一方为了防止爬虫拿到数据,谁是最后的赢家?
重新理解爬虫中的一些概念
爬虫:自动获取网站数据的程序
反爬虫:使用技术手段防止爬虫程序爬取数据
误伤:反爬虫技术将普通用户识别为爬虫,这种情况多出现在封ip中,例如学校网络、小区网络再或者网络网络都是共享一个公共ip,这个时候如果是封ip就会导致很多正常访问的用户也无法获取到数据。所以相对来说封ip的策略不是特别好,通常都是禁止某ip一段时间访问。
成本:反爬虫也是需要人力和机器成本
拦截:成功拦截爬虫,一般拦截率越高,误伤率也就越高
反爬虫的目的
初学者写的爬虫:简单粗暴,不管对端服务器的压力,甚至会把网站爬挂掉了
数据保护:很多的数据对某些公司网站来说是比较重要的不希望被别人爬取
商业竞争问题:这里举个例子是关于京东和天猫,假如京东内部通过程序爬取天猫所有的商品信息,从而做对应策略这样对天猫来说就造成了非常大的竞争
爬虫与反爬虫大战
上有政策下有对策,下面整理了常见的爬虫大战策略
Scrapy分布式原理
关于Scrapy工作流程
Scrapy单机架构
上图的架构其实就是一种单机架构,只在本机维护一个爬取队列,Scheduler进行调度,而要实现多态服务器共同爬取数据关键就是共享爬取队列。
分布式架构
我将上图进行再次更改
这里重要的就是我的队列通过什么维护?
这里一般我们通过Redis为维护,Redis,非关系型数据库,Key-Value形式存储,结构灵活。
并且redis是内存中的数据结构存储系统,处理速度快,提供队列集合等多种存储结构,方便队列维护
如何去重?
这里借助redis的集合,redis提供集合数据结构,在redis集合中存储每个request的指纹
在向request队列中加入Request前先验证这个Request的指纹是否已经加入集合中。如果已经存在则不添加到request队列中,如果不存在,则将request加入到队列并将指纹加入集合
如何防止中断?如果某个slave因为特殊原因宕机,如何解决?
这里是做了启动判断,在每台slave的Scrapy启动的时候都会判断当前redis request队列是否为空
如果不为空,则从队列中获取下一个request执行爬取。如果为空则重新开始爬取,第一台丛集执行爬取向队列中添加request
如何实现上述这种架构?
这里有一个scrapy-redis的库,为我们提供了上述的这些功能
scrapy-redis改写了Scrapy的调度器,队列等组件,利用他可以方便的实现Scrapy分布式架构
关于scrapy-redis的地址:https://github.com/rmax/scrapy-redis
搭建分布式爬虫
参考官网地址:https://scrapy-redis.readthedocs.io/en/stable/
前提是要安装scrapy_redis模块:pip install scrapy_redis
这里的爬虫代码是用的之前写过的爬取知乎用户信息的爬虫
修改该settings中的配置信息:
替换scrapy调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
添加去重的class
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
添加pipeline
如果添加这行配置,每次爬取的数据也都会入到redis数据库中,所以一般这里不做这个配置
ITEM_PIPELINES = {
'scrapy_redis.pipelines.RedisPipeline': 300
}
共享的爬取队列,这里用需要redis的连接信息
这里的user:pass表示用户名和密码,如果没有则为空就可以
REDIS_URL = 'redis://user:pass@hostname:9001'
设置为为True则不会清空redis里的dupefilter和requests队列
这样设置后指纹和请求队列则会一直保存在redis数据库中,默认为False,一般不进行设置
SCHEDULER_PERSIST = True
设置重启爬虫时是否清空爬取队列
这样每次重启爬虫都会清空指纹和请求队列,一般设置为False
SCHEDULER_FLUSH_ON_START=True
分布式
将上述更改后的代码拷贝的各个服务器,当然关于数据库这里可以在每个服务器上都安装数据,也可以共用一个数据,我这里方面是连接的同一个mongodb数据库,当然各个服务器上也不能忘记:
所有的服务器都要安装scrapy,scrapy_redis,pymongo
这样运行各个爬虫程序启动后,在redis数据库就可以看到如下内容,dupefilter是指纹队列,requests是请求队列
Scrapy分布式部署
这个scrapyd的github地址:https://github.com/scrapy/scrapyd
当在远程主机上安装了scrapyd并启动之后,就会再远程主机上启动一个web服务,默认是6800端口,这样我们就可以通过http请求的方式,通过接口的方式管理我们scrapy项目,这样就不需要在一个一个电脑连接拷贝过着通过git,关于scrapyd官方文档地址:http://scrapyd.readthedocs.io/en/stable/
安装scrapyd
安装scrapyd:pip install scrapyd
这里我在另外一台ubuntu linux虚拟机中同样安装scrapy以及scrapyd等包,保证所要运行的爬虫需要的包都完成安装,这样我们就有了两台linux,包括上篇文章中我们已经有的linux环境
在这里有个小问题需要注意,默认scrapyd启动是通过scrapyd就可以直接启动,这里bind绑定的ip地址是127.0.0.1端口是:6800,这里为了其他虚拟机访问讲ip地址设置为0.0.0.0
scrapyd的配置文件:/usr/local/lib/python3.5/dist-packages/scrapyd/default_scrapyd.conf
这样我们就可以通过浏览器访问:
关于部署
如何通过scrapyd部署项目,这里官方文档提供一个地址:https://github.com/scrapy/scrapyd-client,即通过scrapyd-client进行操作
这里的scrapyd-client主要实现以下内容:
把我们本地代码打包生成egg文件
根据我们配置的url上传到远程服务器上
我们将我们本地的scrapy项目中scrapy.cfg配置文件进行配置:
我们其实还可以设置用户名和密码,不过这里没什么必要,只设置了url
这里设置url一定要注意:url = http://192.168.1.9:6800/addversion.json
最后的addversion.json不能少
我们在本地安装pip install scrapy_client,安装完成后执行:scrapyd-deploy
zhaofandeMBP:zhihu_user zhaofan$ scrapyd-deployPacking version 1502177138Deploying to project "zhihu_user" in http://192.168.1.9:6800/addversion.jsonServer response (200):{"node_name": "fan-VirtualBox", "status": "ok", "version": "1502177138", "spiders": 1, "project": "zhihu_user"}zhaofandeMBP:zhihu_user zhaofan$看到status:200表示已经成功
关于常用操作API
listprojects.json列出上传的项目列表
zhaofandeMBP:zhihu_user zhaofan$ curl http://192.168.1.9:6800/listprojects.json{"node_name": "fan-VirtualBox", "status": "ok", "projects": ["zhihu_user"]}zhaofandeMBP:zhihu_user zhaofan$listversions.json列出有某个上传项目的版本
zhaofandeMBP:zhihu_user zhaofan$ curl http://192.168.1.9:6800/listversions.json?project=zhihu_user{"node_name": "fan-VirtualBox", "status": "ok", "versions": ["1502177138"]}zhaofandeMBP:zhihu_user zhaofan$schedule.json远程任务的启动
下面我们启动的三次就表示我们启动了三个任务,也就是三个调度任务来运行zhihu这个爬虫
zhaofandeMBP:zhihu_user zhaofan$ curl http://192.168.1.9:6800/schedule.json -d project=zhihu_user -d spider=zhihu{"node_name": "fan-VirtualBox", "status": "ok", "jobid": "97f1b5027c0e11e7b07a080027bbde73"}zhaofandeMBP:zhihu_user zhaofan$ curl http://192.168.1.9:6800/schedule.json -d project=zhihu_user -d spider=zhihu{"node_name": "fan-VirtualBox", "status": "ok", "jobid": "99595aa87c0e11e7b07a080027bbde73"}zhaofandeMBP:zhihu_user zhaofan$ curl http://192.168.1.9:6800/schedule.json -d project=zhihu_user -d spider=zhihu{"node_name": "fan-VirtualBox", "status": "ok", "jobid": "9abb1ba27c0e11e7b07a080027bbde73"}zhaofandeMBP:zhihu_user zhaofan$同时当启动完成后,我们可以通过页面查看jobs,这里因为我远端服务器并没有安装scrapy_redis,所以显示任务是完成了,我点开日志并能看到详细的日志情况:
这里出错的原因就是我上面忘记在ubuntu虚拟机安装scrapy_redis以及pymongo模块,进行
pip install scrapy_redis pymongo安装后重新启动,就可以看到已经在运行的任务,同时点开Log日志也能看到爬取到的内容:
listjobs.json列出所有的jobs任务
上面是通过页面显示所有的任务,这里是通过命令获取结果
zhaofandeMBP:zhihu_user zhaofan$ curl http://192.168.1.9:6800/listjobs.json?project=zhihu_user{"node_name": "fan-VirtualBox", "status": "ok", "running": [], "pending": [], "finished": [{"start_time": "2017-08-08 15:53:00.510050", "spider": "zhihu", "id": "97f1b5027c0e11e7b07a080027bbde73", "end_time": "2017-08-08 15:53:01.416139"}, {"start_time": "2017-08-08 15:53:05.509337", "spider": "zhihu", "id": "99595aa87c0e11e7b07a080027bbde73", "end_time": "2017-08-08 15:53:06.627125"}, {"start_time": "2017-08-08 15:53:10.509978", "spider": "zhihu", "id": "9abb1ba27c0e11e7b07a080027bbde73", "end_time": "2017-08-08 15:53:11.542001"}]}zhaofandeMBP:zhihu_user zhaofan$cancel.json取消所有运行的任务
这里可以将上面启动的所有jobs都可以取消:
zhaofandeMBP:zhihu_user zhaofan$ curl http://192.168.1.9:6800/cancel.json -d project=zhihu_user -d job=0f5cdabc7c1011e7b07a080027bbde73{"node_name": "fan-VirtualBox", "status": "ok", "prevstate": "running"}zhaofandeMBP:zhihu_user zhaofan$ curl http://192.168.1.9:6800/cancel.json -d project=zhihu_user -d job=63f8e12e7c1011e7b07a080027bbde73{"node_name": "fan-VirtualBox", "status": "ok", "prevstate": "running"}zhaofandeMBP:zhihu_user zhaofan$ curl http://192.168.1.9:6800/cancel.json -d project=zhihu_user -d job=63f8e12f7c1011e7b07a080027bbde73{"node_name": "fan-VirtualBox", "status": "ok", "prevstate": "running"}这样当我们再次通过页面查看,就可以看到所有的任务都是finshed状态:
我相信看了上面这几个方法你一定会觉得真不方便还需要输入那么长,所以有人替你干了件好事把这些API进行的再次封装:https://github.com/djm/python-scrapyd-api
关于python-scrapyd-api
该模块可以让我们直接在python代码中进行上述那些api的操作
首先先安装该模块:pip install python-scrapyd-api
使用方法如下,这里只演示了简单的例子,其他方法其实使用很简单按照规则写就行:
from scrapyd_api import ScrapydAPIscrapyd = ScrapydAPI('http://192.168.1.9:6800')res = scrapyd.list_projects()res2 = scrapyd.list_jobs('zhihu_user')print(res)print(res2)Cancel a scheduled job
scrapyd.cancel('project_name', '14a6599ef67111e38a0e080027880ca6')
Delete a project and all sibling versions
scrapyd.delete_project('project_name')
Delete a version of a project
scrapyd.delete_version('project_name', 'version_name')
Request status of a job
scrapyd.job_status('project_name', '14a6599ef67111e38a0e080027880ca6')
List all jobs registered
scrapyd.list_jobs('project_name')
List all projects registered
scrapyd.list_projects()
List all spiders available to a given project
scrapyd.list_spiders('project_name')
List all versions registered to a given project
scrapyd.list_versions('project_name')
Schedule a job to run with a specific spider
scrapyd.schedule('project_name', 'spider_name')
Schedule a job to run while passing override settings
settings = {'DOWNLOAD_DELAY': 2}
Schedule a job to run while passing extra attributes to spider initialisation
scrapyd.schedule('project_name', 'spider_name', extra_attribute='value')
以上是全部代码,只是善于分享,不足之处请包涵!爬虫基本的原理就是,获取源码,进而获取网页内容。一般来说,只要你给一个入口,通过分析,可以找到无限个其他相关的你需要的资源,进而进行爬取。
我也写了很多其他的非常简单的入门级的爬虫详细教程,关注后,点击我的头像,就可以查看到。
欢迎大家一起留言讨论和交流,谢谢!
举报/反馈

专业项目源码分享

33获赞 67粉丝
我的世界不允许你的消失。
关注
0
0
收藏
分享