简单爬虫,突破IP访问限制和复杂验证码,小总结
简单爬虫,突破复杂验证码和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访问限制和复杂验证码,小总结的更多相关文章
- 爬虫遇到IP访问频率限制的解决方案
背景: 大多数情况下,我们遇到的是访问频率限制.如果你访问太快了,网站就会认为你不是一个人.这种情况下需要设定好频率的阈值,否则有可能误伤.如果大家考过托福,或者在12306上面买过火车票,你应该会有 ...
- Tor网络突破IP封锁,爬虫好搭档【入门手册】
本文地址:http://www.cnblogs.com/likeli/p/5719230.html 前言 本文不提供任何搭梯子之类的内容,我在这里仅仅讨论网络爬虫遇到的IP封杀,然后使用Tor如何对抗 ...
- 【小型系统】简单的刷票系统(突破IP限制进行投票)
一.前言 相信大家平时肯定会收到朋友发来的链接,打开一看,哦,需要投票.投完票后弹出一个页面(恭喜您,您已经投票成功),再次点击的时候发现,啊哈,您的IP(***.***.***.***)已经投过票了 ...
- 简单的刷票系统(突破IP限制进行投票) (转)
前言 相信大家平时肯定会收到朋友发来的链接,打开一看,哦,需要投票.投完票后弹出一个页面(恭喜您,您已经投票成功),再次点击的时候发现,啊哈,您的IP(***.***.***.***)已经投过票了,不 ...
- java爬虫进阶 —— ip池使用,iframe嵌套,异步访问破解
写之前稍微说一下我对爬与反爬关系的理解 一.什么是爬虫 爬虫英文是splider,也就是蜘蛛的意思,web网络爬虫系统的功能是下载网页数据,进行所需数据的采集.主体也就是根据开始的超链接,下 ...
- Python做简单爬虫(urllib.request怎么抓取https以及伪装浏览器访问的方法)
一:抓取简单的页面: 用Python来做爬虫抓取网站这个功能很强大,今天试着抓取了一下百度的首页,很成功,来看一下步骤吧 首先需要准备工具: 1.python:自己比较喜欢用新的东西,所以用的是Pyt ...
- [转帖]nginx 禁止ip访问以及禁止post方法的简单方法
nginx禁止IP访问站点的设置方法 http://www.512873.com/archives/471.html http://www.512873.com/archives/312.html c ...
- 可能是一份没什么用的爬虫代理IP指南
写在前面 做爬虫的小伙伴一般都绕不过代理IP这个问题. PS:如果还没遇到被封IP的场景,要不就是你量太小人家懒得理你,要不就是人家压根不在乎... 爬虫用户自己是没有能力维护一系列的代理服务器和代理 ...
- python爬虫-基础入门-python爬虫突破封锁
python爬虫-基础入门-python爬虫突破封锁 >> 相关概念 >> request概念:是从客户端向服务器发出请求,包括用户提交的信息及客户端的一些信息.客户端可通过H ...
随机推荐
- Tengine 安装配置全过程
Tengine官网上有个非常简单的教程,中间并未涉及到一些常用的设置,所以仅供参考.一下午为本人的安装步骤及过程. 1.安装必要的编译环境好 由于Tengine安装需要使用源代码自行编译,所以在安装前 ...
- 深入理解JSX
本文由笔者翻译自官方文档的JSX In Depth,若干案例经过了改写.其实说白了也好像不算太深入,但还是提示了一些可能的盲区. JSX是为构造React元素方法React.createElement ...
- 237. Delete Node in a Linked List
在链接列表中删除节点. 编写一个函数来删除单链表中的一个节点(除了尾部),只提供对该节点的访问..假设链表是1 - > 2 - > 3 > 4,并给出了具有值为3的节点, 链表应该成 ...
- MySQL练习-employees数据库(一)
安装一个数据库示例--employees 使用工具为Navicat--(ctrl + q: 打开新查询窗口 ctrl + r: 运行当前窗口内的所有语句) 参考http://www.cnblogs.c ...
- iOS中如何监测来电
http://blog.csdn.net/liujinlongxa/article/details/44207587
- 最新 Eclipse IDE下的Spring框架配置及简单实例
前段时间开始着手学习Spring框架,又是买书又是看视频找教程的,可是鲜有介绍如何配置Spring+Eclipse的方法,现在将我的成功经验分享给大家. 本文的一些源代码来源于码农教程:http:// ...
- c++ 接口和抽象类
其实对抽象类与接口的区别一直是搞不太清楚,最近正在学习<设计模式>,期间用到了很多c++多态的知识.这是才恍然发现,是应该整理下这方面的知识了.但在翻阅书本.上网查阅资料之际,发现有篇文章 ...
- EBS中加载FORM使用的JavaBean的JAR包
1.SSH端,APP用户登录: 2.输入env,确定环境变量名称FORMS_WEB_CONFIG_FILE: 3.定位模板文件: $AD_TOP/bin/adtmplreport.sh con ...
- 让VS2010支持Windows2000
2015-10-20 14:21 375人阅读 评论(0) 收藏 举报 分类: 学习笔记(33) 技术心得(1) 用Visual Studio 2010编译的程序无法在Windows 200 ...
- Maven的Missing artifact问题解决
Maven的Missing artifact问题解决 今天在创建一个新的Maven项目时,在其中添加了很多依赖.刚开始为了避免错误就每添加一次,保存一下,Eclipse就会下载相应的包.最后为了 ...