持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第25天,点击查看活动详情
📢📢📢📢📢📢 💗 你正在阅读 【梦想橡皮擦】 的博客 👍 阅读完毕,可以点点小手赞一下 🌻 发现错误,直接评论区中指正吧 📆 橡皮擦的第 621 篇原创博客
⛳️ webpack 原理说明
webpack 是前端程序员用来进行打包 JS 的技术,打包之后的代码特征非常明显,例如下述代码。
(window.webpackJsonp = window.webpackJsonp || []).push([[0], []]);
有经验之后,当看到出现 app.版本号.js,chunk-libs.版本号.js> 就能大概猜到 JS 是使用了 webpack 加密。
学习过程中,我们顺手解决一个 webpack 的加密站点,地址如下所示:https://passport.gm99.com/
添加了包含关键字
login/login3 的断点之后,通过开发者工具调试得到下述代码段。
当通过调试进入
a.encode() 函数内部之后,发现了大量的 webpack 打包 JS 的痕迹,例如下图红框部分。
其实发现加密逻辑之后,可以直接用 Python 进行复写代码也是可以的。
这里面出现的关键字包含如下内容。
n = function(t,e,n)n.exports = s.call(e,i,e,t)
然后翻阅到 JS 文件头部,简化代码得到如下内容,到这里 webpack 的痕迹。
!(function (t) {
function e(s) {
return t[s].call(n.exports, n, n.exports, e), (n.loaded = !0), n.exports;
}
})();
如果在细研究一下,webpack 打包之后的代码执行规则也非常简单。
!(function (t) {
function e(s) {
// 代码省略
return t[s].call(n.exports, n, n.exports, e), (n.loaded = !0), n.exports;
}
e(0); // 调用下面的 0
e(1); // 调用下面的 1
})({
0: function (t, e, i) {
// 这里有一大堆打码
},
1: function (t, e) {
t.exports = jQuery;
},
});
扣 JS 代码
接下来我们就实战扣取一下可执行的 JS 代码。
第一步:创建一个 JS 文件,名称任意
编写如下代码,将函数 e 暴露出来。
var _e;
!(function (t) {
var i = {};
function e(s) {
if (i[s]) return i[s].exports;
var n = (i[s] = {
exports: {},
id: s,
loaded: !1,
});
return t[s].call(n.exports, n, n.exports, e), (n.loaded = !0), n.exports;
}
_e = e;
})();
接下来分区域扣取 JS 代码,这里依据 function() 进行区分即可。
所有不全之后的代码,可以去 gitcode 进行下载。
接下来运行生成的静态文件,测试可执行函数,就能得到对应的数据了。
⛳️ 起点 实战场景
本次采集的案例是点起文中,你可以随机打开一本目标xiaoshuo,检查一下网络请求中是否存在字体文件响应数据。
Python脱敏处理.Python脱敏处理.Python脱敏处理/info/2952453/#Catalog
字体加密位置呈现的效果如下图所示。
编写网页爬取代码,查看其字体位置使用的编码。
import requests
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36",
"Origin": 'https://Python脱敏处理.com',
"referer": "https://Python脱敏处理.com"
}
response = requests.get(url='https://Python脱敏处理/info/2952453/',headers=headers)
response.encoding = 'utf-8'
print(response.text[:20000])
截取源码部分,查看编码内容。
同时下载本页面的字体文件,用工具打开之后,发现字体编码图形顺序没有什么变化,这对于后续我们解决反爬就变得非常简单了。
接下来读取和解构一下这个字体文件,在其中找到能用的数据。
from fontTools.ttLib import TTFont
import io
file_woff = './fonts/YOfzYtjr.woff'
with open(file_woff, 'rb') as font_file:
font = TTFont(io.BytesIO(font_file.read())) # 转换成字体对象
#字体映射关系
font_cmap = font['cmap'].getBestCmap()
print(font_cmap)
输出的信息为:
{100418: 'two', 100420: 'seven', 100421: 'five', 100422: 'nine', 100423: 'six', 100424: 'three', 100425: 'four', 100426: 'zero', 100427: 'one', 100428: 'period', 100429: 'eight'}
接下来在回头去看一下刚才字体反爬位置的特殊字符与字体编码。 网页特殊字符
𘞱𘞯𘞴𘞲𘞱𘞭
字体编码
{100269: 'nine', 100271: 'five', 100272: 'three', 100273: 'six', 100274: 'period', 100275: 'one', 100276: 'eight', 100277: 'two', 100278: 'four', 100279: 'seven', 100280: 'zero'}
得到最终的结果。
𘞱 -> 6