写在前面

现在前端页面为了防止爬虫恶意爬取数据,多多少少会对数据进行加密,有的是重新编码再解码,有的是用字体来表示纯文本,还有用图片的。如果直接爬取,由于没有js动态加载,因此都是原始的加密后的数据,需要通过一定手段还原为可读数据。正所谓只有魔法才能打败魔法,也只有代码才能打败代码。还是一句话,只要是前端js加密的内容,理论上都是可以通过js来反向还原数据的,只不过大多数js都经过混淆,可读性差,需要不断打断点调试,确定核心的解密函数。本来想直接爬取的,结果发现名称都是被加密过的,查看源代码后,发现加密过程简单,非常适合入门。

解密过程分析

网页显示的是一行行的标题内容,是通过ul li标签实现的,爬取不是难事,但是标题不是直接的文本,而是下面这样的内容,显然是js动态生成标题的。

<li>[03-07] 
    <a href="/movie.php?id=9523175675421954" target='_blank'>
        <script type="text/javascript">
            document.write(d('OTHlkYblk6Xns7vliJcwMTYt6YWS5bqX5YG35oOFNFPlupfnvo7lpbPplIDllK7pq5jmuIXml6DmsLTljbDlrozmlbTniYg='));
        </script>
    </a>
</li>

既然是前端解密,那么就好办了,找到d函数就可以了,这里使用使用Chrome的F12功能,打断点找到函数调用过程即可,找到的d函数是孤立的,没有与其他函数嵌套,所以单独分析d函数即可。

function d(input){
    rv = window.atob(input);
    rv = escape(rv);
    rv = decodeURIComponent(rv);
    return rv;
}

虽然d函数中有三个其它函数,但都是js自带的函数,也就是说只要查阅这三个函数的功能即可。
window.atob是用于将编码后的Base64字符串转为ASCII字符串。效果如下:

var str = 'javascript';
window.btoa(str)                    // 编码结果 "amF2YXNjcmlwdA=="
window.atob("amF2YXNjcmlwdA==")     // 解码结果 "javascript"

escape函数可对字符串进行编码,这样就可以在所有的计算机上读取该字符串。该方法不会对 ASCII 字母和数字进行编码,也不会对下面这些 ASCII 标点符号进行编码: * @ - _ + . / 。其他所有的字符都会被转义序列替换。

escape("JavaScript_ _脚本语言@!");
"JavaScript_%20_%u811A%u672C%u8BED%u8A00@%21"

decodeURIComponent函数可对encodeURIComponent函数编码后的 URI 进行解码。
我们尝试将数据解码后看一下,可以得到如下结果:

// 再也不用担心被显示敏感词了。
d("OTHlkYblk6Xns7vliJcwMTYt6YWS5bqX5YG35oOFNFPlupfnvo7lpbPplIDllK7pq5jmuIXml6DmsLTljbDlrozmlbTniYg=")
"91呆哥系列016-酒店偷情4S店美女销售高清无水印完整版"

在弄懂了d函数的实现过程后,还可以写出其逆过程

function r(input){
    res = encodeURIComponent(input); 
    res = unescape(res);
    res = window.btoa(res);
    return res;
}

Python实现

import base64
base64.b64decode(input).decode()
from urllib.request import unquote
unquote(base64.b64decode(input).decode())    // 其实不要这步已经可以得到结果了。