趣发现是一个很好玩的网页,因为它选择了一直用手机QQ浏览器。最近想做一个爬虫,就想那它练练。
第一步:获取动态图片的链接
趣发现首页:http://fun.html5.qq.com/?ch=01201&g=3
用chrome打开首页链接以后,按F12,再次刷新页面,分析NetWork中的链接。可以依次筛选不同的类型,进行过滤。
在XHR标签中,注意到有四条链接很有规律,如图所示:
点击链接,查看其信息,得到对应的Request URL:
进一步的,在浏览器中,打开此链接:
(我的浏览器中,安装的有解析json的插件———JSON—handle,所以页面显示的是格式化后的效果)
从这个页面中,可以找到显示出来的图片链接等,可以判定是我们所需的页面素材。
那么XHR标签中,同时四个页面是怎么回事???看不懂,咱就多试试。
一直拉下网页的拉条,使页面加载更多的动态图,则XHR标签中,连接越来越多,也会发现一个很规律的事情:
猜测关键信息:
从这些链接中,可以提取一些有用的信息:
ist_2? //固定不变
key = 1 //只有第一行
2 //只有第二行
4 //除了第一、第二、最后一行 后的全部
5 //只有最后一行
limit= 8 //四个数值都有分布,且没有特别少的,从而推测四种取值差不多
9
10
11
rt = 1 //只有第一行,第二行,第三行,最后一行
//或者 key!=4,则rt=1 ,且 第一个key==4,则rt=1
2 //tr!=1 ,则rt=2
_t=??? //完全没规律,只知道它们前五位相同,接着的一位,相差在两个数之间。
这里,还可以获取到的另一个有用信息是,这个链接中的特殊字符串:limit、rt、_t 等。
一个完整的请求动态图片资源的链接是:http://fun.html5.qq.com/api/list_2?key=4&limit=9&rt=2&_t=1474946575006&ch=01201
我们照着这个资源链接构造需要的模板:http://fun.html5.qq.com/api/list_2?key=【】&limit=【】&rt=【】&_t=【】&ch=01201 // 【】 代表需要填参数
第二步:查找 图片的链接 的出处
由第一步,我们找到了发往服务器获取图片的链接,现在需要分析这些链接是从哪里构建的或者是怎么构建的,以便我们自己也可以批量构建这样的链接。
接着查看Network下,其他标签有没有比较有价值的信息:就比如JS标签下,仅仅有六个文件,那么就可以那他们来分析。
打开这几个文件,里面好多、好长,干脆偷点懒,直接把刚才得到的链接中的特殊字符串:limit、rt、_t 往里代,直接搜索这些文件中有没有这些字符串。
时间+耐心+不放弃==一点蛛丝马迹!!!
关键JS文件 1、
在 http : //res.imtt.qq.com/video_fun/dist/index-d573bf9b4f.js 文件中:
fetchCore : function (e)函数里面有一段关键的代码,出现了关键字:limit,而附近的关键字“/api/list_2” “key” “rt”等,也印证了这段代码是请求资源文件的关键:
fetchCore : function (e) {
try {
var t = this.props.groupInfo,
n = t.fetchType,
a = t.fetchKey,
r = t.pageSize;
$fn.triggerReactEvent(Enum.ReactEventName.VIDEO_SECTION_PLAY, {
currentTargetScope : null
}),
$fn.triggerReactEvent(Enum.ReactEventName.GIF_SECTION_REQUIRE_STOP, {
exceptTarget : null
}),
this.state.groupItemData && (e && e.refresh ? $fn.reportOptNgx("LIST_REFRESH") : $fn.reportOptNgx("LIST_SCROLL_MORE"));
var c = parseInt(Math.random() * (r - 8) + 8, 10);
return n === Enum.GroupPageFetchType.RECOM ? $fn.ajax("/api/recom", {
limit : c,
rt : e && e.refresh === !0 ? Enum.GroupPageRefreshType.REFRESH : Enum.GroupPageRefreshType.SCROLLMORE
}) : $fn.ajax("/api/list_2", {
key : a,
limit : c,
rt : e && e.refresh === !0 ? Enum.GroupPageRefreshType.REFRESH : Enum.GroupPageRefreshType.SCROLLMORE
})
} catch (i) {
$fn.jsRuntimeError(i, "bc0e4d47a48d600e1f14c366174ebfe2")
}
},
代码前后文断掉的太多,就是查找函数之间的各个调用关系,也可能会出现漏掉的现象。我们需求的不是那么精细,就可以根据第一步中得到的一些结果,跟这里的代码经行匹配:
进一步猜测关键信息:
1、
从函数中:var c = parseInt(Math.random() * (r - 8) + 8, 10);
limit : c,
两行,加上第一步的推测(limit=8、9、10、11 而且都有不少的分步),
可以得知::limit就是一个随机数,取值在【8-11】之间。
2、
函数中: key : a,
rt : e && e.refresh === !0 ? Enum.GroupPageRefreshType.REFRESH : Enum.GroupPageRefreshType.SCROLLMORE
看不懂什么意思,就直接用一步推测的值:
key=4 //在多次下拉 趣发现首页面 的下拉条,查看XHR标签的时候,新出现的链接中,这两个参数一直没变
rt=2
3、 还有一个很关键的参数: “_t= " 在这里没出现,而且明知道 $fn.ajax() 是一个函数调用,但是找不到它在哪里。
那么就找找这几个js文件中,有没有 "_t" 这个关键字的出现。
当然,试一试还是有的:
关键JS文件 2、
在 http : //res.imtt.qq.com/video_fun/res/js/plugin-ffd048441a.js 文件中,出现了“_t”这个关键字,而且它后面还加一个很重要的函数:a(r.report + u[2] + "&_t=" + +new Date
u = function () {
if (r.report) {
for (; e.length; ) {
for (var t = !1, n = e.shift(), u = s(n, c.length), h = 0, f = r.ignore; f > h; h++) {
var p = r.ignore[h];
if (o(p, "RegExp") && p.test(u[1]) || o(p, "Function") && p(n, u[1])) {
t = !0;
break
}
}
t || (r.combo ? c.push(u[0]) : a(r.report + u[2] + "&_t=" + +new Date))
}
if (r.combo) {
if (l)
return;
l = !0,
i = setTimeout(function () {
var t = c.length;
a(r.report + c.join("&") + "&count=" + t + "&_t=" + +new Date),
c = [],
l = !1
}, r.delay)
}
}
}
在JS代码中,+new Date() 是以毫秒数的格式返回当前时间,(不知道这一点,多次与它擦肩而过,看过了也就过了
)
在第一步中,得知 _t 的值一直在变化,且前几位相同,和这个 +new Date()的效果是一样的,所以可以猜测就是这一段代码了。
第三步:填充 模板链接
由第二步中两个关键JS文件中分析的参数,加上第一步构建的模板链接:http://fun.html5.qq.com/api/list_2?key=【】&limit=【】&rt=【】&_t=【】&ch=01201 // 【】 代表需要填参数
我们就可以往其中赋值了:http://fun.html5.qq.com/api/list_2?key=【4】&limit=【8或9或10或11】&rt=【2】&_t=【以毫秒格式显示的当前时间】&ch=01201 // 【】 中的参数为可能填的值
最后,随便测一个链接:http://fun.html5.qq.com/api/list_2?key=4&limit=8&rt=1&_t=1474952332148&ch=01201 就出现json格式的响应资源文件。解析这个文件就可以得到想要的动态图片链接。
(注意:单独打开测试链接是没有用的,其中原因可能是,页面使用了cookie机制。 测试的方法是,首先打开趣发现的首页,再在同一个开着的浏览器中,输入测试链接地址)
总结: 查找整个代码,耗费了好长时间。最开始的时候,也是想着去分析那个连接在哪里构建的,走了一些弯路,才慢慢的采取这样的分解关键词,并在源码中搜索办法。整个过程,大多是猜测进行下去的,因为不是要求很严密的逻辑,所以就猜着猜着,离想要的越来越近。