简单爬虫,突破复杂验证码和IP访问限制

文章地址:http://www.cnblogs.com/likeli/p/4730709.html

     好吧,看题目就知道我是要写一个爬虫,这个爬虫的目标网站有一些反爬取意识,所以就有了本文了。

我先说说场景吧:

由于工作需要,平时有一大堆数据需要在网上查询,并归档存库。某次,这种任务也给我安排了一份。观察了一网站,我的第一反应就是用爬虫取抓取。这种机械的工作何必人工呢?

由于这家网站有反爬虫的意识,做了些工作,给我的爬虫去爬取数据造成了某些麻烦。

先列举出问题所在:

  • 首当其冲,验证码,该网站采用了数字加中文的简单四则运算作为验证码。
  • 查询目标路径参数经过了加密,我并不能直接通过取路径加参数的方式来直接跳过某些页面。
  • IP限制,该网站对访问的IP做了访问次数计数限制。经过我的测试,一个纯净IP访问该网站一小时内最多能爬取40个有效数据(这里针对我的抓取目标来说,HTTP请求次数差不多之多200次,但是若在30s内访问次数超过25次HTTP请求,那么这个IP就直接被封掉)

好吧,主要的问题就是这些,一些爬取过程中的小问题,就不列举了。园子里面一大堆的解决方案。这里我主要说的是,验证码和IP限制 的问题。

当然,我的解决方案并不是什么高超的技巧。应该都是老路子了。

1、  验证码

原图:

  

这种的验证码难度在于字符粘连,字符随机旋转问题。这两种,我分别采用了投影直方图分割卡壳法来分别切割字符和校正角度。

   我首先写了一个工具来测试:

   从上面的效果图,各位看官应该能看出,我的方法还是比较简单和传统的,那就是做特征库,通过分割出来的字符去匹配特征库的相似度来判断图片中的文字到底是什么。这里没有使用 第三方的光学识别(OCR ),因为识别汉字感觉识别率还是比较差,而且验证码中的汉字其实并不多,就是几个特定的字符,加减乘除等。所以通过特征库来识别也是绰绰有余了。

    关于验证码,我来说说我的一些问题,对于灰度计算和二值化,园子里面有很多算法,但是对于降噪,也就是去干扰线,需要自己根据目标来写特定的算法。我这里是通过削皮的方式来去掉的,每次给所有阴影剥掉一层1px的范围,填充为白色。当然了,我这方法不具备通用性。不同的验证码需要根据观察来用不同的方式来去除。

  分割呢,也就是直方图了,其实我的验证码也是可以根据色彩来做单色的直方图,这样来一步完成分割字符和降噪(有这想法,但是没有实际去实现。不过看有些大牛的博客说这样的方法是可行的)。我所了解到的分割方法还有滴水分割,不过我拿了论文资料,可惜看得不是很懂。下面贴了一段简单绘制直方图的方法:

 //绘制直方图
var zftbit = new Bitmap(bit4.Width, bit4.Height);
using (Graphics g = Graphics.FromImage(zftbit))
{
Pen pen = new Pen(Color.Blue);
for (int i = ; i < bit4.Width; i++)
{
g.DrawLine(pen, i, bit4.Height - YZhiFang[i] * , i, bit4.Height);
}
//阀值
g.DrawLine(new Pen(Color.Red), , bit4.Height - , bit4.Width, bit4.Height - );
}
p_zft.Image = zftbit;

绘制直方图

  关于随机旋转的字符问题,我的做法是,将验证码中的字符分割成独立单位后,进行正负30度旋转,每旋转一次,计算一次投影宽度,由于我们的字体基本上都是‘方块字’,所以呢,在旋转的时候,最小宽度肯定是‘摆正’了的,不过,这里有个小问题,那就是若源字符旋转超过45°,我们将字横着放置的时候,其宽度也是最小的。不过我们让机器多学习几次,将四个方向摆放的图形都学习了,就可以了。这就是卡壳法了。

2、IP限制问题

  这里我用了最无赖也是最无解的方法来解决的。我直接通过切换访问的代理来突破,这里没有丝毫技术性含量。挂上代理后,去访问目标网站,根据返回的结果判断代理是否还有效。若是无效了,将当前查询目标回滚一次,并切换代理就行了。

3、爬虫

  主角爬虫来了,我最早设计的爬虫是不控制时间的连续访问的,这导致代理消耗的特别快。所以不得不想办法解决这个问题。另外由于没有专门的爬虫服务器,我只能通过办公室的电脑来完成这项任务。由此,我设计了一个总线式爬虫。

  我写了一个爬虫服务端和一个爬虫客户端,服务端当做中央处理器,来分配计算量,客户端爬虫用来抓取数据。这样的情况下,各个客户端执行的速度其实是不一样的,请求响应又快又慢,验证代理是否有效也需要时间,所有,客户端爬虫完成任务的时间肯定不一样,所以我安排了这样一台电脑做作为中央处理器,分批次,小剂量的去分发任务列表。并接收客户端回传的结果,等完成所有任务之后统一导出或者进行写入数据库等其他操作。

爬虫节点

  每个节点上的爬虫,给17个线程去跑,10个做代理IP的验证,7个爬数据。若是给10台办公室的笔记本安装软件,一起去爬数据,那么,就相当于 70人/秒 的速度在访问这个网站。至此,效率问题也解决了。

总线

  总线方面,将任务列表根据下面的节点数进行分配(上图是之前截的图,之前是均分出去,后来发现均分的客户端并不是同时完成,有的快有的慢,结果快的弄完了,就空闲了,慢的还在慢吞吞的跑,所以,之后进行了小剂量分配,变相的达到动态的安排任务量)。

后记

  文章到此就基本上结束了,代码不多,我主要数我的制作思路,因为我的的这个并不具备通用性,验证码家家基本都不一样(一些极度简单的规规矩矩的纯数字或字母验证码不算,这类验证码跟没有一样)。

2018年09月30日

  多年后来更新这篇文章:当年萌新的技术缺点

    1. 验证码识别的方式太辣鸡,算法复杂度O(n^2),辣鸡中的战斗鸡

    2. 采用分布式的思维来做,这点,我很肯定当年的萌新,毕竟是自己想出来的提速方法嘛。也想到了队列这个概念,现在可以对这里的队列重新定义一下,可以采用RabbitMQ等中间件来完成分发任务,更可靠也更高效。

    3. 感谢当年萌新的彻夜奋斗!

