其实之前实现过这个功能,是使用selenium模拟浏览器页面点击来完成的,但是效率实际上相对来说较低。本次以解密参数来完成爬取的过程。

首先打开煎蛋网http://jandan.net/ooxx,查看网页源代码。我们搜索其中一张图片的编号,比如3869006,看下在源代码中是否能找到图片链接

python3爬虫爬取煎蛋网妹纸图片(上篇)

python3爬虫爬取煎蛋网妹纸图片(上篇)

 

从上面的HTML结构中找到这个标号对应的一些属性,没有直接的图片链接地址,只有一个src=//img.jandan.net/blank.gif,这很明显不是个真实的链接地址,因为每一个图片编号都有这个值。我们注意到后面还有一个onload=‘jandan_load_img(this)’,可以大胆猜测真实地址有关,传入了一个this参数,也就是调用它的对象。然后后面还有一个img-hash,后面文本一长串的字符,按命名来看应该是图片的hash值,这个目前不知道什么用,先留意下就好,继续往后走,我们去看jandan_load_img()这个函数。

打开chrome F12开发者工具,刷新网页,查看NetWork选项卡中的js,可以在左侧列表项里找到一个包含jandan_load_img()函数的js。如下图:

python3爬虫爬取煎蛋网妹纸图片(上篇)

 

下面我们把这个函数拿出来分析下:

function jandan_load_img(b) {
  // 传入一个参数b,把b赋值给变量d,把d的img-hash赋值给f,把f的文本提取出来。。。说白了就是e等于图片的hash值
var d = $(b); var f = d.next("span.img-hash"); var e = f.text(); f.remove(); // 重点关注下面两句 var c = jdN1vojzUDgDM5WyoSjf4YBLbPRYr4ovPc(e, "9e03YzcYoHuEBMj5eS4c2tbLVWiqSgn1"); 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) } } }

很明显可以看到里面有句话,查看原图,说明这个原始图片链接在这里。所以这个a就是我们所需要的,但是a是拼接起来的一个标签,真实的图片地址应该是c.replace(/(\/\/\w+\.sinaimg\.cn\/)(\w+)(\/.+\.(gif|jpg|jpeg))/, "$1large$3"),所以现在算出c就可以了,看到变量c=jdN1vojzUDgDM5WyoSjf4YBLbPRYr4ovPc(e, "9e03YzcYoHuEBMj5eS4c2tbLVWiqSgn1"),这是一个函数,传入了两个参数,一个e(图片hash值),还有一个字符串,返回值赋值给了c。那我们继续找jdN1vojzUDgDM5WyoSjf4YBLbPRYr4ovPc函数,和jandan_load_img()在同一个js文件中。

函数如下:

var jdN1vojzUDgDM5WyoSjf4YBLbPRYr4ovPc = function(n, t, e) {
    var f = "DECODE";
    var t = t ? t : "";
    var e = e ? e : 0;
    var r = 4;
    t = md5(t);
    // 将n也就是图片的hash值赋值给变量d
    var d = n;
    var p = md5(t.substr(0, 16));
    var o = md5(t.substr(16, 16));
    if (r) {
        if (f == "DECODE") {
            var m = n.substr(0, r)
        }
    } else {
        var m = ""
    }
    var c = p + md5(p + m);
    var l;
    if (f == "DECODE") {
        n = n.substr(r);
        l = base64_decode(n)
    }
    var k = new Array(256);
    for (var h = 0; h < 256; h++) {
        k[h] = h
    }
    var b = new Array();
    for (var h = 0; h < 256; h++) {
        b[h] = c.charCodeAt(h % c.length)
    }
    for (var g = h = 0; h < 256; h++) {
        g = (g + k[h] + b[h]) % 256;
        tmp = k[h];
        k[h] = k[g];
        k[g] = tmp
    }
    var u = "";
    l = l.split("");
    for (var q = g = h = 0; h < l.length; h++) {
        q = (q + 1) % 256;
        g = (g + k[q]) % 256;
        tmp = k[q];
        k[q] = k[g];
        k[g] = tmp;
        u += chr(ord(l[h]) ^ (k[(k[q] + k[g]) % 256]))
    }
    if (f == "DECODE") {
        if ((u.substr(0, 10) == 0 || u.substr(0, 10) - time() > 0) && u.substr(10, 16) == md5(u.substr(26) + o).substr(0, 16)) {
            u = u.substr(26)
        } else {
            u = ""
        }
        //进行base64解码
        u = base64_decode(d)
    }
    return u
};

这个代码写的真。。。长,但是我们只分析自己需要的部分,上面jandan_load_img函数里的c是这个函数的返回值,也就是说我们只需要关注返回值就好。注意到这个返回值是y一个u,找到离return语句最近的u的赋值情况,可以看到,就是那句u=base64_decode(d),这个是一个base64解码,参数是d。我们再找这个d是神马玩意。主要到这个函数只有一句与d有关,就是var d = n,这个n是函数的第一个函数,也就是图片的hash值。也就是说,这个图片hash值经过一个base64解码后返回值就是c,也就是图片地址。

纳尼!!!!!!!!!你写这么长的代码就是整这么个事情么?!

我们以刚才那个图片hash值为例,用python代码写一下,看看到底是不是能得到图片的url。

#! usr/bin/env python
# coding:utf-8

import base64

img_hash = 'Ly93eDQuc2luYWltZy5jbi9tdzYwMC8wMDc2QlNTNWx5MWZzbWRxd2F1dzBqMzBnazBrcGFkOS5qcGc='
url = base64.b64decode(img_hash)
print(url)

python3爬虫爬取煎蛋网妹纸图片(上篇)

 

用浏览器打开这个链接看一下。

python3爬虫爬取煎蛋网妹纸图片(上篇)

 

我感觉我收到了侮辱!!!!!!我先吃碗面压压惊。相信大家看到这里,应该都会爬取煎蛋妹子图片了吧。代码改天再补,我是真的吃面去了。。

 

仅供学习,请勿用于商业用途哦。