scrapy: 使用HTTP代理绕过网站反爬虫机制

来源:互联网 发布:mac重装系统教程 编辑:程序博客网 时间:2024/06/05 10:49

下面的链接是我在python3.4 和Scarpy1.2上的实现的代理中间件

http://blog.csdn.net/letunihao/article/details/52350437

Table of Contents

  • 1. 简介
  • 2. 设计
  • 3. 实现
    • 抓免费代理的脚本
    • HttpProxyMiddleware
  • 4. 坑
  • 5. 想法

1 简介

最近接了个私活, 一同学在爬雪球网的数据时, 经常被雪球网以IP短时间内过多次访问为由要求输入验证码, 导致爬虫无法长时间运行. 一开始他的想法是用python的一些库自动识别验证码, 或者网上找一些人工输入验证码的服务来解决这个问题. 但是我看了一下雪球网的验证码还是挺复杂的, 肉眼看都不太好认, 自动识别应该是不行了. 至于人工打码服务, 看了一下他们的网站觉得整个一副”我有病毒, 我很山寨”的样子, 就完全不想用了. 于是我决定用HTTP代理来避免IP被禁就无法继续爬的问题.

经过一番调研, 国内提供稳定可靠的HTTP代理的服务基本没有. 国外倒是找到两个, 其中一个提供试用, 但是不知道为什么连不上他们的代理. 另一个最便宜也要$25/月, 钱倒是小事(反正不是我出), 但是不试用过不知道效果怎么样, 最终都放弃了. 另外还有个tor, 提供不定时的切换IP, 理论上来说是最适用我的需求的, 奈何一来连tor需要翻墙, 二来网速实在是慢. 最终决定试用网上免费提供的大陆高匿代理.

2 设计

scrapy提供下载中间件机制, 可以在请求队列与下载请求之间做一些动作. scrapy本身也提供了一个ProxyMiddleware, 但是它只能使用固定的IP地址, 由于免费的代理相当不稳定, 很多代理其实根本不能用. 因此需要对ProxyMiddleware改造使得这个middleware能够发现代理不可用, 并且在发现不可用的时候切换到另一个代理.

scrapy提供的ProxyMiddleware相当简单, 对其改造基本上等同于重新写一个了…首先就是如何发现一个代理不可用. 最常见的不可用代理的症状就是超时或者拒绝服务, 完全连不上, 为了处理这个问题, 新的ProxyMiddleware就要在process_exception里捕捉超时和ConnectionRefused异常. 还有些代理的问题是直接返回403或者407. 于是还要在process_response中检查response的status.

发现异常之后要换新的代理, 所以在新的ProxyMiddleware中需要一个list来保存所有代理, 每个代理还要有些属性, 例如valid, 这样当发现一个代理根本连不上时将valid属性设为False, 下次需要换代理时就忽略这些valid为False的代理, 避免再经历一遍超时.

另外就是发现IP被ban了之后更换代理, 一开始我是直接在middleware里处理这种情况, 但是IP被ban的检查各个网站都不一样, 写死在middleware里不太好. 于是我在spider里检查是否被ban, 如果被ban了则重新yield一个请求, 并设置meta["change_proxy"]=True, 然后在middleware里的process_request处检查这个属性, 如果为True则更换代理.

还有个问题就是代理数量不足的问题. 由于免费代理一般都是临时性的, 随着运行时间的增长, 有些代理会失效, 这样到最后就没有可用的代理了. 于是我在新的ProxyMiddleware里, 每次换新代理时检查代理列表中有效代理的数量, 如果小于一个阈值, 则从网上抓新的免费代理扩充代理列表.

3 实现

抓免费代理的脚本

这个脚本用于为了获取免费代理, 由于是为雪球网设计的, 主要抓的是大陆的高匿代理. 代码见https://github.com/kohn/HttpProxyMiddleware/blob/master/fetch_free_proxyes.py

抓代理的时候会简单筛选一下响应时间, 这个数据是提供免费代理的网站提供的.

HttpProxyMiddleware

见https://github.com/kohn/HttpProxyMiddleware

4 坑

光写个middleware其实一天就写好了, 接着又花了一天调参数. 然后在用到实际项目中去的时候就是与坑作斗争的血泪史.

有些代理根本不按常理出牌, 简单归纳一下:

  1. 将URL重定向到一个格式不合法的URL, 例如http://xueqiu.com/ 它给重定向到了http://xueqiu.com/http://xueqiu.com/. 通过设置request的dont_redirect属性以及检查302来解决
  2. 返回404, 500等各种各样的status. 解决方法是一个个加到检查列表里去(直接检查不等于200就换代理理论上应该可行)
  3. 最坑的就是虽然不好用, 但是返回的status是200! 只不过内容是一行错误信息. 这种错误在middleware里根本没法检查, 因为有些response的内容是一行错误信息说”… was not found on this server”(没找到你倒是返回404 啊), 而有些返回的内容是一个广告网站…这种代理只有在spider的parse里检查了, 如果找不到需要的内容, 就新建一个request, 设置meta["change_proxy"]=True来要求middleware换代理.
  4. 各种坑层出不穷, 防不胜防, 最终决定在获取免费代理时, 首先使用免费代理爬取一个测试用的网页, 如果能够爬下来并且比较过内容之后发现确实是目标网页, 则认为这个代理可用.

除了可用性之外, 在实际应用过程中还有一些效率上的问题需要优化.

  1. 使用代理总是比不使用代理要慢, 因此实现时用到了一个定时器, 当发现已经两小时没有用原生的连接(就是不用代理)去爬网页时, 自动切换到不用代理的情况.
  2. 运行过程中可能会出现”抖动”的问题, 当已有的n个代理都能正常使用, 但是被ban了, 就会不断的在这n个代理之间切换而实际上什么都没抓下来, 解决方法时定时(如半小时)抓取新的代理.

5 想法

写爬虫绕过网站的反爬虫机制应该是一个比较通用的需求, 但是国内竟然没有针对这一需求提供商业解决方案的公司. 如果能实现一个中间代理, 使得用户只要简单的将他的爬虫的代理设置为我的中间代理的URL, 然后由这个中间代理再去使用另一个代理根据用户需求抓数据, 并且能根据需要或者定时更换代理, 这样用户只要简单的设置一个代理, 就能实现IP的不断切换了, 这种服务应该能有盈利空间吧.

http_proxy_middleware_idea.png


https://github.com/kohn/HttpProxyMiddleware

https://github.com/cocoakekeyu/autoproxy

http://blog.csdn.net/xiao4816/article/details/50650075

0 0
原创粉丝点击