最近在鼓捣python,于是想写一个小爬虫来玩玩。百度一圈,目标定为煎蛋妹子图
首先,浏览器打开煎蛋妹子图网页http://jandan.net/ooxx(为啥不是xxoo),
F12打开开发者工具箱,点击开发者工具箱左上角的箭头,然后点击图片,就可以定位到图片代码位置。
可以看到如下格式代码:

1
2
3
4
5
6
7
8
<div class="text">
<span class="righttext"><a href="//jandan.net/ooxx/page-411#comment-3654801">3654801</a></span>
<p>
我不知道下面有什么好看的,我只知道上面挺好看的<br>
<a href="//wx1.sinaimg.cn/large/82f0dc00gy1fmtwpyp93uj20go0go7a0.jpg" target="_blank" class="view_img_link">[查看原图]</a><br>
<img src="http://wx1.sinaimg.cn/mw600/82f0dc00gy1fmtwpyp93uj20go0go7a0.jpg" style="max-width: 480px; max-height: 750px;">
</p>
</div>

看起来很简单是不是?现在来试试截取图片地址
方法有很多种,我用的是较笨的方法,正则提取。
python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
# -*- coding:utf-8 -*-
import re
import requests

# header可以模拟浏览器访问
rq = requests.get('http://jandan.net/ooxx',headers = {...})
if rq.status_code == 200:
rq_txt = rq.text.strip().replace('\n','').replace('\t','')
# <a href=" 开头,“查看原图”结尾
img_re = re.compile(r'<a href="(.*?)".*?查看原图')
imgs = re.findall(img_re, rq_txt)
print(imgs)

看了一下没什么问题,结果测试的时候,什么都没出来。鼓捣半天,总以为是正则提取出现问题了。
后来才发现是拿到的页面里根本没有这个标签
拿到的页面如下:

1
2
3
4
5
6
7
<div class="text">
<span class="righttext"><a href="//jandan.net/ooxx/page-411#comment-3654801">3654801</a></span>
<p>
我不知道下面有什么好看的,我只知道上面挺好看的<br>
<img src="//img.jandan.net/img/blank.gif" onload="jandan_load_img(this)"><span class="img-hash">3f1eculWZ1KHRsZjhu7FZGRebA+bkD6FyKLrIw3OnkFgl1SaxQXtJU50f0ofqFz4jGR7IJj7V8RVFegNeTMMgLn2e9oB4qJoeSjD6K0qkukc9EKwXmfufw</span>
</p>
</div>

看来是加密了,抱着准备放弃的心去百度了一圈,八九不离十的都是通过模块执行js来解密,这确实是一个好方法,但不知怎么的,我就是不想用。
没办法,动手试试看能不能解密吧,
回到上面通过python拿到的代码,发现本来是显示图片的位置有一个img标签,但是图片是一个1像素的无意义图片,而后面紧跟着一个onload,同级子元素是一个span,class的名字已经暴露了这是什么,从img的onload上入手,浏览器点击进去,不出以为是一些加密混淆后的js,煎蛋粗暴的alert这个函数,得到解密代码
jandan_load_img(b):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function jandan_load_img(b) {
//img元素
var d = $(b);
//span元素
var f = d.next("span.img-hash");
//取得span元素的html
var e = f.text();
//删除span
f.remove();
//解密,继续alert这个解密函数,这个函数名称是动态的,也就是一段时间后可能就不叫这个名了,解决方法就是发现解密错误就去抓一波
var c = f_OAOs3oZgIf3pRi5U9htb21iNCqphCxyq(e, "wGEIMFQbjxuyQZuWLrdDe4ZOrdSrJt3f");
var a = $('<a href="' + c.replace(/(\/\/\w+\.sinaimg\.cn\/)(\w+)(\/.+\.(gif|jpg|jpeg))/, "$1large$3") + '" target="_blank" class="view_img_link">[查看原图]</a>');
d.before(a);
d.before("<br>");
d.removeAttr("onload");
d.attr("src", location.protocol + c.replace(/(\/\/\w+\.sinaimg\.cn\/)(\w+)(\/.+\.gif)/, "$1thumb180$3"));
if (/\.gif$/.test(c)) {
d.attr("org_src", location.protocol + c);
b.onload = function() {
add_img_loading_mask(this, load_sina_gif)
}
}
}

核心解密代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
function(m, r, d) {
var e = "DECODE";
var r = r ? r : "";
var d = d ? d : 0;
var q = 4;
r = md5(r);
var o = md5(r.substr(0, 16));
var n = md5(r.substr(16, 16));
if (q) {
if (e == "DECODE") {
var l = m.substr(0, q)
}
} else {
var l = ""
}
var c = o + md5(o + l);
var k;
if (e == "DECODE") {
m = m.substr(q);
k = base64_decode(m)
}
var h = new Array(256);
for (var g = 0; g < 256; g++) {
h[g] = g
}
var b = new Array();
for (var g = 0; g < 256; g++) {
b[g] = c.charCodeAt(g % c.length)
}
for (var f = g = 0; g < 256; g++) {
f = (f + h[g] + b[g]) % 256;
tmp = h[g];
h[g] = h[f];
h[f] = tmp
}
var t = "";
k = k.split("");
for (var p = f = g = 0; g < k.length; g++) {
p = (p + 1) % 256;
f = (f + h[p]) % 256;
tmp = h[p];
h[p] = h[f];
h[f] = tmp;
t += chr(ord(k[g]) ^ (h[(h[p] + h[f]) % 256]))
}
if (e == "DECODE") {
if ((t.substr(0, 10) == 0 || t.substr(0, 10) - time() > 0) && t.substr(10, 16) == md5(t.substr(26) + n).substr(0, 16)) {
t = t.substr(26)
} else {
t = ""
}
}
return t
}

翻译成python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
def jandan_load_img(m, r = 'ArC3kjouAVZINJqJcXG5tNPFCeUNDzqd', d = 0):
r = hashlib.md5(r.encode('utf-8')).hexdigest()
o = hashlib.md5(r[0:16].encode('utf-8')).hexdigest()
n = hashlib.md5(r[16:].encode('utf-8')).hexdigest()
l = m[0:4]
c = o + hashlib.md5((o+l).encode('utf-8')).hexdigest()
m = m[4:]
k = base64.b64decode(m+'==')
h = []
for i in range(256):
h.append(i)
b = []
for i in range(256):
b.append(ord(c[i%len(c)]))
f = 0
for i in range(256):
f = (f + h[i] + b[i]) % 256
tmp = h[i]
h[i] = h[f]
h[f] = tmp
t = ''
p = 0
f = 0
for i in range(len(k)):
p = (p+1)%256
f = (f + h[p])%256
tmp = h[p]
h[p] = h[f]
h[f] = tmp
t = t + chr(k[i] ^ (h[(h[p] + h[f]) % 256]))
if ((int(t[0:10]) == 0 or int(t[0:10]) - int(time.time()) > 0) and t[10:26] == hashlib.md5((t[26:] + n).encode('utf-8')).hexdigest()[0:16]):
t = t[26:]
else:
t = ''
return t

试了试,成功解析出图片地址,加上代理放肆的爬吧