前言
最近在爬一个网站图片的时候,发生了一件很有意思的事。当我拿到图片链接后打开发现它和加载出来的图片不一样啊,细看后发现原图片是被切片成了多段后倒序拼接在一起的。(给兄弟萌整两张图片看看嗷)当时我整个人就不对劲了,但我是谁?爬虫小能手(自吹的),我能受着气?直接逮着就是一顿输出嗷。
原图片:  加载出来的图片: 
提示:以下是本篇文章正文内容,下面案例可供参考
一、思路分析
一个优秀的爬虫选手,第一步都应该是整理思路,理清前后的逻辑关系。 我们先来看一下整个网页的html代码,找到img标签那块看看  然后我们就看出来了,这啥也没有,这只放了一堆原图的链接屁用没有。 此时我们直接F12,打开开发者模式看看,我们直接定位到图片  哟哟哟,怎么多出来个canvas标签啊,此时的思路一下就明了了,说一下我当时大概的猜测吧:我觉得应该是在加载图片时动态生成了canvas标签,然后通过canvas标签的drawImage方法成功将图片加载出来。 现在我们就需要验证这个思路究竟是不是正确的,怎么来验证了?划重点:动态生成canvas标签,是不是就等同于存在document.createElement(“canvas”),那我们直接到top文件夹下搜索canvas字段试试  哦哟哟哟,不得了不得了,还真让我搜出点东西嗷。很明显最后两个js文件又猫腻,那我们的思路分析就到此结束,下一步就是分析js代码了。
二、细说JS
1.JS分析
我们先来看一看第一个js文件 第一处:  第二处:  第三处:  第一个文件里面有三处含有canvas,可是很遗憾没有找到我们想要的信息。那我们就只能看看第二个js文件了。  卧槽,差点没绷住,很明显这个js文件的代码全被混淆了,要想接着走下去我们就只有先把混淆的代码想办法弄出来。
2.搞定JS混淆
我们细看的话可以发现,上面的混淆代码可以分成4个函数,分别是 第一个: 第二个:  第三个:  第四个:  这样细分下来就可以看出一些东西了: 第一点:这里执行了两个方法,就是三和四 第二点:最后的方法里面返回的应该是一段字符串而且还是一段代码,因为它用了eval() 那我们现在应该怎么做了?很简单嘛,四个函数挨个扔到控制台里面,跑一下不就行了?    我们这里对最后两个函数处理了一下,定义了一个函数名,方便我们调用。接下来我们就调用一下试试看嗷: 首先是调用A函数也就是第三个,传入的参数就是它原方法下面括号里的参数  然后再调用B函数,和A函数方法一样  哟哟哟,这不就来了吗?这就到了第三步了。
3.最终分析
我们先复制下来,然后代码格式化后看看
function scramble_image(e, t, a, n, d) {
n || (n = !1), d || (d = !1), e.src.indexOf(".jpg") < 0 || parseInt(t) < parseInt(a) || "1" == d ? "none" === e.style.display && (e.style.display = "block") : 1 == n || 0 == e.complete ? document.getElementById(e.id)
.onload = function() {
onImageLoaded(e)
} : onImageLoaded(e)
}
function onImageLoaded(e) {
var t;
null == e.nextElementSibling ? (t = document.createElement("canvas"), e.after(t)) : t = document.getElementById(e.id)
.nextElementSibling;
var a = t.getContext("2d"),
n = e.width,
d = e.naturalWidth,
i = e.naturalHeight;
t.width = d, t.height = i, (n > e.parentNode.offsetWidth || 0 == n) && (n = e.parentNode.offsetWidth), t.style.width = n + "px", t.style.display = "block";
var r = document.getElementById(e.id)
.parentNode;
r = (r = r.id.split("."))[0];
for (var s = get_num(aid, r), l = parseInt(i % s), o = d, m = 0; m < s; m++) {
var c = Math.floor(i / s),
g = c * m,
h = i - c * (m + 1) - l;
0 == m ? c += l : g += l, a.drawImage(e, 0, h, o, c, 0, g, o, c)
}
$(e)
.addClass("hide")
}
function showBig(e, t, a) {
var n = document.getElementById("popup");
if (n.onclick = function() {
n.style.display = "none"
}, t || (t = !1), t) {
var d;
0 != n.getElementsByTagName("img")
.length && (y = n.getElementsByTagName("img")[0], n.removeChild(y)), 0 == n.getElementsByTagName("canvas")
.length ? (d = document.createElement("canvas"), n.append(d)) : d = n.getElementsByTagName("canvas")[0];
var i = d.getContext("2d"),
r = e.naturalWidth,
s = e.naturalHeight;
d.width = r, d.height = s, window.screen.width < 991 ? d.style.width = window.screen.width + "px" : r > window.screen.width && (d.style.width = r / 2 + "px"), d.style.padding = "10px";
var l = a.split(".");
l = l[0];
for (var o = get_num(aid, l), m = parseInt(s % o), c = 0; c < o; c++) {
var g = r,
h = Math.floor(s / o),
p = h * c,
u = s - h * (c + 1) - m;
0 == c ? h += m : p += m, i.drawImage(e, 0, u, g, h, 0, p, g, h)
}
} else {
var y;
0 == n.getElementsByTagName("img")
.length ? (y = document.createElement("img"), n.append(y)) : y = n.getElementsByTagName("img")[0], y.src = e
}
n.style.display = "block"
}
function get_num(e, t) {
var a = 10;
if (e >= 268850) {
var n = e + t;
switch (n = (n = (n = md5(n))
.substr(-1))
.charCodeAt(), n %= 10) {
case 0:
a = 2;
break;
case 1:
a = 4;
break;
case 2:
a = 6;
break;
case 3:
a = 8;
break;
case 4:
a = 10;
break;
case 5:
a = 12;
break;
case 6:
a = 14;
break;
case 7:
a = 16;
break;
case 8:
a = 18;
break;
case 9:
a = 20
}
}
return a
}
看见第一个函数的函数名我们就知道应该去找谁了吧,我们直接在top文件夹中搜索scramble_image看看有没有东西。  你是真没让兄弟失望啊!我们直接点进去看看它传的参数具体是啥 这里面有四处调用了该方法     哥们也不管那么多了,直接打断点就完事了  通过对得到的数据进行查找,最后在当前页面的html里面找到了几个参数  但是我们还是不知道imgObj[0]传入的啥,这边建议直接控制台输出好吧。  这不就有了吗? 最终我们拿到了所有的参数,直接对刚刚解出来的代码进行分析,这里我就说结果,代码就在上面那么可以自己分析试试。  最后分析得出就是通过onImageLoaded方法来实现的,传入的参数e就是imgObj[0]。 它在这个方法里面生成了canvas标签,然后获取了图片的原始高宽,然后通过get_num方法计算出当前图片切片次数,最后通过for循环和canvas的drawImage绘制出最终的图片。 至此大功告成!!!
总结
做爬虫一定要有清晰的思路和逻辑,其次需要的是耐心,要敢于去尝试、去挖掘,不然只有败兴而归。当然F12、断点以及控制台我愿称之为最强!!! 就这样吧,下次见!!!期待你的关注!!!
|