爬取菜鸟裹裹的数据
菜鸟裹裹{:target=”_blank”}是阿里旗下的一个物流数据的整合平台,数据准确、及时.前几天在关注菜鸟和顺丰的争端,因为在前一天我刚刚爬到菜鸟上面的快递数据,第二天看到二者出现了摩擦,在菜鸟上面已经查不到顺丰的信息了,还好有国家邮政局出面了解决,不得不为我们是社会主义点个赞。这次爬数据经历点波折,个人觉得阿里做的安全性还是很专业的。下面开始介绍如何找到突破口把数据拿到的。
声明:此文只做技术交流,请不要恶意攻击,当然我也相信阿里的技术,不可能轻意被攻破的。
本文Demo下载:
菜鸟裹裹Demo(可能已经不能用)
快递100数据Demo
监控Ajax请求
打开Chrome的控制台中的NetWork后,点击上面的查询按钮,查看请求记录,如下使用一个顺丰的物流号查询出对应的信息和请求:
对应的请求为:
参数原始为:v=1.0&api=mtop.cnwireless.CNLogisticDetailService.wapqueryLogisticPackageByMailNo&appKey=12574478&t=1496714756142&callback=mtopjsonp5&type=jsonp&sign=2ac43c025e94399c2ee2b7e0240f8303&data=xxxx
分析Url参数
从上面的请求和响应结果可以看出,请求的参数为:v, api, appKey, t, callback, type, sign, data,其中很明显sign是加密的,appKey在多次请求验证后发现是一个固定的值,callback是回调的参数,这个我们用不到,直接给一个任意值就可以,根据callback参数和type=jsonp,可以推测出,菜鸟使用的跨域回调的方法来进行数据传输的,这里也在js代码里面已经有验证了,采用的是动态追加\<script>标签的方法(可以自己去验证)。
右击查看在新的标签布页打开链接,查看数据详细:
现在的问题就是解决下面的的几个参数t和sing,这两个都可以调试对应的js来进行查看,页面js的路径为://g.alicdn.com/cn/guoguo-website/1.1.0/js/query.js
找到dom绑定的代码:
如果你看到的代码是压缩的,可以使用chrome的格式化工具格式化:
下面的工作就要考验你的耐心了。。。
调试和分析js
从上面的图片可以看到下面的代码:
1 | $("#J_SearchBtn").on("click", function() { |
可以看出首先调用的是e._handleSearch的函数,而o是当前输入的编号,继续跟进
在调用完loading方法后,调用了_requestPackage方法,详细看下这个方法:
1 |
|
_requestPackage内部有很多函数的定义,函数运行的核心在于 lib.mtop.request()方法,这个函数有三个参数,分别是json对象,单号o,和一个回调函数r。后面的调试过程省略。。。。(自己找吧)
在最终的mtop.js中有一个 l 的函数,可以找到我们想要的信息如下:
从图片上面可以看出参数t只是一个时间戳,同样在这个函数里面看到了sign的赋值:
上面是一个调用了一个 k 函数,k函数的定义如下:
1 | function k(a, b, c) { |
k中又调用了i函数:
1 | function i(b) { |
1 |
|
在i的内部是由f(P)返回的值传递给b,而b函数是上面调用i的传入的匿名函数,在匿名函数调用传入a调用k参数中的匿名回调函数function(a){…},所以可以确定f是我们想要的sign值。f值的来自于d函数的返回值
1 |
|
d中的几个参数a:是k传过来的a.data,是经过包装的单号{mailNo:xxx},b是t参数,就是时间戳。h()是上面说的appKey,可以调试看出来是一个固定值 12574478。 而对于e,是函数i中的f(P),经函数c中的三元表达式a = a ? a.split(“_”)[0] : “”处理后的结果,而P值我们可以找到定义的地方,发现它是一个固定值:
总结上面的分析,目前所有的参数都已经大体清楚,剩下的就是获得e最终的值和函数d的作用。
cookie的分析
对于e值的获得是来自于cookie,再看函数f的逻辑,其中参数a是一个固定值P:
1 |
|
这个是一个正则匹配出对应的cookie中的value,这里可以不用细看,可以直接用代码来模拟。
加密
刚开始看了函数d的返回值,觉得是一个加密函数,后面看脚本内容证实了猜想,但问题是这个是什么方式的加密呢?可以先看下函数d的核心代码:
1 | var o, p, q, r, s, t, u, v, w, x = [], y = 7, z = 12, A = 17, B = 22, C = 5, D = 9, E = 14, F = 20, G = 4, H = 11, I = 16, J = 23, K = 6, L = 10, M = 15, N = 21; |
通过代码我个人是很难看出用的是什么加密方式,所以我在控制台,测试了加密的结果
通过这个结果可以先排除des加密了(因为des都是以==结尾),经过几种加密方式对比发现是md5的32bit的加密。
好了,到这里,已经是万事具备.下面开始去写代码抓取,代码很简单,不多解释:
1 | var mainUrl = |
方法中会用到的方法
1 |
|
返回数据: