浅谈Scrapy框架普通反爬虫机制的应对策略


Posted in Python onDecember 28, 2017

简单低级的爬虫速度快,伪装度低,如果没有反爬机制,它们可以很快的抓取大量数据,甚至因为请求过多,造成服务器不能正常工作。而伪装度高的爬虫爬取速度慢,对服务器造成的负担也相对较小。

爬虫与反爬虫,这相爱相杀的一对,简直可以写出一部壮观的斗争史。而在大数据时代,数据就是金钱,很多企业都为自己的网站运用了反爬虫机制,防止网页上的数据被爬虫爬走。然而,如果反爬机制过于严格,可能会误伤到真正的用户请求;如果既要和爬虫死磕,又要保证很低的误伤率,那么又会加大研发的成本。

简单低级的爬虫速度快,伪装度低,如果没有反爬机制,它们可以很快的抓取大量数据,甚至因为请求过多,造成服务器不能正常工作。而伪装度高的爬虫爬取速度慢,对服务器造成的负担也相对较小。所以,网站反爬的重点也是那种简单粗暴的爬虫,反爬机制也会允许伪装度高的爬虫,获得数据。毕竟伪装度很高的爬虫与真实用户也就没有太大差别了。

这篇文章主要讨论使用Scrapy框架时,如何应对普通的反爬机制。

header检验

最简单的反爬机制,就是检查HTTP请求的Headers信息,包括User-Agent,Referer、Cookies等。

User-Agent

User-Agent是检查用户所用客户端的种类和版本,在Scrapy中,通常是在下载器中间件中进行处理。比如在setting.py中建立一个包含很多浏览器User-Agent的列表,然后新建一个random_user_agent文件:

class RandomUserAgentMiddleware(object): @classmethod defprocess_request(cls, request, spider): ua = random.choice(spider.settings['USER_AGENT_LIST']) if ua: request.headers.setdefault('User-Agent', ua)

这样就可以在每次请求中,随机选取一个真实浏览器的User-Agent。

Referer

Referer是检查此请求由哪里来,通常可以做图片的盗链判断。在Scrapy中,如果某个页面url是通过之前爬取的页面提取到,Scrapy会自动把之前爬取的页面url作为Referfer。也可以通过上面的方式自己定义Referfer字段。

Cookies

网站可能会检测Cookie中session_id的使用次数,如果超过限制,就触发反爬策略。所以可以在Scrapy中设置COOKIES_ENABLED=False让请求不带Cookies。

也有网站强制开启Cookis,这时就要麻烦一点了。可以另写一个简单的爬虫,定时向目标网站发送不带Cookies的请求,提取响应中Set-cookie字段信息并保存。爬取网页时,把存储起来的Cookies带入Headers中。

X-Forwarded-For

在请求头中添加X-Forwarded-For字段,将自己申明为一个透明的代理服务器,一些网站对代理服务器会手软一些。

X-Forwarded-For头一般格式如下

X-Forwarded-For:client1,proxy1,proxy2

这里将client1,proxy1设置为随机IP地址,把自己的请求伪装成代理的随机IP产生的请求。然而由于X-Forwarded-For可以随意篡改,很多网站并不会信任这个值。

限制IP的请求数量

如果某一IP的请求速度过快,就触发反爬机制。当然可以通过放慢爬取速度绕过,这要以爬取时间大大增长为代价。另一种方法就是添加代理。

很简单,在下载器中间件中添加:

request.meta['proxy'] = 'http://' + 'proxy_host' + ':' + proxy_port

然后再每次请求时使用不同的代理IP。然而问题是如何获取大量的代理IP?

可以自己写一个IP代理获取和维护系统,定时从各种披露免费代理IP的网站爬取免费IP代理,然后定时扫描这些IP和端口是否可用,将不可用的代理IP及时清理。这样就有一个动态的代理库,每次请求再从库中随机选择一个代理。然而这个方案的缺点也很明显,开发代理获取和维护系统本身就很费时费力,并且这种免费代理的数量并不多,而且稳定性都比较差。如果必须要用到代理,也可以去买一些稳定的代理服务。这些服务大多会用到带认证的代理。

在requests库中添加带认证的代理很简单,

proxies = { "http": "http://user:pass@10.10.1.10:3128/", }

然而Scrapy不支持这种认证方式,需要将认证信息base64编码后,加入Headers的Proxy-Authorization字段:

importbase64 # Set the location of the proxy proxy_string = choice(self._get_proxies_from_file('proxies.txt')) # user:pass@ip:port proxy_items = proxy_string.split('@') request.meta['proxy'] = "http://%s" % proxy_items[1] # setup basic authentication for the proxy user_pass=base64.encodestring(proxy_items[0]) request.headers['Proxy-Authorization'] = 'Basic ' + user_pass

动态加载

现在越来越多的网站使用ajax动态加载内容,这时候可以先截取ajax请求分析一下,有可能根据ajax请求构造出相应的API请求的URL就可以直接获取想要的内容,通常是json格式,反而还不用去解析HTML。

然而,很多时候ajax请求都会经过后端鉴权,不能直接构造URL获取。这时就可以通过PhantomJS+Selenium模拟浏览器行为,抓取经过js渲染后的页面。

