淘宝客淘宝联盟商品爬虫使用教程:如何设置商品采集入口页url

淘宝联盟商品采集爬虫获取地址http://www.shenjian.io/index.php?r=market/product&product_id=500180

第一步:打开淘宝联盟官网,然后搜索栏里面输入要采集的宝贝关键字,输入后点击搜索按钮:




第二步:搜索结果出来后,可以直接把浏览器里的当前url作为入口页url设置到爬虫设置中;

也可以选择宝贝的细分类,或者在高级设置里面设置商品要求、店铺要求或者图片要求。同时也可以选择排序方式:




第三步:复制当前浏览器里的url,设置到爬虫设置中:






爬虫启动后,从设置的url开始自动采集网页上的商品,自动发现下一页。

如果希望采集更多的商品,可以尽量少设置商品筛选条件。

需要注意的是:淘宝联盟网站最多只有100页商品搜索结果,所以爬虫只能爬取最多100页。


神箭手新增微信公众号发布接口

神箭手微信公众号发布接口正式上线,自媒体作者可以方便的接入公众号发布接口,一键将文章发布到公众号平台。

神箭手发布接口一直是神箭手最具特色也是最强大的功能之一,支持发布到几乎所有主流CMS,数据库和邮箱发布。今天发布接口家族又迎来一个重量级的选手-微信公众号发布接口:


通过微信公众号发布接口,可以方便的将网站的内容同步到微信公众号的素材中,帮助大家迅速累计公众号文章的素材,获取更好的内容,吸引更多的粉丝,更简单快捷的做公众号内容运营。

携程反爬中的Eleven参数-反爬与反反爬的奇技淫巧

大家好,先回顾下之前的文章:

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

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

爬虫中Cookie的伪造(非登录)-反爬与反反爬的奇技淫巧

爬虫与诡异的字体-反爬与反反爬的奇技淫巧

爬虫与汽车之家的Css:Content-反爬与反反爬的奇技淫巧

爬虫与CloudFlare邮箱加密(cfemail)-反爬与反反爬的奇技淫巧

今天我们要聊点什么呢,之前说要聊去哪儿的,不过暂且咱们再放一放,先聊一聊去哪儿的干爹携程吧,上次我记得看了携程工程师霸气回应说懂爬虫的来去哪儿,懂反爬的来携程。我觉得特别棒,这种开放的心态和自信,正是一个开放的互联网环境所需要的。

所以今天这节课虽然咱们以携程为例,但是我们还是以学习的目的为主,因此我不会把完整的代码放出来,大家掌握思路,拿到渔网比直接copy代码有用的多。

上篇文章用邮箱加密给大家演示了爬虫中简单的JS对抗,今天这节课咱们就用携程的Eleven参数来演示下复杂的JS对抗。

对了,这个题图,主要是因为携程给他们这个反爬的JS起了一个名字叫oceanball-海洋球,不明觉厉啊。

好了,言归正传。做过携程酒店爬虫的朋友,估计都研究过这个eleven参数,这个参数到底是哪里的呢,我们先看下页面请求:

就是这样一个页面,打开一个酒店页面会发现实际的酒店房型列表是一个ajax请求,如下:

http://hotels.ctrip.com/Domestic/tool/AjaxHote1RoomListForDetai1.aspx?psid=&MasterHotelID=441351&hotel=441351&EDM=F&roomId=&IncludeRoom=&city=2&showspothotel=T&supplier=&IsDecoupleSpotHotelAndGroup=F&contrast=0&brand=0&startDate=2017-08-28&depDate=2017-08-29&IsFlash=F&RequestTravelMoney=F&hsids=&IsJustConfirm=&contyped=0&priceInfo=-1&equip=&filter=&productcode=&couponList=&abForHuaZhu=&defaultLoad=T&TmFromList=F&eleven=c4350e460862b69d9d76724e1325a0a54ef23c2e0648636c855a329418018a85&callback=CASuBCgrghIfIUqemNE&_=1503884369495

前面咱说过,出于对反爬工程师工作的尊重,我们今天的文章不去完整介绍整个携程爬虫的做法,其实除了这eleven参数,携程还是在代码了下了不少毒的。

一般来说,一个ajax请求,如果没有做cookie限制的话,最难的问题就是能把所有的参数拼接完整,这个请求中最难的就是这个eleven参数的获取,那咱们遇到这种问题,应该具体如何处理,同时对于反爬工作来说,又有什么可以借鉴的地方呢。

一、反反爬中遇到复杂JS请求的处理流程

凡是题目总有一个解题思路,反反爬也不例外,解题思路很重要。不然就像没头苍蝇一样到处乱撞,今天这篇文章最重要的就是说说这个解题思路。

1.查看发起这个请求的JS来源

首先,Ajax请求大多都是由JS发起的(今天我们不讨论flash或者其他情况,不常见),我们使用Chrome工具,将鼠标移动到这个请求的Initiator这一栏上,就可以看到完整的调用栈,非常清晰。

2.确认核心JS文件

可以看到调用栈中有非常多的JS,那具体我们要分析哪个呢?一般来说我们可以首先排除掉VM开头的和常见库如jQuery这类,当然也不绝对,有些JS也会把自己注册到VM中去,这个另说,携程这里的情况挺明显,一眼就看到了那个不寻常的oceanball,看着就不是一般人,就他了。

3.分析JS文件

点击这个oceanball咱们就可以看到完整了源码了,下面也是最难的一步,分析JS文件。上一篇文章已经简单说了一些,首先,可读性非常重要,咱们复制完整的JS,贴进Snippet中,咱们大概看下,文件太大,没办法贴到文章中来:

一看就是在代码里面下毒,携程反爬工程师不简单啊。

不过呢,咱们看到这种很多数字的其实不要害怕,特别是在看到eval函数和String.fromCharCode,因为这就是把代码加密了一下,这种加密就跟没加密一样,咱们把eval函数直接换成console.log函数,运行一下这个Snippet。在控制台就可以看到原始代码。解密后如下:

看来这个是毒中毒啊,解密后的代码虽然比刚刚的可读性大为增加,但是依然可读性不强,不过根据经验,这样的文件已经没有一个特别简单的方案可以一举解密,只能逐行分析加部分替换了。当然直接Debug也是一个最省力的方案。

通过Debug调试,我们可以看到很多变量的中间值,这中间最重要的莫过于这最后一行,我们可以看到Eleven参数这个时候已经算出来了,而向CASttwHNetheyMWqSJ这个函数中传入一串实现,而这个实现正式返回eleven的值(这段代码是要把人绕死的节奏吗),所以我们只需要构造一个假的CASttwHNetheyMWqSJ来接收这段实现即可,而CASttwHNetheyMWqSJ这个函数名也是通过url传入的,好了,基本上大体的分析搞定了,下面就是构造这个代码的运行环境了。

4.构造运行环境

重要的话要重复很多遍:写爬虫最好的语言就是JS,因为JS对抗是爬虫中最难的部分,而一个合适的JS环境则可以事半功倍。全球最好的JS爬虫框架-在线网络爬虫/大数据分析/机器学习开发平台-神箭手云

有了JS运行环境,我们其实只需要构造一个函数接受Eleven参数,请求oceanball,并直接运行他就可以了。我们看下我们构造的CASttwHNetheyMWqSJ函数:

var callbackFunc = randomCallback(15); var getEleven; eval("var "+callbackFunc+" = function(a){getEleven = a}"); 

这里对于初学者可能还是有点绕,简单说明下,首先我们随机了一个函数名,然后我们定义了一个空函数来接受oceanball中的返回eleven参数的函数实现,然后我把这个函数名定义为接受new Function的实现,这样我们后面就可以用getEleven来直接获取eleven参数了。

这里还得说下普通JS环境的缺陷,由于在普通JS环境中(非浏览器中)缺少一些重要的内置变量,如window,document等等,导致很多JS是运行不了的,这里我们补上这些变量:

