爬虫中的验证码识别-反爬与反反爬的奇技淫巧

上一课带大家聊了聊反爬与反反爬最基础的对抗-代理ip,别看这个简单,真正处理好了代理ip基本上解决大半的爬虫问题,包括本节的验证码。很多网站弹出验证码也是因为发现ip重复过多,比如搜狗微信搜索,如果在合理的时间切换ip,就可以完美的躲避掉搜狗微信中的验证码(注意只有搜狗微信中的验证码可以,微信中的是不可以的,其中区别可以通过浏览器中的域名来区分)。

上一篇文章写完之后,爬虫天坑的文章意外收获了不少赞,这里拜谢大家支持,同时如果天坑系列破百赞的话,我会继续更新那个系列。

要完了赞,扯完了废话,我们赶紧进入这一篇文章的正题-验证码识别。

先让我来摘抄一段验证码的介绍:

验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机还是人的公共全自动程序。

话说直到今天我才知道CAPTCHA原来是这么直白的英文缩写,外国人对单词的缩写狂热真是一点不比国人差啊。(突然想到刚进公司那会摸不着头脑的TGIF)

那好了,延续上篇文章的套路,我们先来看看反爬:

一.为什么验证码可以反爬?

简单来说,是人类有着一种天赋,可以很轻松的从一段图片中识别出文字和数字,而机器却不能。但是由于这些年机器学习的飞速进展。这项技能上人类和机器之间的差距越来越小,导致为了区分人和机器,人类工程师已经快达到变态的地步,终于诞生了宇宙无敌12306验证码:

当然这些年同样随着机器学习技术的飞速进展,验证码也开始出现了新的形式,比如极验验证为代表的轨迹模式,这类的优缺点我们后面再聊。

二.如何使用验证码实现反爬?

使用验证码相信是所有web工程师的基本功,百度谷歌上一搜一大堆,还有自动生成代码的。对于普通图文类的验证码,无非就是先生成随机串,再生成图片,将随机串存入session,等待用户提交后进行比对。或者也可以集成极验验证这类第三方验证服务,这里就不再赘述了。

使用验证码都会使用,那我们这里着重讲一讲到底该如何选择,这些常用验证码形式利弊各有哪些:

1.数字字母验证码:这类验证码优点是生成简单,大部分语言都自带图形库,在加入一点扭曲和噪点,基本可以解决掉初级爬虫工程师和暴力破解的脚本小子。缺点当然也显而易见,对于cnn代码只用写10行的今天,这些验证码只要有足够的标注数据,破解起来简直是轻而易举。我们在微信验证码识别中大约使用了10万张标注好的图片进行训练就可以完成类似人的准确度,具体可以参考我们的应用-微信文章爬虫[按公众号或关键字]-神箭手云

2.中文验证码:比如知乎采用过的验证码选择倒立的中文以及网易邮箱类的验证码(标记文字位置)。这类验证码一般来很少有公用的代码,因此编写起来麻烦。不过也正因为每一家采用的都不一样,在加上中文庞大的汉字库,确实给机器识别带来的比较大的挑战,如果配合好字体和扭曲,确实可以有不错的效果。

3.极验验证:这几年新型的验证码代表,很多网站争相采用。首先抛开技术角度,仅从成本角度来说,我是不太推荐大家用这类验证码的,越广泛的越不宜使用。对于一个网站特有的验证码体系,破解难度大,收益小。但这么多网站采用同一种验证码,即使破解难度再大,也必然有人会去尝试,因为收益太大。

反过来说说极验采用的技术,极验的v2版验证体系破解难度甚至比不过数字字母验证码来的复杂,唯一的优势就是现在大部分打码平台不支持。图片识别上直接对比像素就可以识别位置,唯一难点的移动轨迹,但用轨迹做分类人类和机器间的特征并不那么明显,加上网页中采集轨迹的准确性较差,因此做一些简单的模拟就可以轻松躲过轨迹识别。网上有很多破解方案。

当然验证码还有很多类型,比如12306这类,整体来说,如果对反爬要求很高,最好是自己实现,如果没有12306这种庞大的图片库,比较推荐的就是采用中文验证码模式(不是直接识别中文,而是标记中文位置类型的)。不太推荐采用极验验证这种,毕竟太多人使用意味着就像把自己的船和别人的船都连在一起,虽然稳定,但是一把火烧过来,大家全部遭殃。更不推荐采用数字+字母模式,这种实在烂大街,打码平台一分钱一次,包括算术类,麻烦自己,也没有提高太多识别门槛。

