跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
PythonNode.js大前端算法

Selenium 动态数据抓取与 JS 逆向解密实战

Selenium 用于处理动态加载页面和模拟登录,相比 PhantomJS 更稳定。通过 chromedriver 控制真实浏览器,利用 page_source 获取渲染后数据。针对验证码,需截图裁剪而非重复请求。JS 逆向方面,通过抓包定位加密参数生成函数和解密回调,结合 PyExecJS 在 Python 中执行 JS 逻辑完成数据解密。涵盖动态爬取、打码平台对接及混淆代码分析实战。

技术博主发布于 2025/2/4更新于 2026/7/3147 浏览
Selenium 动态数据抓取与 JS 逆向解密实战

Selenium 与爬虫的关联

在 Selenium 普及之前,基于 Webkit 的无界面浏览器 PhantomJS 曾是自动化测试的主流工具。但 Selenium 直接运行在真实浏览器中,模拟用户操作更加自然,数据提取能力更强,目前已基本取代了 PhantomJS。

Selenium 的核心作用

  1. 捕获任意形式的数据:page_source 属性能返回页面加载完成后的所有源码,无论是静态 HTML 还是 Ajax 动态加载的内容,真正实现了"可见即可爬取"。虽然效率略低于纯 HTTP 请求,但准确性高。
  2. 模拟登录:对于反爬机制复杂的大型网站,Selenium 能模拟真实的浏览器行为,绕过部分验证逻辑。

Selenium 捕获动态加载数据

环境准备

首先需要下载 chromedriver,这是驱动 Chrome 浏览器的核心组件。务必确保驱动版本与你本地安装的 Chrome 浏览器版本一致。在地址栏输入 chrome://version/ 可查看当前版本号。

安装依赖:

pip install selenium

案例:药监总局企业数据爬取

该网站数据通过 Ajax 动态加载,URL 固定,点击页码会触发后台请求。利用 Selenium,我们无需关心 Ajax 细节,直接解析渲染后的 DOM 即可。

先尝试爬取第一页数据:

from selenium import webdriver
from lxml import etree
import time

# 指定 chromedriver 路径,建议配置环境变量
bro = webdriver.Chrome(executable_path='../chromedriver_win32/chromedriver.exe')
url = 'http://125.35.6.84:81/xk/'
bro.get(url)

# page_source 获取渲染后的完整 HTML
page_text = bro.page_source

# 解析企业名称
tree = etree.HTML(page_text)
li_list = tree.xpath('//*[@id="gzlist"]/li')
for li in li_list:
    name = li.xpath('./dl/@title')[0]
    print(name)

bro.quit()

如何爬取多页数据?

由于 URL 不变,我们需要模拟点击"下一页"按钮。注意添加延时等待数据加载。

from selenium import webdriver
from lxml import etree
import time

bro = webdriver.Chrome(executable_path='../chromedriver_win32/chromedriver.exe')
url = 'http://125.35.6.84:81/xk/'
bro.get(url)

all_page_text = []
# 控制翻页次数
for i in range(3):
    # 定位下一页按钮并点击
    next_page_tag = bro.find_element_by_xpath('//*[@id="pageIto_next"]')
    next_page_tag.click()
    time.sleep(2)  # 等待 Ajax 请求完成
    all_page_text.append(bro.page_source)

# 批量解析
for page_text in all_page_text:
    tree = etree.HTML(page_text)
    li_list = tree.xpath('//*[@id="gzlist"]/li')
    for li in li_list:
        name = li.xpath('./dl/@title')[0]
        print(name)

bro.quit()

Selenium 的优势在于它就是一个可控制的真实浏览器,无需处理复杂的反爬策略,只需掌握元素定位(XPath、ID、Class)和 page_source 的使用即可。

Selenium 模拟登录:以 12306 为例

简单的古诗文登录可能不需要截图,但像 12306 这种带有图形验证码的网站,不能单独请求验证码图片,因为 Selenium 打开页面时已经触发了一次请求,再次请求会导致验证码不一致。

解决方案:截屏后裁剪验证码区域,再送入打码平台。

前置准备:

pip install Pillow

代码实现:

from PIL import Image
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
import time

bro = webdriver.Chrome(executable_path='../chromedriver_win32/chromedriver.exe')
url = 'https://kyfw.12306.cn/otn/login/init'
bro.get(url)
time.sleep(2)  # 等待验证码加载

# 输入账号密码
username_tag = bro.find_element(By.ID, 'username')
username_tag.send_keys('你的用户名')
password_tag = bro.find_element(By.ID, 'password')
password_tag.send_keys('你的密码')

# 截屏并裁剪验证码
bro.save_screenshot('./main.png')
code_img_tag = bro.find_element(By.XPATH, '//*[@id="loginForm"]/div/ul[2]/li[4]/div/div/div[3]/img')
location = code_img_tag.location
size = code_img_tag.size

# 计算裁剪坐标
rect = (int(location['x']), int(location['y']), 
        int(location['x'] + size['width']), int(location['y'] + size['height']))

i = Image.open('./main.png')
frame = i.crop(rect)
frame.save('./code.png')

# TODO: 此处调用超级鹰等打码接口
# result = transform_code_img('./code.png', 9004)

# 假设已获取坐标结果,格式为 x1,y1|x2,y2...
result = "100,100|200,200"

# 解析坐标
all_list = []
if '|' in result:
    list1 = result.split('|')
    for item in list1:
        xy_list = [int(item.split(',')[0]), int(item.split(',')[1])]
        all_list.append(xy_list)