var Image = function(){}; var window = {}; window.document = {}; var document = window.document; window.navigator = {"appCodeName":"Mozilla", "appName":"Netscape", "language":"zh-CN", "platform":"Win"}; window.navigator.userAgent = site.getUserAgent(); var navigator = window.navigator; window.location = {}; window.location.href = "http://hotels.ctrip.com/hotel/"+hotel_id+".html"; var location = window.location; 

JS如果比较熟悉的话,应该能看出来这里有一个变量不常规,就是第一行的Image变量。这又是携程下的毒啊,我们回到刚刚oceanball的代码看下:

代码中有一句尝试new一个Image对象,如果失败了,则把某一个参数+1,而这个参数正是eleven参数中的某一位,也就是说eleven参数中有一位记录了JS运行环境是否支持new Image,我们这种伪造的浏览器环境当然不支持,所以我们得补上。

5.大功告成

好了,解了这么多毒,咱们终于可以获取到了eleven参数,当然这只是漫漫长征第一步,后面请求到的结果中,还有更深更辣的毒等着大家:

二、反爬中可以借鉴的地方

首先非常感谢携程反爬工程师给了一个教科书般的JS反爬案例,从这个例子我们也可以看出反爬中使用JS代码加密混淆的威力,基本上如果不是JS熟手,或者不熟悉解题思路的话,就是束手无策。JS混淆的方案有很多,大家可以到网上搜一搜,这里还是很推荐携程这种ajax配合回调+js二次混淆的方案,可以说极大提升了反反爬难度的同时也做到了基本不影响性能。但是这个方案依然对于直接渲染JS页面效果一般,还是建议配合之前文章提到的css:content的方案,这样处理之后那对于反反爬工程师的酸爽绝对够得上100桶统一老坛。

爬虫与CloudFlare邮箱加密(cfemail)-反爬与反反爬的奇技淫巧

大家好,今天我们终于要进入我们激动人心的反爬界最重量级选手–Javascript加密混淆,我们先来回顾之前叨逼叨了5篇文章的反爬经验:

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

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

爬虫中Cookie的伪造(非登录)-反爬与反反爬的奇技淫巧

爬虫与诡异的字体-反爬与反反爬的奇技淫巧

爬虫与汽车之家的Css:Content-反爬与反反爬的奇技淫巧

由于Javascript这块的内容很多,难度也不一样。所以这一篇文章希望给大家讲一些入门级别的。本来找来找去感觉都是高段位玩家,然而今天在做邮箱地址爬虫的过程中一段代码突然跳到了我的面前-邮箱地址加密JS。恰好难度适中,就今天拿出来跟大家一起聊一聊:

首先当然是上广告:

不可言说与迷之强大的邮箱采集爬虫:

网页邮箱Email采集爬虫-营销必备工具-神箭手云

下面我们就进入正题,先来看看这个文章标题上的内容跟我们这篇文章到底有啥关系:

CloudFlare是一家美国的跨国科技企业,总部位于旧金山,在英国伦敦亦设有办事处。CloudFlare以向客户提供网站安全管理、性能优化及相关的技术支持为主要业务。通过基于反向代理的内容传递网络(ContentDeliveryNetwork,CDN)及分布式域名解析服务(DistributedDomainNameServer),CloudFlare可以帮助受保护站点抵御包括拒绝服务攻击(DenialofService)在内的大多数网络攻击,确保该网站长期在线,同时提升网站的性能、访问速度以改善访客体验。

看完了好像还是没关系,别急,我们今天要讲的是CloudFlare中的一个功能,叫做Email Obfuscation,也就是邮箱混淆。

当我们使用了 CloudFlare 的服务,如果开启了 Email Obfuscation ,页面里真正的 Email 地址会被隐藏,具体隐藏的代码如下:

<a class="__cf_email__" href="/cdn-cgi/l/email-protection" data-cfemail="a89b9b9c919d9b909a989ae8d9d986cbc7c5">[email&#160;protected]</a><script data-cfhash='f9e31' type="text/javascript">/* <![CDATA[ */!function(t,e,r,n,c,a,p){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-cfhash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-cfemail')){for(e='',r='0x'+a.substr(0,2)|0,n=2;a.length-n;n+=2)e+='%'+('0'+('0x'+a.substr(n,2)^r).toString(16)).slice(-2);p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */</script> 

做过爬虫的朋友应该都对这段代码不陌生,非常常见的一个邮箱混淆服务。

一.为什么要使用邮箱混淆服务。

事实上很多站长可能并不知道自己使用了这样的服务,因为CloudFlare主要还是以CDN为主,这个服务是附加的,而且CloudFlare也做的很贴心,几乎不用什么设置,就可以自动混淆。(实际上是识别了输出的页面里是否有邮箱,有邮箱就替换成[email protected]并在下面添加一段JS代码)。

无论邮箱和电话号码,即使主动留在互联网上,也不希望被人批量获取,所以邮箱混淆一直是件很重要的事情。包括用at代替@,用#代替@,还有生成图片的。而CloudFlare提供了一种完全不需要修改代码的方案,确实给了大家很大的方便。

二.CloudFlare邮箱混淆服务的优劣

那么我们使用这种方案有什么优点和缺点呢?

我们先说说优点:首先不用改代码,很方便;其次全局替换,不会有遗漏;最后JS混淆,比at和#更加彻底也对显示影响最小,毕竟at和#用的人多了,就和@一样了,有时候还会让真正想联系的客户摸不着头脑。

我们再说说缺点:我在验证码那篇文章中就提到过的成本回报比概念,当很多人用一个方案的时候,由于回报无限增大导致无论这个方案有多么好,他被破解的概率都会大大增加。当然CloudFlare混淆远远不止这个问题这么简单。他的这个混淆有时候恰恰使得这个页面中的邮箱标志更加明显,有点类似本来你把金子放在地上,很危险。现在把金子埋在地下,然后为了自己能找到,又画了一个此处有金子的标记。事实上在真正识别邮箱的爬虫中,CloudFlare反而降低获取Email的难度。所以先提前说反爬的结论,严重不推荐大家使用这个方案!

三.写爬虫时遇到CloudFlare邮箱混淆,如何解密?

说完了反爬,再说反反爬。这个我就不得不提工具的重要性了。有时候你遇到一个好工具,那真的一身轻松。这里需要再次强调,写爬虫最好的语言是JS,因为JS对抗是爬虫中最难的部分,框架本身就是JS的环境将使得事半功倍:

世界上最好的JS爬虫开发框架- 在线网络爬虫/大数据分析/机器学习开发平台-神箭手云

好了,今天的盒饭有着落了。当然我们这篇文章还是得给爬虫工程师来点干货的。

我们今天就通过这个简单的例子来看看写爬虫时遇到复杂的JS到底怎么分析。

1.格式化代码

JS分析最重要的是格式,因为大部分JS代码都是混淆且压缩的。基本是不具备任何可读性,先格式化成可读的形式最重要。格式化的工具很多,这里我最推荐Chrome浏览其中的Snippet。因为格式化完了之后还可以调试,简直是神器。

我们把前面例子中HTML代码部分删除掉,留下JS部分,贴进Snippet,点击左下角的{}按钮格式化:

2.分析代码

是不是看着舒服太多了,已经到了人眼能看的级别了。我们贴出来看看:

!function(t, e, r, n, c, a, p) { try { t = document.currentScript || function() { for (t = document.getElementsByTagName('script'), e = t.length; e--; ) if (t[e].getAttribute('data-cfhash')) return t[e] }(); if (t && (c = t.previousSibling)) { p = t.parentNode; if (a = c.getAttribute('data-cfemail')) { for (e = '', r = '0x' + a.substr(0, 2) | 0, n = 2; a.length - n; n += 2) e += '%' + ('0' + ('0x' + a.substr(n, 2) ^ r).toString(16)).slice(-2); p.replaceChild(document.createTextNode(decodeURIComponent(e)), c) } p.removeChild(t) } } catch (u) {} }() 

我们先大概看下整个代码,首先外层就是一个函数的定义及直接调用。大部分的JS库都会采用这种方法,既可以保证代码模块之间变量不相互污染,又可以通过传入参数实现内外部变量的传输。

再读代码第一段:获取变量t,这个过程我们结合前面的HTML代码可以看出,这个是在获取Email被加密后的Dom元素,为了后面获取data-cfemail做准备。

最后看第二段:显然就是从Dom元素中获取data-cfemail并解密出真实的Email并替换到页面显示中去。

3.整合进爬虫

一般来说,对于复杂的JS,我们还会有断点调试和其他分析的过程,这里的JS很简单,所以咱直接开始写代码。我们怎么在像神箭手这样的JS爬虫框架中处理呢,同样也非常简单:

var cfemails = extractList(content, "//*[@data-cfemail]/@data-cfemail"); for(var c in cfemails){ var a = cfemails[c]; for (e = '', r = '0x' + a.substr(0, 2) | 0, n = 2; a.length - n; n += 2) e += '%' + ('0' + ('0x' + a.substr(n, 2) ^ r).toString(16)).slice(-2); var emailDecoded = decodeURIComponent(e); console.log(emailDecoded); } 

可以看到,我们先通过xpath直接获取所有的data-cfemail的值,然后直接把CloudFlare这段解密JS复制过来就行了。运行后就可以直接获取该页面所有被CloudFlare混淆过的邮箱,简直比直接用正则提取邮箱还要简单还要准确。

————————————————最后再说两句——————————————————–

通过这篇文章中这个非常常见却又相对入门的例子,我们一起看了下Javascript在反爬与反反爬中扮演的角色,同时也看到了一个JS爬虫框架的重要性,如果是其他爬虫框架,要么需要自己整合JS引擎,要么就得读懂整段解密代码再翻译成那种语言,这个难度在我们后面会提到的一些JS加密中,将不敢想象。同时我们也可以看到类似CloudFlare这类通用邮箱混淆的脆弱性。

爬虫与汽车之家的Css:Content-反爬与反反爬的奇技淫巧

大家好,我又要食言了,总盯着去哪儿挺没意思的,今天咱们先聊另外一个老朋友-汽车之家。

先上广告,土豪朋友不想写代码的,可以直接使用我们的汽车之家论坛爬虫:

汽车之家论坛采集爬虫-神箭手云

给新朋友的之前的文章列表:

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

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

爬虫中Cookie的伪造(非登录)-反爬与反反爬的奇技淫巧

爬虫与诡异的字体-反爬与反反爬的奇技淫巧

话说感觉这个系列的我起名字越来越不走心了。越写越像哈利波特的起名套路了-爬虫与混血王子。(嗯,一点都不违和)我这个爱扯犊子的性格真是很难收敛啊。

话说Css自从越来越强大之后,被很多反爬工程师看上了。上篇文章介绍的字体就需要用到Css中的font-face和font-family。这节我们通过汽车之家来看看Css在反爬中另外一个妙用-content。

本来网页上显示的字无非两种,一种就是文本,一种就是显示在图片上的。所以之前有一种常规的反爬,就是把字当做图片替换来显示,目前百度还经常喜欢这么处理,比如百度知道,百度指数(参考天坑),当然不少的电话号码和邮箱这类重要信息,依然也再沿用这个方案。

然后随着css的content兼容性越来越好之后,就又有了一个性能更好的反爬,就是用css的content来代替原来文本中的文字,辅以合适的随机生成的方法,确实也不错。算是一个性能和反爬折中的方案吧,比如我们今天要提到的 汽车之家论坛 就是采用这样一个反爬方案。

一.为什么Css:Content能反爬。

事实上任何能让原来html中文本隐藏混淆加密又不影响正常用户显示的方式都可以来做反爬,比如我们上一篇文章提到的字体方式混淆,比如我们后面要提到的JS加密。而这篇文章主要是采用Css的content属性来隐藏。

我们简单的看下content属性使用,大家可以尝试复制这段写入一个网页的Css中

div:before {
   content: "神箭手";
}

我们会发现每一个div的开头都加入的神箭手的文字,而且这些文字还是无法复制的。再加上并不像生成图片那样会严重拖慢服务器性能,所以算是一个挺折中的方案。

二.如何好好利用Css:Content反爬

我们一起来看看汽车之家的反爬学习一下:

我们打开一个汽车之家论坛网页,然后直接Ctrl+A全选,就可以很明显的看到用Css的Content插入进的字符,我们掀开被子仔细研究下:

可以看到,汽车之家是将一些常用的字,包括<了><,><的><九>等等变换成Css,这样做优点是可以提前写好css,缺点是由于是固定的库,很容易先把映射的关系解析好,然后直接全文替换。因此比较推荐的,当然还是每次的动态生成,不过这依然产生一个工程性的优化问题,这里还是比较推荐用池的方案,或者用客户的IP做一个hash映射也不错。

不过汽车之家做的比较好的在于很好的隐藏了这段固定映射的Css,同时Css中的class也每次会替换一些名称部分,同时又不是每次都把所有的映射库输出出来,而是节选文章中有的文字,因此既缩小了输出大小,又隐藏了整体库,看得出工程师也是打得一手好牌啊。

三.如何应对Css:Content这种类型的反爬

我们就以汽车之家为例吧:

1.获取映射的Css

其实汽车之家这个例子来说,主要的问题并不是如何解决这种反爬,因为这种模式的反爬如果知道映射,搞起来太简单,直接正则替换就行了。这里最难的是怎么找到这个映射,汽车之家可以说隐藏的是教科书级的完美,解析方案我就不展开讲了,因为这个是Javascript对抗里的内容(后面我可能会拿出几篇文章单独讲JS对抗),重点就是解析跟在正文后面的这一段JS。

好的工具等于成功的一半,想要很好的解析JS,一定要有一个好的JS解释引擎。这样可以省掉大量的破解的工作而直接运行别人的JS,在代码中整合脚本引擎相当麻烦,最完美的莫过于找一个好的JS的爬虫框架。

具体的Javascript对抗我在后面再讲,这里简单说下,直接运行这段代码,我们可以看到在Nl_(可变的)这个变量中存储了完整的Css映射,因此我们想办法在运行中保存该变量,带入下一步即可。

2.根据映射进行内容替换

我们既然拥有了Css映射,那还有啥难的,直接读取CssRules,循环用正则替换把

<span class='hs_kw4_mainYM'></span>

这类标签直接替换成content中的文字:

好了,大功告成。

贴一下部分神箭手中运行的解析代码:

var code = extract(page.raw, "//div[@class='conttxt']/div/script"); if(code){ eval(code); var cssMapping = {}; if(rules.length > 0){ for(var ri in rules){ var rule = rules[ri]; var matches1 = /content:\s*"([^"]+)"/.exec(rule) var matches2 = /\.([^:]+)::before/.exec(rule) if(matches1 && matches2){ cssMapping[matches2[1]] = matches1[1]; } } page.raw = page.raw.replace(/<span\s+class='(hs_kw\d+_[^']+)'><\/span>/g, function(match,p1,p2){ return cssMapping[p1]; }); } } page.raw = exclude(page.raw, "//div[@class='conttxt']/div/script"); 

————————————————最后说两句————————————————————

大家会发现,很多非常奇特的反爬措施,大多依赖Javascript加密的功力。当然有些Javascript加密可以直接通过JS渲染,如[Email Protection],但是也有很多单纯通过渲染JS无法解决,如今天这篇文章中提到,因此也让Css的这种反爬措施有别于普通的JS加密形式,给反反爬工程师设置了更高的障碍,是我个人比较推荐的一种反爬手段。反过来对于反反爬来说:在有了好的工具前提下,熟练掌握JS则是一个必备内功之一。