三.如何识别验证码?

识别验证码也一直是爬虫工程师的基本功,特别对于有登录需求的爬虫来说,验证码也是一道绕不过去的坎,那我们从反反爬的角度,来看看识别验证码的常用姿势。

1.打码平台:最常用,最简单的识别,唯一的难度就在于选择集成(也是一些工程性的东西),一般字母文字1分一次,中文识别略贵,计算题可能5分吧。具体大家可以去搜一搜,这里不赘述了。不支持极验这类。

2.OCR库:这个嘛,虽然换汤不换药,但是这个词听起来就显得灰尘味很重,另外,传统的ocr采用先切割再识别的方案,对于新型的验证码已经很难做了,不建议大家尝试这个方案。

3.机器学习:端到端数字字母识别神器,具体方案我在爬虫天坑系列-百度指数爬虫 这篇文章中已经有所介绍,根据识别难度和长度不同,对标注数据的需求量不一样,当然图片预处理也稍微有些区别,其他的,直接从网上找代码贴进来跑就好。(插个广告,神箭手平台支持直接运行tensorflow代码,并且自动生成serving接口)

4.神箭手库:我们内置了solveCaptcha和solveGeetest两个函数,对于部分验证码还是免费的,大家自己体会一下。

5.其他:之所以列一个其他,对于一些特殊验证码,比如12306不仅需要识别结果,还需要识别问题等等特殊的。单个问题单个对待,可能需要结合多重知识,这里就不展开讲了。

好了,最后说两句:验证码这篇一方面给大家提供了一个验证码类型的选择方案,同时也展示了识别验证码的难易和常见方法。事实上,很多时候,优秀的工程师并不是写代码写的最快的,而是遇到一个问题就知道哪个方案是最合适的。不断积累这种经验,让我们在工作中事半功倍。

下一篇给大家讲讲反爬与反反爬第三常规战斗-Cookies

爬虫被封IP了怎么办-反爬与反反爬的奇技淫巧

大家好,好久不见了,之前写了一篇爬虫天坑系列的文章,本想继续写下去,没想到可能篇幅太长,废话太多,导致很多朋友感觉帮助不大。因此组织上决定,从这篇文章开始,让我写一些更接地气的文章。


其实很多人都觉得爬虫没什么深奥的技术,但是又觉得想真正写好爬虫却似乎很难。原因就在于爬虫本身的功能简单,而真正难的都在反反爬技术当中。那从今天开始我们一起来聊一聊反爬和反反爬们使用的那些奇技淫巧。

说到反爬,最简单的方法莫过于封IP了,简单有效,还很难破解。这就像门卫大爷问你叫什么,你说你叫周杰伦,下次你再来,你还说你叫周杰伦,那大爷肯定问:“怎么又是你!滚”(这个例子举的有点暴露年龄)。


1.为啥封ip有效?

其实一次网页请求,还有大量的信息,比如UserAgent,比如Cookie。那为啥封ip最有效?是因为其他的信息都可以伪造,但是http请求中却无法直接伪造ip的,了解网络协议的同学们应该知道,http协议基于tcp,而tcp协议存在握手机制的,这样你就绝对无法用假的ip来连接了。就像你要写信给一个小姐姐,然后希望小姐姐回信,但是你却写了一个假的发信地址,那你就是注孤生了。(当然,你可以写一个小哥哥的地址,让小哥哥把收到的信再交给你,这样的话,你能不能收到信,就取决于小哥哥的人品了,当然回到代码里,就是代理服务器的稳定性。)


2.怎么封ip?

我们先来看看老牌论坛程序Discuz的反爬功能-防采集:


非常简单粗暴,一个ip只允许访问多少次,这里默认是200次。也就是说当一个ip访问超过200次就会记入黑名单,限制访问。实现方式也很简单,对于大部分语言来说,获取ip地址都是很简单的,获取到ip之后,将ip作为主键存入数据库中(当然discuz会将ip转换成int来做一些优化,减小主键占用的空间)。最后再加一个字段来记录访问次数就可以了。

当然当我们每天ip数量很多的时候,我们可以考虑存入非关系型数据库中,毕竟我们只需要key-value形式的数据,用关系型数据库反倒浪费了。


3.救命啊,我的爬虫封ip了怎么办?