需要注意的是,使用Selenium后,请求不再由Scrapy的Downloader执行,所以之前添加的请求头等信息都会失效,需要在Selenium中重新添加

headers = {...} for key, valuein headers.iteritems(): webdriver.DesiredCapabilities.PHANTOMJS['phantomjs.page.customHeaders.{}'.format(key)] = value

另外,调用PhantomJs需要指定PhantomJs的可执行文件路径,通常是将该路径添加到系统的path路径,让程序执行时自动去path中寻找。我们的爬虫经常会放到crontab中定时执行,而crontab中的环境变量和系统的环境变量不同,所以就加载不到PhamtonJs需要的路径,所以最好是在申明时指定路径:

driver = webdriver.PhantomJS(executable_path='/usr/local/bin/phantomjs')

总结

以上就是本文关于浅谈Scrapy框架普通反爬虫机制的应对策略的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:

如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

Python 相关文章推荐
Django集成百度富文本编辑器uEditor攻略
Jul 04 Python
python从网络读取图片并直接进行处理的方法
May 22 Python
使用Python的Flask框架构建大型Web应用程序的结构示例
Jun 04 Python
python验证码识别教程之利用滴水算法分割图片
Jun 05 Python
Python爬虫框架scrapy实现的文件下载功能示例
Aug 04 Python
python 输入一个数n,求n个数求乘或求和的实例
Nov 13 Python
Python面向对象基础入门之设置对象属性
Dec 11 Python
python pandas写入excel文件的方法示例
Jun 25 Python
django url到views参数传递的实例
Jul 19 Python
Windows上安装tensorflow  详细教程(图文详解)
Feb 04 Python
python 调整图片亮度的示例
Dec 03 Python
使用Python下载抖音各大V视频的思路详解
Feb 06 Python
scrapy爬虫实例分享
Dec 28 #Python
Python解决N阶台阶走法问题的方法分析
Dec 28 #Python
Python实现嵌套列表去重方法示例
Dec 28 #Python
Python登录并获取CSDN博客所有文章列表代码实例
Dec 28 #Python
python 寻找优化使成本函数最小的最优解的方法
Dec 28 #Python
python机器学习案例教程——K最近邻算法的实现
Dec 28 #Python
Python实现螺旋矩阵的填充算法示例
Dec 28 #Python
You might like
编写漂亮的代码 - 将后台程序与前端程序分开
2008/04/23 PHP
让浏览器非阻塞加载javascript的几种方法小结
2011/04/25 Javascript
JS添加删除一组文本框并对输入信息加以验证判断其正确性
2013/04/11 Javascript
JavaScript动态创建div属性和样式示例代码
2013/10/09 Javascript
JQuery异步获取返回值中文乱码的解决方法
2015/01/29 Javascript
js实现可兼容IE、FF、Chrome、Opera及Safari的音乐播放器
2015/02/11 Javascript
JS实现不使用图片仿Windows右键菜单效果代码
2015/10/22 Javascript
JavaScript实现简单获取当前网页网址的方法
2015/11/09 Javascript
AngularJS实现标签页的两种方式
2016/09/05 Javascript
Javascript动画效果(4)
2016/10/11 Javascript
浅谈js停止事件冒泡 阻止浏览器的默认行为(阻止超连接 #)
2017/02/08 Javascript
使用Node.js实现ORM的一种思路详解(图文)
2017/10/24 Javascript
浅谈vue2 单页面如何设置网页title
2017/11/08 Javascript
详解vue数组遍历方法forEach和map的原理解析和实际应用
2018/11/15 Javascript
Vue 子组件与数据传递问题及注意事项
2019/07/11 Javascript
bootstrap table实现横向合并与纵向合并
2019/07/18 Javascript
layui type2 通过url给iframe子页面传值的例子
2019/09/06 Javascript
使用layui的layer组件做弹出层的例子
2019/09/27 Javascript
Vue管理系统前端之组件拆分封装详解
2020/08/23 Javascript
Python警察与小偷的实现之一客户端与服务端通信实例
2014/10/09 Python
Python脚本在Appium库上对移动应用实现自动化测试
2015/04/17 Python
Python3字符串学习教程
2015/08/20 Python
python OpenCV学习笔记实现二维直方图
2018/02/08 Python
python使用正则表达式去除中文文本多余空格,保留英文之间空格方法详解
2020/02/11 Python
培训演讲稿范文
2014/01/12 职场文书
入党自我鉴定
2014/03/25 职场文书
卫校毕业生个人自我鉴定
2014/04/28 职场文书
经营理念口号
2014/06/21 职场文书
国家机关领导干部民主生活会对照检查材料思想汇报
2014/09/17 职场文书
出生公证书
2015/01/23 职场文书
学校清洁工岗位职责
2015/04/15 职场文书
世界名著读书笔记
2015/06/25 职场文书
百善孝为先:关于孝道的经典语录
2019/10/18 职场文书
5分钟教你docker安装启动redis全教程(全新方式)
2021/05/29 Redis
MySQL注入基础练习
2021/05/30 MySQL
CentOS7设置ssh服务以及端口修改方式
2022/12/24 Servers