基于scrapy框架爬虫学习小结
缘由
在之前完全没有接触过爬虫的我,甚至都不知道爬虫是何物,然而在数据挖掘课程第二次大作业中却要我们小组直接用scrapy框架做一个爬取朋友圈的爬虫,一接到作业的我们马上就懵逼了,别说是scrapy了,我们就连什么是爬虫,爬虫原理是什么都一无所知,突然就要爬微信朋友圈,还要两周内,开什么玩笑。
但是怎么也得做,就分工着做,折腾了一段时间,总算有点收获和更加清晰的认识,现在有点小进度,就来报告一下进度~(其实是来总结的.)
话说爬虫
先说说爬虫,爬虫常被用来抓取特定网站网页的HTML数据,定位在后端数据的获取,而对于网站而言,爬虫给网站带来流量的同时,一些设计不好的爬虫由于爬得太猛,导致给网站来带很大的负担,当然再加上一些网站并不希望被爬取,所以就出现了许许多多的反爬技术。
Scrapy
Scrapy是用python写的一个爬虫框架,当然如果只是写一些简单爬虫,python自己就有做爬虫的库,scrapy只是更加流水线化,各部分分工更加清晰.它的结构如下图:
首先从初始 URL 开始,Scheduler 会将其交给 Downloader 进行下载,下载之后会交给 Spider 进行分析,Spider 分析出来的结果有两种:一种是需要进一步抓取的链接,例如“下一页”的链接,这些东西会被传回 Scheduler ;另一种是需要保存的数据,它们则被送到 Item Pipeline 那里,那是对数据进行后期处理(详细分析、过滤、存储等)的地方。
当然,光是学会最基础的scrapy的使用是很快的,因为demo很多,但是对于实际爬取却并不是这么简单,就拿weixin.sogou.com(或者chuansong.me)来说,一开始我以为,只要在spider里面start_urls里面把爬取URL入口改成 http://weixin.sogou.com,再定义一下parse规则选择要抓取的内容就可以了,但是运行的时候发现,抓下来的只有半个括号,重复几次都是同样的问题,然后我仔细查看了输出信息,里面出现了robots.txt禁止了我的爬虫爬取,于是我上网查了一下robots.txt是何方神圣,这一查让我打开了反爬,反反爬的大门。
绅士协议
什么是robots.txt? robots.txt(统一小写)是一种存放于网站根目录下的ASCII编码的文本文件,它通常告诉网络蜘蛛,此网站中的哪些内容是不应被搜索引擎的网络蜘蛛获取的,哪些是可以被网络蜘蛛获取的。robots.txt是一个这个绅士协议也不是一个规范,而只是约定俗成的,有些搜索引擎会遵守这一规范,而其他则不然。
这就说明了scrapy自动遵守了robots协议.(这个要在settings.py里面设置不遵守才可以爬得到把scrapy写进robots.txt的网站)
那么我就有个疑问,既然是个绅士协议,那么也就是说不具备强制力,一些流氓爬虫就可以我行我素的爬取,那么网站是怎么反爬的呢?
反爬
网站当然是有强制力的反爬措施:
1.查看80端口连接数量,一般来说爬虫并发连接非常高,然后找出这些IP,直接把这些IP的C网段ban掉,这是因为一般爬虫都是运行在托管机房里面,可能在一个C段里面的多台服务器上面都有爬虫,而这个C段不可能是用户宽带上网,封锁C段可以很大程度上解决问题;
2.有些爬虫隐蔽上做的好一点,并发连接不会很高,来源IP分布很广,那么第一种的办法的就很难通过上面封锁IP网段解决问题,对付这些爬虫就要用http头部的User-Agent信息识别,每个爬虫在爬取网页的时候,会声明自己的User-Agent信息,因此我们就可以通过记录和分析User-Agent信息来挖掘和封锁爬虫,通过收集统计User-Agent的信息,抽取User-Agent信息,找出访问量最大的那些爬虫的User-Agent来进行封锁
3.还有些爬虫连User-Agent都伪装了,把自己伪装成为一个真实浏览器的User-Agent,这种情况下我们可以通过网站流量系统记录的真实用户访问IP来进行识别.
主流的网站流量统计系统不外乎两种实现策略: ①一种策略是在网页里面嵌入一段js,这段js会向特定的统计服务器发送请求的方式记录访问量;
②另一种策略是直接分析服务器日志,来统计网站访问量。在理想的情况下,嵌入js的方式统计的网站流量应该高于分析服务器日志,这是因为用户浏览器会有缓存,不一定每次真实用户访问都会触发服务器的处理。但实际情况是,分析服务器日志得到的网站访问量远远高于嵌入js方式,极端情况下,甚至要高出10倍以上,这当中服务器日志得到的网站访问量远远高于嵌入js方式,就是因为有伪装成为浏览器的爬虫存在。
通过流量统计系统得到的用户IP基本是真实的用户访问,因为一般情况下爬虫是无法执行网页里面的js代码片段的,所以我们可以拿流量统计系统记录的IP和服务器程序日志记录的IP地址进行比较,如果服务器日志里面某个IP发起了大量的请求,在流量统计系统里面却根本找不到(因为爬虫没执行,但是浏览器会执行),或者即使找得到,可访问量却只有寥寥几个,那么无疑就是一个网络爬虫.
4.上面三种方法都是非实时的,都是基于信息收集和统计的,还有些更牛逼一点的分布式爬虫,寻找几百上千个国外的代理服务器疯狂的爬取你的网站,就会导致网站无法访问,这就需要实时地反爬,措施是在单位时间之内,如果一个IP的访问频率超过一个阀值,我们就认为这个IP很可能有问题,那么我们就可以返回一个验证码页面,要求用户填写验证码,如果是爬虫的话,当然不可能填写验证码,所以就被拒掉了。
反反爬
在知道网站反爬原理,针对性地修改你的爬虫策略,那么反反爬就变得有路可循,其实说到底,反爬还是斗不过反反爬,因为网站要给正常用户访问的,那么爬虫模仿正常的访问是可能的,爬虫的策略越贴近正常的用浏览器的访问,那么那么网站对这类隐蔽性极高的爬虫是非常困难的,更何况一些针对性的爬虫.
实战开始
以下是爬取weixin.sogou.com实战(linux系统下):
0.先来讲讲最开始接到这个让我们小组感到懵逼的作业以后,我们是怎么分析的。
首先完整的作业要求是“用scrapy抓取微信朋友圈的内容”,在初步认识scrapy的过程中,发现scrapy工作基于URL的,换句话说没有URL/IP,scrapy就没有办法开始工作。那么如何确定微信朋友圈的位置呢?即确定微信朋友圈的URL/IP,我们首先想到weixin.qq.com,看微信网页版有没有朋友圈,如果有的话,或许用抓微博的办法(模拟用户登录)尝试抓取,很可惜微信网页版并没有朋友圈这个功能。
那么另外一个贴合题目的办法就是确定手机端的微信的朋友圈的URL,可是这个是和运营商的IP分配有关,而且就算知道用户的IP,还要确定到手机内的微信的信息收集,这个在两个礼拜内根本不可能做的出什么成果,所以我们打算先爬取网页先来熟悉scrapy,然后又因为和weixin相关的有weixin.sogou.com,chuangsong.me等网站,最后我们选择用scrapy爬取weixin.sogou.com(事实证明在两个礼拜,加上还有其它课程的状态下这种选择是正确的,其实最后我们只能抓个weixin.sogou.com罢了)
1.新建wechat项目 首先默认你已经装了scrapy,linux下很方便,直接pip一个就好,win下自己折腾 命令行输入scrapy startproject wechat来创建一个wechat项目
2.项目结构(其中wechat.spider需要自己建立)
3.items.py
注意:items.py是我们想要抓取的项目名字,user是对应公众号名字,titile是首页热门文章的标题,text是对应文章的摘要。
4.pipelines.py
注意:定义了最后输出保存文件为wechat.json
5.settings.py
注意:ROBOTSTXT_OBEY = False这句,原来是True的,不改成False就爬不了weixin.sogou.com,因为weixin.sogou.com的robots.txt里面禁止了scrapy。不过实测weixin.sogou.com除了robots.txt以外并没有封User-Agent的措施,false掉robots.txt能顺利爬取(过频繁请求会不会被封还没有尝试).
ITEM_PIPELINES里面指定了用户pipeline的项目内位置
6.wechat.spider
注意: wechat.spider是整个项目中最核心的部分,name定义了爬虫的名字,等下项目的启动需要用到 allowed_domains就是允许爬虫爬取范围,规划了爬虫爬取范围 start_urls定义了爬虫爬取开始页面, parse中定义了分析分析规则,通过xpath精确定位我们需要的内容的位置,提取我们需要的部分,再放入item中,返回item.
xpath/re是关乎你是否能爬到你想要的信息的关键,这里需要实地考察(看网页的结构),然后对所要爬取内容的位置进行分析,然后多次尝试定位,据说xpath定位貌似比re准确,而且快?没感觉出来,不过要想精准,xpath学习的功夫和网页调研的时间不能少。
7.启动项目 wechat项目目录下命令行输入scrapy crawl wechat启动爬虫,等它跑完,就会储存到wechat.json文件里面,下面是没有爬取item[‘text’]的爬取结果
总结与感悟
其实说实在的直到现在觉得自己只是做了一个对爬虫的认识和scrapy框架的熟悉,只是刚刚入门,还有很多反爬的措施没有应对过,感觉自己在爬虫和反反爬上还有很长的路要走,特别是python基础上,不过刚做完的报告以后,老师说会给我们时间继续完善这个作业,直到可以真的爬到微信朋友圈内容,甚至会提供一些帮助,这就让我们有深入的时间了.
友情提醒:其实自己之前也自学过python,不过那时候的自己只会看语法,结果因为没有入手点和能动手的项目,没几天就把背书一样记下来的东西忘记光了,所以说从爬虫入手学python真的是一个不错的选择(或者在服务器管理上用python写个脚本也是不错的,但是我现在还处于学习shell script的阶段),比起单纯去看python教程要好,当然基础语法你要先过一遍,再以项目为目标去学习才得以深入。记得需求为先,计算机语言是为了完成人类需求而存在的.