说完了反爬,我们来说反反爬。爬虫被封ip简直就是所有爬虫工程师必须要迈过去的一道坎,而作为这个行业混迹多年的老司机,对于ip怎么来的问题,那是相当的熟悉。下面一一给大家梳理一下利弊:

    1、自己想办法伪造:赶紧打消这个念头,浪费时间,当年我们给中国移动做爬虫系统,作为运营商,人家都不自己造ip。

    2、从万能的淘宝上买:跟很多人一样,我当年第一次需要ip的时候,也是第一时间求助万能的淘宝。但后来才了解,淘宝上的ip大多都是从专业代理ip厂商买过来,然后进行二次销售,很多过期的,稳定性和可用率可以说是相当的差,如果是做爬虫的基本可以放弃,如果是干其他什么我完全不了解的事情,勉强可以尝试,毕竟比较便宜。

    3、代理IP服务商:现在比较好的几家是:全网代理,tk代理,快代理(不包含一些量小质高,非批量的代理ip服务商)。每家的优点不一样,全网的代理相对质量较高,tk代理数量多,而快代理则有自建的私密代理,但数量不多。这类厂商大部分的代理是通过自己写的ip扫描程序从网上扫来的,质量比淘宝的能好点,用作爬虫的话,需要自己先做一次过滤,大概每天过滤出来的可用的ip大约在1000左右,如果每天爬的网页不多,可以尝试,价格不是特别便宜。另外像是微信爬虫这种,扫描来的ip基本就是废,因为早就被别人用的时候就被封了。

    4、神箭手云爬虫:作为神箭手创始人之一,我对自己的产品从来都是不吹不黑的,神箭手的代理ip怎么说呢,可以说是宇宙之内找不到第二家的存在。我们首先买了三家主流代理ip服务商的所有ip,然后给大家免费用(你没有看错,就是免费用),但是为了爬一些鹅厂,狼厂这类大厂的网页,我们又自建了几百台代理服务器,每天产生40万的私密代理ip(注意是40万是实际ip,不是什么ip池)。价格却便宜到没朋友,给大家对比一下我们和快代理的价格对比:快代理3600元/每月,每天5000ip,神箭手299元/每月,每天40万ip。当然我们也有限制:只有在我们平台上的爬虫才能接入我们的ip。


好了,说了这么多,对于ip限制这种最常见的反爬措施来说,反反爬也可以说是相当的常规,就是买代理,具体买哪一家,就看你自己的情况喽。可以说有了高质量的代理ip之后,80%的爬虫写起来都非常简单了。


下一节我们会带大家一起看看反爬与反反爬的第二常规战斗-验证码

如何在神箭手上快速开发爬虫——第四课 如何爬取分页数据【蘑菇街商品评论】

注:

1、本课完整的爬虫代码可以在神箭手示例代码中查看:http://www.shenjianshou.cn/index.php?r=demo/docs&demo_id=500006

2、如何在神箭手上运行代码,请查看文档:http://docs.shenjianshou.cn/overview/guide/develop/crawler.html

3、更详细的爬虫开发教程,请查看文档:http://docs.shenjianshou.cn/develop/summary/summary.html



大家好,我是神箭手的游牧老师~

今天继续给大家带来 如何在神箭手上快速开发爬虫 系列教程的第四课:如何爬取分页数据。


通过前三课的学习,相信大家爬爬文章、爬爬商品啥的已经很简单了(还不会的筒子面壁去( ̄▽ ̄)”)。那么今天呢,主要跟大家分享下爬取分页数据的方法。

分页数据指的是要爬取的数据在多个分页上,无法通过请求一个页面一次抽取出来。举个常见的栗子,就是电商商品的评论了:


如果要将每个商品的所有评论爬取为一个商品数据的一个字段,因为在商品的详情页内,评论是分页显示的,所以需要通过分别访问每页评论抽取。

如何在内容页中抽取分页数据,神箭手提供了两种方法:

继续阅读“如何在神箭手上快速开发爬虫——第四课 如何爬取分页数据【蘑菇街商品评论】”

如何在神箭手上快速开发爬虫——第三课 如何爬取列表页数据【87870 VR资讯文章】

注:
1、本课完整的爬虫代码可以在神箭手示例代码中查看:http://www.shenjianshou.cn/index.php?r=demo/docs&demo_id=500004
2、如何在神箭手上运行代码,请查看文档:http://docs.shenjianshou.cn/overview/guide/develop/crawler.html

3、更详细的爬虫开发教程,请查看文档:http://docs.shenjianshou.cn/develop/summary/summary.html


