JS逆向爬虫教程与实战技巧

news2025/7/28 1:20:49

想要一个关于爬虫JS逆向的详细教程。这是一个很专业的技术需求,最近有个可能是正在学习爬虫技术的开发者或者数据分析师,遇到了需要破解JavaScript加密的反爬机制的问题,想让我出一期实战教程,话不多说,开干。

在这里插入图片描述

以下是我整理的一份系统化的爬虫JS逆向教程,结合实战技巧与工具使用,能有效的突破前端加密参数限制。内容涵盖基础原理、调试方法、扣代码技巧及高效解决方案:

一、JS逆向核心流程

  1. 寻找加密入口

    • Network分析:捕获目标请求(XHR/fetch),定位加密参数(如tokensignxyz
    • 全局搜索:在Sources面板按Ctrl+Shift+F搜索参数名(如"nonce"password:
    • 调用栈追踪:通过Network请求的Initiator标签回溯加密逻辑触发点
  2. 调试分析技巧

    • 代码格式化:点击Sources面板左下角 {} 美化压缩代码
    • 断点类型
      • XHR断点:针对特定URL拦截请求
      • 事件断点:监听clicksubmit等DOM事件
      • 条件断点:在加密函数内设置Conditional Breakpoint
    • Scope面板:查看局部变量、闭包域中的关键值(如密钥、盐值)
  3. 模拟执行方案

    方法适用场景工具示例
    扣JS代码逻辑简单、无环境依赖execjs(Python调用)
    RPC通信复杂混淆/浏览器环境依赖Sekiro
    无头浏览器需完整渲染流程PlayWright/Selenium

二、实战案例解析(以汽车之家登录为例)

  1. 目标定位

    • 登录请求中pwd参数为MD5加密:

      # 原始请求示例
      FormData: {username: "test", pwd: "d6d7d5a8c4e6e7b8"}
      
  2. 逆向步骤

    • 步骤1:在Sources搜索pwd,定位到login.js文件

    • 步骤2:发现关键函数 hex_md5(s),其结构如下:

      function hex_md5(s) {
          return binl2hex(core_md5(str2binl(s), s.length * chrsz));
      }  // 
      
    • 步骤3:扣取完整MD5相关函数(core_md5, binl2hex, str2binl

    • 步骤4:Python通过execjs调用:

      import execjs
      with open('qichezhijia.js', 'r', encoding='utf-8') as f:
          js_code = f.read()
      ctx = execjs.compile(js_code)
      encrypted_pwd = ctx.call('hex_md5', '123456')  # 输出:d6d7d5a8c4e6e7b8
      

三、高级技巧

  1. Hook拦截

    • 使用Tampermonkey注入脚本监听关键函数(如btoaencrypt):

      // Hook Base64示例
      (function() {
        var originBtoa = window.btoa;
        window.btoa = function(data) {
          console.log("Base64 input:", data);
          return originBtoa(data);
        }
      })();
      
  2. 反混淆方案

    • 控制流平坦化:使用AST还原工具(如babel
    • 字符串阵列化:动态执行提取真实字符串
  3. Overrides覆盖

    • Chrome的Local Overrides功能替换线上JS文件
    • 注入调试代码或修复环境检测(如补全window对象)

四、常见加密类型与对策

  • 哈希算法(MD5/SHA1):扣取标准算法实现(如本文MD5案例)
  • RSA加密:提取公钥 + 使用rsa库(苏宁易购登录案例)
  • 动态参数
    • 时间戳:同步生成
    • 随机数:Math.random()重放或固定盐值
  • 自定义编码:Base64变异/移位编码 → Hook charCodeAt分析

五、注意事项

  1. 合法合规:遵守robots.txt,避免高频请求
  2. 更新维护:网站JS变动时需重新分析
  3. 性能权衡
    • 简单加密 → 扣代码(高效)
    • 复杂方案 → RPC/无头浏览器(稳定)

通过上面教程,我们可掌握从基础断点调试到复杂RPC调用的全链路JS逆向技能。遇到具体网站难题时,建议结合Chrome DevTools动态分析快速定位突破点。

具体实战代码示例我公布在下面。

以下是一个完整的JS逆向爬虫实战代码示例,以汽车之家登录密码加密为例,演示如何逆向分析并实现自动化登录:

1. 目标分析(浏览器开发者工具操作)

在汽车之家登录页面:

  1. 打开Chrome开发者工具(F12)

  2. 输入用户名/密码点击登录

  3. 在Network面板查看登录请求,发现密码字段为加密值:

    {
      "username": "test@example.com",
      "pwd": "d6d7d5a8c4e6e7b8",  // 123456的加密结果
      "remember": 1
    }
    

2. JS逆向代码实现

步骤1:提取加密JS代码

在Sources面板找到login.js,定位并提取MD5加密函数:

// 保存为 autohome_md5.js
function hex_md5(s) {
  return binl2hex(core_md5(str2binl(s), s.length * chrsz));
}

function core_md5(x, len) {
  /* 此处省略完整MD5算法实现,实际需扣取完整200行代码 */
}

function str2binl(str) {
  var bin = Array();
  var mask = (1 << chrsz) - 1;
  for (var i = 0; i < str.length * chrsz; i += chrsz)
    bin[i >> 5] |= (str.charCodeAt(i / chrsz) & mask) << (i % 32);
  return bin;
}

function binl2hex(binarray) {
  var hex_tab = "0123456789abcdef";
  var str = "";
  for (var i = 0; i < binarray.length * 4; i++) {
    str += hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8 + 4)) & 0xF) +
           hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8)) & 0xF);
  }
  return str;
}

var chrsz = 8;  // 字符位数 (8-bit)
步骤2:Python爬虫实现
import execjs
import requests
from urllib.parse import urlencode

class AutoHomeSpider:
    def __init__(self):
        # 加载JS加密代码
        with open('autohome_md5.js', 'r', encoding='utf-8') as f:
            self.js_code = f.read()
        self.ctx = execjs.compile(self.js_code)
        
        self.session = requests.Session()
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
            'Origin': 'https://account.autohome.com.cn'
        }

    def encrypt_password(self, password):
        """JS逆向加密密码"""
        return self.ctx.call('hex_md5', password)

    def login(self, username, password):
        """执行登录操作"""
        login_url = 'https://account.autohome.com.cn/api/login'
        
        # 加密密码
        encrypted_pwd = self.encrypt_password(password)
        
        # 构造表单数据
        form_data = {
            'username': username,
            'pwd': encrypted_pwd,
            'remember': 1,
            'vcode': '',
            'redirect': 'https://www.autohome.com.cn/'
        }
        
        # 发送登录请求
        response = self.session.post(
            url=login_url,
            data=form_data,
            headers=self.headers
        )
        
        # 检查登录结果
        result = response.json()
        if result['returncode'] == 0:
            print(f"登录成功! 用户名: {username}")
            print(f"Cookies: {self.session.cookies.get_dict()}")
            return True
        else:
            print(f"登录失败: {result['message']}")
            return False

    def get_user_info(self):
        """获取用户信息(需登录后)"""
        info_url = 'https://account.autohome.com.cn/api/GetUserInfo'
        response = self.session.get(info_url, headers=self.headers)
        return response.json()

if __name__ == "__main__":
    spider = AutoHomeSpider()
    
    # 测试账号(请替换为实际账号)
    USERNAME = "your_username@example.com"
    PASSWORD = "your_password"
    
    if spider.login(USERNAME, PASSWORD):
        user_info = spider.get_user_info()
        print("用户信息:", user_info)

3. 复杂场景解决方案(RPC通信)

当遇到环境检测或复杂混淆时,使用Sekiro实现JS桥接:

# Python端 (Sekiro客户端)
from sekiro import SekiroClient

sekiro = SekiroClient("your-group-name", "your-client-id")

@sekiro.action("encrypt")
def handle_encrypt(params):
    password = params["password"]
    # 调用浏览器环境执行加密
    return {"encrypted": sekiro.invoke_browser("encryptPassword", password)}
// 浏览器端 (Tampermonkey脚本)
SekiroClient.register("encryptPassword", function(password) {
    // 在真实浏览器环境中执行加密
    return window.encryptFunction(password); 
});

4. 常见错误处理

# 在加密函数中添加错误处理
def encrypt_password(self, password):
    try:
        return self.ctx.call('hex_md5', password)
    except execjs.RuntimeError as e:
        # 处理JS执行错误
        print(f"JS执行错误: {e}")
        # 降级方案:使用Python的MD5实现
        import hashlib
        return hashlib.md5(password.encode()).hexdigest()
    except Exception as e:
        print(f"加密失败: {e}")
        return None

5. 完整项目结构

js_reverse_demo/
├── autohome_md5.js    # 扣取的加密JS
├── autohome_spider.py # 主爬虫程序
├── requirements.txt   # 依赖文件
└── sekrio_client.py   # RPC桥接文件

requirements.txt内容

requests==2.31.0
PyExecJS==1.5.1
nodejs==0.1.1  # 需要安装Node.js环境

关键点说明:

  1. 完整扣取JS:必须确保核心加密函数及其所有依赖函数都被完整提取
  2. 环境一致性:注意JS中的全局变量(如chrsz)需在扣取代码中保留
  3. 错误降级:准备备用加密方案应对JS执行失败
  4. 请求仿真:需复制所有必要的请求头(特别是Content-Type和Origin)
  5. 会话保持:使用requests.Session维持cookies

这里需要注意的是,实际项目中,我们需根据目标网站的加密实现调整扣取的JS代码。可通过Chrome Overrides功能持久化调试修改后的JS文件(Sources > Overrides > Enable Local Overrides)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2401814.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Redis】Redis 的常见客户端汇总

目录 一、命令行客户端 二、图形界面的客户端 三、Java 客户端 3.1 SpringDataRedis 3.2 Jedis 3.2.1 连接池的配置 3.3 Lettuce 3.3.1 RedisTemplate 工具类实现 3.3.2 自定义序列化器 3.3.3 StringRedisTemplate 3.3.4 集群配置 3.3.4.1 刷新节点集群拓扑动态感应…

关于akka官方quickstart示例程序(scala)的记录

参考资料 https://doc.akka.io/libraries/akka-core/current/typed/actors.html#first-example 关于scala语法的注意事项 extends App是个语法糖&#xff0c;等同于直接在伴生对象中编写main 方法对象是通过apply方法创建的&#xff0c;也可以通过对象的名称单独创建&#x…

2025年渗透测试面试题总结-腾讯[实习]玄武实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]玄武实验室-安全工程师 1. 自我介绍 2. CSRF原理 3. Web安全入门时间 4. 学习Web安全的原因 …

网站首页菜单两种布局vue+elementui顶部和左侧栏导航

顶部菜单实现 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Vue.js Element UI 路由导航</…

@Builder的用法

Builder 是 Lombok 提供的一个注解&#xff0c;用于简化 Java 中构建对象的方式&#xff08;Builder 模式&#xff09;。它可以让你以更加简洁、链式的方式来创建对象&#xff0c;尤其适用于构造参数较多或部分可选的类。

vue实现点击按钮input保持聚焦状态

主要功能&#xff1a; 点击"停顿"按钮切换对话框显示状态输入框聚焦时保持状态点击对话框外的区域自动关闭 以下是代码版本&#xff1a; <template><div class"input-container"><el-inputv-model"input"style"width: 2…

[蓝桥杯]取球博弈

取球博弈 题目描述 两个人玩取球的游戏。 一共有 NN 个球&#xff0c;每人轮流取球&#xff0c;每次可取集合 n1,n2,n3n1​,n2​,n3​中的任何一个数目。 如果无法继续取球&#xff0c;则游戏结束。 此时&#xff0c;持有奇数个球的一方获胜。 如果两人都是奇数&#xff…

[Java 基础]数组

什么是数组&#xff1f;想象一下&#xff0c;你需要存储 5 个学生的考试成绩。你可以声明 5 个不同的 int 变量&#xff0c;但这会显得很笨拙。数组提供了一种更简洁、更有组织的方式来存储和管理这些数据。 数组可以看作是相同类型元素的集合&#xff0c;这些元素在内存中是连…

‘pnpm‘ 不是内部或外部命令,也不是可运行的程序

npm install -g pnpm changed 1 package in 4s 1 package is looking for funding run npm fund for details C:\Users\gang>pnpm pnpm 不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。 原来是安装的全局路径被我改了 npm list -g --depth 0 把上述…

Android Test2 获取系统android id

Android Test2 获取系统 android id 这篇文章针对一个常用的功能做一个测试。 在项目中&#xff0c;时常会遇到的一个需求就是&#xff1a;一台设备的唯一标识值。然后&#xff0c;在网络请求中将这个识别值传送到后端服务器&#xff0c;用作后端数据查询的条件。Android 设备…