简单爬虫,突破IP访问限制和复杂验证码,小总结的更多相关文章

  1. 爬虫遇到IP访问频率限制的解决方案

    背景: 大多数情况下,我们遇到的是访问频率限制.如果你访问太快了,网站就会认为你不是一个人.这种情况下需要设定好频率的阈值,否则有可能误伤.如果大家考过托福,或者在12306上面买过火车票,你应该会有 ...

  2. Tor网络突破IP封锁,爬虫好搭档【入门手册】

    本文地址:http://www.cnblogs.com/likeli/p/5719230.html 前言 本文不提供任何搭梯子之类的内容,我在这里仅仅讨论网络爬虫遇到的IP封杀,然后使用Tor如何对抗 ...

  3. 【小型系统】简单的刷票系统(突破IP限制进行投票)

    一.前言 相信大家平时肯定会收到朋友发来的链接,打开一看,哦,需要投票.投完票后弹出一个页面(恭喜您,您已经投票成功),再次点击的时候发现,啊哈,您的IP(***.***.***.***)已经投过票了 ...

  4. 简单的刷票系统(突破IP限制进行投票) (转)

    前言 相信大家平时肯定会收到朋友发来的链接,打开一看,哦,需要投票.投完票后弹出一个页面(恭喜您,您已经投票成功),再次点击的时候发现,啊哈,您的IP(***.***.***.***)已经投过票了,不 ...

  5. java爬虫进阶 —— ip池使用,iframe嵌套,异步访问破解

    写之前稍微说一下我对爬与反爬关系的理解 一.什么是爬虫      爬虫英文是splider,也就是蜘蛛的意思,web网络爬虫系统的功能是下载网页数据,进行所需数据的采集.主体也就是根据开始的超链接,下 ...

  6. Python做简单爬虫(urllib.request怎么抓取https以及伪装浏览器访问的方法)

    一:抓取简单的页面: 用Python来做爬虫抓取网站这个功能很强大,今天试着抓取了一下百度的首页,很成功,来看一下步骤吧 首先需要准备工具: 1.python:自己比较喜欢用新的东西,所以用的是Pyt ...

  7. [转帖]nginx 禁止ip访问以及禁止post方法的简单方法

    nginx禁止IP访问站点的设置方法 http://www.512873.com/archives/471.html http://www.512873.com/archives/312.html c ...

  8. 可能是一份没什么用的爬虫代理IP指南

    写在前面 做爬虫的小伙伴一般都绕不过代理IP这个问题. PS:如果还没遇到被封IP的场景,要不就是你量太小人家懒得理你,要不就是人家压根不在乎... 爬虫用户自己是没有能力维护一系列的代理服务器和代理 ...

  9. python爬虫-基础入门-python爬虫突破封锁

    python爬虫-基础入门-python爬虫突破封锁 >> 相关概念 >> request概念:是从客户端向服务器发出请求,包括用户提交的信息及客户端的一些信息.客户端可通过H ...

随机推荐

  1. sublime 安装插件GitGutter报错,git binary cannot be found等等

    今天给sublime text安装插件GitGutter的时候,居然报错了,网上查找了下解决方法,在此记录下.因为本博主的电脑是windows的,所以这里只能提供windows的方法啦. 解决方法很简 ...

  2. runtime-对成员变量和属性的操作

    成员变量 首先我们来看看成员变量在runtime中是什么样的 在runtime中成员变量是一个objc_ivar类型的结构体,结构体定义如下 struct objc_ivar { char *ivar ...

  3. 调用手机在线API获取手机号码归属地信息

    手机在线(www.showji.com)始创于2001年,发展至今已拥有国内最准确.号段容量最大的手机号码归属地数据库系统, 目前号段容量将近33万条,每月保持两次以上规模数据更新,合作伙伴包括:百度 ...

  4. 【转】 jquery遍历json数组方法

    $(function () { var tbody = ""; //------------遍历对象 .each的使用------------- //对象语法JSON数据格式(当服 ...

  5. 关于unity如何制作mmo

    昨天去看了下unity的成都openday,还是有很多收获的,之前我对于这类的活动始终提不起来兴趣,不过看来日后还是要多参加下类似的活动长长见识. 公司打算开发3d mmo手游,昨天好玩123恰好也分 ...

  6. Hadoop基础思维导图

  7. React入门

    一.引入Reactjs 方法一:直接下载相关js文件引入网页,其中react.js 是 React 的核心库,react-dom.js 是提供与 DOM 相关的功能,Browser.js 的作用是将 ...

  8. Python 3.x 连接数据库(pymysql 方式)

    ==================pymysql=================== 由于 MySQLdb 模块还不支持 Python3.x,所以 Python3.x 如果想连接MySQL需要安装 ...

  9. Mongodb命令集合

    一.数据库常用命令 1.Help查看命令提示 复制代码代码如下: help db.help(); db.yourColl.help(); db.youColl.find().help(); rs.he ...

  10. XCode8目录整理后的几个警告消除,Missing file

    Git目录没有及时更新导致 终端进入目录运行如下命令 git rm main.m git rm Info.plist git rm AppDelegate.h git rm AppDelegate.m ...