【学习心得】webpack技术在爬虫逆向中的应用

一、webpack技术是什么?

(1)定义

Webpack 是一个前端资源模块化管理和打包工具,Webpack技术的出现主要是为了解决现代前端开发中JS代码的模块化组织问题(当然还有别的原因,这里只重点讲和逆向有关的)。

随着JavaScript生态的发展,特别是CommonJS和ES6模块等规范的引入,项目中代码需要以模块化的方式组织。然而,浏览器原生并不直接支持这些模块加载机制,WebPack通过解析、编译和打包模块,使得开发者可以利用模块化的优点编写可维护性更强的代码。

(2)webpack的格式

简单的webpack格式:

javascript 复制代码
// 简单
!function (e) {
    加载器
}(接收的参数)

详细的webpack格式:

javascript 复制代码
// 详细
!function (e) {
    // 存放加载器
    var c = {}
    // 加载器
    function n(t) {
        // 创建a对象
        var a = {
            i: t,  // 表示模块的标识符
            l: !1, // 布尔值,初试为false,用来表示当前模块是否被加载
            exports: {}  // 空对象,用于讲模块导出,存储
        };
        c[t] = {
            i: t,  // 表示模块的标识符
            l: !1, // 布尔值,初试为false,用来表示当前模块是否被加载
            exports: {}  // 空对象,用于讲模块导出,存储
        };
        // 执行函数里面的代码
        return e[t].call(a.exports, a, a.exports, n),
            a.l = !0,
            a.exports
    }
    n.m = e  // n.m 用来存所有的模块
    n(2)     // 执行当前选中的模块,下标2就是第三个模块
}([
    function () {...},
    function () {...},
    function () {...},
    function () {...},
])

(3)模块化

比如下面代码中有三个模块,他们其实就是三个函数,假设这三个模块都有着不同的功能,这里演示代码中显示的是打印不同字符。

javascript 复制代码
function ModuleA() {console.log("a")}
function ModuleB() {console.log("b")}
function ModuleC() {console.log("c")}

但如果你的写的功能模块有几百上千个,那么这样的书写方式必须放在同一个JS文件中就会非常臃肿,于是出现了这样的代码结构:

javascript 复制代码
!function(i) {
    function n(t) {
        return i[t].call(a, b, c, d)
    }
}([
    function(t, e, n) {}, 
    function(t, e, r) {}, 
    function(t, e, o) {}, 
    function(t, e) {},
]);

由于在扣JS加密代码时会经常遇到,所以理解这种语法对于逆向来说是非常重要的。

这种代码组织相当于进行了模块化编程,因此被称为 webpack。上面的代码看起来很费劲,其中的一个重要原因就是函数的参数和函数名都是简单的字母没有含义,都不知道这是干什么。于是我们可以写成下面这种方式便于理解:

javascript 复制代码
!function (allModule) {

    // 定义执行模块的函数
    function useModule(whichModule) {
        // 用call方法来执行函数
        allModule[whichModule].call(null, "hello world!");
    }
    useModule(0)  // 这里指定加载哪一个模块
}([
    function ModuleA(param) {console.log("A" + param)},  // 用数组装所有的模块,这是第一个
    function ModuleB(param) {console.log("B" + param)},
    function ModuleC(param) {console.log("C" + param)},
]);

二、技术拆解

(1)JS的自执行函数

IIFE 全称 Immediately-invoked Function Expressions,译为立即调用函数表达式,也称为自执行函数、立即执行函数、自执行匿名函数等,IIFE 是一种语法,这种模式本质上就是函数表达式(命名的或者匿名的)在创建后立即执行。当函数变成立即执行的函数表达式时,表达式中的变量不能从外部访问。IIFE 主要用来隔离作用域,避免污染。它长这个样子(我只介绍最常见的形式):

javascript 复制代码
// 第一种形式:用感叹号表示
!function () {
    console.log("I AM IIFE")
};

!function () {
    console.log(A)
}(A);  // 后面紧跟的小括号里面可以传入参数

// 第二种形式:用括号表示
(function () {
    console.log("I AM IIFE")
}());

(() => {
  console.log("I AM IIFE")
})();

(2)call方法apply方法

JavaScript 中的 call() 和 apply() 方法都是函数对象(Function.prototype)上的方法,它们的主要功能是改变函数调用时的上下文环境(即函数内部 this 的指向),同时允许你传递参数给该函数。

下面是call方法的使用例子:

javascript 复制代码
function sayHello(name) {
  console.log('Hello, ' + this.name + ', ' + name);
}

let user = { name: 'John' };
sayHello.call(user, 'Doe'); // 输出 "Hello, John, Doe"

下面是apply方法的使用例子:

javascript 复制代码
function sum(a, b) {
  return a + b;
}

let numbers = [3, 5];
let result = sum.apply(null, numbers); // 输出 8,等同于 sum(3, 5)

总结起来就是,call和apply第一个参数都是函数运行时的上下文对象thisArg。后面的参数不同,对于call来说,参数是一个个传入;对于apply来说,参数是通过一个数组传入。

  • 当需要以逗号分隔的形式传递参数时,可以使用 call() 方法。
  • 当需要以数组形式传递可变数量的参数时,应该使用 apply() 方法。
相关推荐
初遇你时动了情7 分钟前
react 项目打包二级目 使用BrowserRouter 解决页面刷新404 找不到路由
前端·javascript·react.js
南城巷陌23 分钟前
JWT认证机制在Node.js中的详细阐述
node.js·jwt认证机制·前端安全认证
乔峰不是张无忌33026 分钟前
【HTML】动态闪烁圣诞树+雪花+音效
前端·javascript·html·圣诞树
鸿蒙自习室34 分钟前
鸿蒙UI开发——组件滤镜效果
开发语言·前端·javascript
m0_7482507441 分钟前
高性能Web网关:OpenResty 基础讲解
前端·openresty
前端没钱1 小时前
从 Vue 迈向 React:平滑过渡与关键注意点全解析
前端·vue.js·react.js
NoneCoder1 小时前
CSS系列(29)-- Scroll Snap详解
前端·css
无言非影1 小时前
vtie项目中使用到了TailwindCSS,如何打包成一个单独的CSS文件(优化、压缩)
前端·css
我曾经是个程序员2 小时前
鸿蒙学习记录
开发语言·前端·javascript
羊小猪~~2 小时前
前端入门之VUE--ajax、vuex、router,最后的前端总结
前端·javascript·css·vue.js·vscode·ajax·html5