else:
    all_list.append([int(result.split(',')[0]), int(result.split(',')[1])])

# 使用动作链点击验证码
for position in all_list:
    x, y = position
    ActionChains(bro).move_to_element_with_offset(code_img_tag, x, y).click().perform()
    time.sleep(1)

# 点击登录
bro.find_element(By.ID, 'loginSub').click()
time.sleep(3)

# 验证登录成功
page_str = bro.page_source
print("登录状态检查...")
bro.quit()

注意事项:

  • 电脑屏幕缩放比例必须设置为 100%,否则坐标计算会偏移。
  • 打码服务需要充值积分,请替换为自己的 API Key。

JS 加密与混淆机制分析

案例:空气质量查询网

该网站使用了较为复杂的 JS 加密和混淆技术。响应数据是密文,前端通过回调函数解密显示。

逆向思路:

  1. 抓包:找到 Ajax 请求,观察参数 d(动态加密)和 Response(加密数据)。
  2. 定位源码:搜索绑定搜索按钮的事件函数,追踪到发起 Ajax 的 getServerData 函数。
  3. 反混淆:JS 混淆旨在隐藏逻辑,可使用在线工具或手动还原。
  4. JS 逆向执行:在 Python 中调用 JS 函数生成参数和解密数据。

工具准备:

  • 安装 Node.js 环境(PyExecJS 依赖)。
  • 安装 PyExecJS:
pip install PyExecJS

步骤一:生成加密参数 d

将反混淆后的 JS 代码保存为 test.js,并在末尾添加封装函数:

function getPostParamCode(method, city, type, startTime, endTime){
    var param = {};
    param.city = city;
    param.type = type;
    param.startTime = startTime;
    param.endTime = endTime;
    return getParam(method, param);
}

Python 端调用:

import execjs

node = execjs.get()
file = 'test.js'
ctx = node.compile(open(file, encoding='utf-8').read())

method = 'GETDETAIL'
city = '北京'
type_ = 'HOUR'
start_time = '2018-01-25 00:00:00'
end_time = '2018-01-25 23:00:00'

js = 'getPostParamCode("{0}", "{1}", "{2}", "{3}", "{4}")'.format(
    method, city, type_, start_time, end_time)
params = ctx.eval(js)
print(params)

步骤二:解密 Response

拿到加密的 Response 后,同样通过 JS 函数解密:

response_text = requests.post(url, data={'d': params}).content.decode()
js = 'decodeData("{0}")'.format(response_text)
decrypted_data = ctx.eval(js)
print(decrypted_data)

说明: 部分网站服务器可能不稳定,导致无法获取有效数据,但逆向流程本身是通用的。核心在于找到前端负责加密和解密的 JS 源码,并通过 PyExecJS 桥接至 Python 环境执行。

总结

JS 逆向的核心在于理解前端逻辑。手动改写为 Python 代码可行但繁琐,推荐使用 PyExecJS 配合 Node.js 环境。遇到混淆代码时,善用反混淆工具,结合浏览器调试器逐步追踪函数调用链。

目录

  1. Selenium 捕获动态加载数据
  2. 指定 chromedriver 路径,建议配置环境变量
  3. page_source 获取渲染后的完整 HTML
  4. 解析企业名称
  5. 控制翻页次数
  6. 批量解析
  7. Selenium 模拟登录:以 12306 为例
  8. 输入账号密码
  9. 截屏并裁剪验证码
  10. 计算裁剪坐标
  11. TODO: 此处调用超级鹰等打码接口
  12. result = transformcodeimg('./code.png', 9004)
  13. 假设已获取坐标结果,格式为 x1,y1|x2,y2...
  14. 解析坐标
  15. 使用动作链点击验证码
  16. 点击登录
  17. 验证登录成功
  18. JS 加密与混淆机制分析
  19. 总结
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 在鸿蒙游戏开发中接入 AI NPC 的体验与实践
  • FLUX.1-dev WebUI 实战:实时进度监控与 24G 显存优化指南
  • Neo4j 数据库安装与配置教程(Windows/MacOS/Linux)
  • C 语言 Web 开发:CGI、FastCGI 与 Nginx 实战解析
  • 基于 FPGA 的 16QAM 调制解调系统设计与实现
  • llama.cpp本地部署性能调优指南:从启动瓶颈到推理效率优化
  • Redis 五大核心数据结构详解与应用
  • FPGA 摄像头采集到 HDMI 显示完整链路:OV5640 实时显示方案
  • 构建稳健 RAG 应用:文档索引与存储深度解析
  • 飞算 JavaAI 智能编程助手功能介绍
  • MySQL 深入理解 InnoDB 核心文件结构:.ibd、.ib_logfile、undo 日志与 ibdata1
  • Clip Interrogator AI 绘画提示词生成工具使用指南
  • 基于 GPT-5 API 与 RAG 知识库构建智能客服机器人
  • Spring Web 模块核心架构与 RESTful API 实战指南
  • Qwen2.5-VL-32B 多卡部署:vLLM 通信瓶颈与 llama.cpp 流水线并行实战
  • 阿里开源 Page-Agent:一行 JS 代码实现大模型前端 DOM 操控
  • 基于 SpringAI+RAG 的知识库问答机器人实现
  • Levenberg-Marquardt 非线性最小二乘优化算法 C++ 实战实现
  • SQL Server 2016 安装 Microsoft R Open 和 Microsoft R Server 组件问题解决方法
  • C++ Primer 中文版电子书简介

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online