大家好,好久不见了!游牧老师最近一直在忙着开发咱们神箭手的平台功能,近期我们又上线了很多强大的function,还上线了新版更萌萌哒的官网(大家喜欢么( ̄▽ ̄)”)


今天继续给大家讲解新的爬虫开发知识点:如何爬取列表页的数据


看过之前两课的童鞋们应该对神箭手上开发爬虫的基本过程很了解了,数据都是从内容页中使用xpath进行抽取的。那么在实际开发中,我们会遇到数据需要从列表页中抽取的情况,举个栗子:

打开网址:http://hy.87870.com/news/list-0-0-1.html

我们要爬取87870最新资讯里的文章,包括文章标签。我们可以看到文章标签(如上图红圈内的)是在文章列表页中的,那么就需要从列表页中抽取数据啦~


神箭手提供了”内容页附加数据”的方式将列表页数据添加到内容页内容中,从而统一从内容页抽取数据的方式,从而可以轻松爬取到列表页数据:http://docs.shenjianshou.cn/develop/configs/field.html#SourceType-UrlContext


基本过程呢,主要分为两步:

第一步,在onProcessHelperPage回掉函数中,从列表页读取需要的数据,附加给内容页URL

configs.onProcessHelperPage = function(page, content, site){
    var contentList = extractList(content, "//ul[contains(@class,'news-list')]/li");
    if(!contentList){
      return false;
    }
    for(var i=0;i<contentList.length;i++){
      // 1、获取列表页中每篇文章的tags数据
      var tags = extract(contentList[i], "//span[contains(@class,'keyword')]");
      var contentUrl = extract(contentList[i], "//a[contains(@class,'news-tit')]/@href");
      var options = {
        method: "GET",
        contextData: '<div id="sjs-tags">'+tags+'</div>' // 将tags数据添加到options的contextData中
      };
      // 2、将options附加到内容页中,再将内容页链接添加到待爬队列中
      site.addUrl(contentUrl, options);
    }
    // 判断是否有下一页列表页以及将下一页列表页链接添加到待爬队列中
    var nextPage = extract(content, "//a[contains(@class,'next')]/@href");
    if(nextPage){
      site.addUrl(nextPage);
    }
    
    return false; //不让爬虫自动发现新的待爬链接
};

第二步,在抽取fields中,添加从UrlContext方式抽取

{
            name: "article_tags",
            alias: "标签",
            // 3、从之前添加到内容页中的附加数据中抽取文章标签
            sourceType: SourceType.UrlContext, // 将抽取的数据来源设置为UrlContext
            selector: "//div[@id='sjs-tags']//a/text()",
            repeated : true
        }

是不是很简单啊?神箭手为开发者们提供了最简单和灵活的调用处理方式!


爬取结果截图:

完整的代码在这里:http://www.shenjianshou.cn/index.php?r=demo/docs&demo_id=500004


p.s. 更多爬取列表页数据的例子,请点我查看:http://docs.shenjianshou.cn/develop/advance/useUrlContext.html

再p.s. 如何把爬取的数据发布到自己的系统或者导出到本地文件,看这里:http://docs.shenjianshou.cn/use/publish/summary.html

ThinkSNS发布插件来了

神箭手目前已经支持的发布端包括:

1、网站类

WordPress采集发布插件,织梦(DEDECMS)采集发布插件,帝国采集发布插件,WeCenter采集发布模块,Discuz采集发布模块,PhpCms采集发布模块,PhpWind采集发布模块

2、数据库类

Mysql发布模块,Oracle发布模块,SqlServer发布模块,MongoDB发布模块,PostgreSQL发布模块。

3、其他

邮箱发布模块

现在,发布模块中又有新成员加入-ThinkSNS采集发布模块:

ThinkSNS系统,国内首家全应用端平台社交SNS系统,涵盖WEB网站端、H5手机微信端、Android端(原生)、iOS端(原生)等多个应用端。自主版本IM聊天系统,让及时聊天功能不在产生额外花费。朋友圈、微吧、话题、频道、找伙伴、商城、活动、资讯、找人、地图定位、风云榜附近的人等50多个功能板块,全方位覆盖SNS系统所需,让网站、应用建设更快捷,让系统开发更简单。

插件安装教程:http://docs.shenjianshou.cn/use/publish/install/thinksns.html

发布使用教程:http://docs.shenjianshou.cn/use/publish/website/thinksns.html