webpack打包学习

vue开发 现在项目里安装vue&#xff1a; npm install vue vue的文件后缀是.vue webpack不认识vue的话就接着安插件 npm install vue-loader -D 这是.vue文件&#xff1a; <template> <div><h2 class"title">{{title}}</h2><p cla…

基于Java(Jsp+servelet+Javabean)+MySQL实现图书管理系统

图书管理系统 一、需求分析 1.1 功能描述 1.1.1“读者”功能 1&#xff09;图书的查询&#xff1a;图书的查询可以通过搜索图书 id、书名、作者名、出版社来实现,显示结果中需要包括书籍信息以及是否被借阅的情况&#xff1b; 2&#xff09;图书的借阅&#xff1a;借阅图书…

服务器CPU被WMI Provider Host系统进程占用过高,导致系统偶尔卡顿的排查处理方案

问题现状 最近一个项目遇到一个非常奇葩的问题&#xff1a;正式服务器被一个WMI Provider Host的系统进程占用大量的CPU资源&#xff0c;导致我们的系统偶尔卡顿 任务管理器-详细信息中CPU时间&#xff0c;这个进程也是占用最多的 接口时不时慢很多 但单独访问我们的接口又正…

JavaSwing之--JMenuBar

Java Swing之–JMenuBar(菜单栏) JMenuBar是 Java Swing 库中的一个组件&#xff0c;用于创建菜单栏&#xff0c;通常位于窗口的顶部。它是菜单系统的容器&#xff0c;用于组织和显示应用程序的菜单结构 菜单栏由菜单构成&#xff0c;菜单由菜单项或子菜单构成&#xff0c;也…

【物联网-S7Comm协议】

物联网-S7Comm协议 ■ 调试工具■ S7协议-简介■ S7协议和modbusTCP协议区别■ OSI 层 S7 协议■ S7协议数据结构 &#xff08;TPKTCOTPS7Comm&#xff09;■ TPKT&#xff08;第五层&#xff1a;会话层&#xff09; 总共占4个字节■ COTP&#xff08;第六层&#xff1a;表示层…

数据分析后台设计指南:实战案例解析与5大设计要点总结

引言 数据于企业而言异常重要&#xff0c;企业通过数据可以优化战略决策&#xff0c;因此企业对数据的采集正趋向智能化、数字化&#xff0c;数据分析后台就是企业智能化、数字化记录、分析数据的渠道。本文分享一个数据分析后台原型实战案例&#xff0c;通过页面拆解总结原型…

网络测试实战:金融数据传输的生死时速

阅读原文 7.4 网络测试实战--数据传输&#xff1a;当毫秒决定百万盈亏 你的交易指令为何总是慢人一步&#xff1f; 在2020年"原油宝"事件中&#xff0c;中行原油宝产品因为数据传输延迟导致客户未能及时平仓&#xff0c;最终亏损超过90亿元。这个血淋淋的案例揭示了…

数据库系统概论(十四)详细讲解SQL中空值的处理

数据库系统概论&#xff08;十四&#xff09;详细讲解SQL中空值的处理 前言一、什么是空值&#xff1f;二、空值是怎么产生的&#xff1f;1. 插入数据时主动留空2. 更新数据时设置为空3. 外连接查询时自然出现 三、如何判断空值&#xff1f;例子&#xff1a;查“漏填数据的学生…

【信创-k8s】海光/兆芯+银河麒麟V10离线部署k8s1.31.8+kubesphere4.1.3

❝ KubeSphere V4已经开源半年多&#xff0c;而且v4.1.3也已经出来了&#xff0c;修复了众多bug。介于V4优秀的LuBan架构&#xff0c;核心组件非常少&#xff0c;资源占用也显著降低&#xff0c;同时带来众多功能和便利性。我们决定与时俱进&#xff0c;使用1.30版本的Kubernet…

一台电脑联网如何共享另一台电脑?网线方式

前言 公司内网一个人只能申请一个账号和一个主机设备&#xff1b;会检测MAC地址&#xff1b;如果有两台设备&#xff0c;另一台就没有网&#xff1b;因为是联想老电脑&#xff0c;共享热点用不了&#xff0c;但是有一根网线&#xff0c;现在解决网线方式共享网络&#xff1b; …