前端 AJAX 详解 + 动态页面爬虫实战思路

目前 80% 的网站都使用了AJAX技术,那么传统的爬虫通过 html 来获取数据就不行了,总结一下 AJAX 相关知识。

1、前端三大核心

前端开发的三大核心基础是 HTMLCSSJavaScript

  • HTML 负责搭建网页的结构与内容(结构)
  • CSS 负责网页的样式、布局和视觉效果(表现)
  • JavaScript 负责网页的交互、逻辑和数据处理(行为)

HTML(结构层)

本质上是 标记语言(Markup Language),通过标签描述页面元素。

常见标签:

<h1>标题</h1><p>段落</p><ahref="https://example.com">链接</a><imgsrc="image.jpg"><div></div>

页面结构示例:

<!DOCTYPEhtml><html><head><title>网页标题</title></head><body><h1>Hello World</h1><p>这是一个网页</p></body></html>

CSS(表现层)

主要负责:

  • 颜色
  • 字体
  • 布局
  • 动画
  • 响应式设计

示例

h1{color: red;font-size: 30px;}

HTML + CSS

<h1class="title">Hello</h1>
.title{color: blue;}

JavaScript(行为层)

负责:

  • 动态效果
  • 用户交互
  • 请求服务器数据
  • 操作DOM

示例:

点击按钮改变文字

<buttononclick="changeText()">点击</button><pid="text">Hello</p>
functionchangeText(){ document.getElementById("text").innerText="Hello JS";}

最后再举一个三者的例子

一个按钮:

HTML 定义按钮 CSS 让按钮变漂亮 JS 点击按钮触发逻辑 

代码:

<button id="btn">点击</button><style> button{ background:red; color:white;}</style><script> document.getElementById("btn").onclick=function(){ alert("点击成功");}</script>

2、AJAX

AJAX 是什么

全称:Asynchronous JavaScript and XML(异步 JavaScript 和 XML)。它不是一种新的编程语言,而是一种 Web 开发技术组合,用于让网页在不重新加载整个页面的情况下与服务器交换数据并更新部分页面内容

⚠️ 补充:虽然名字里带 XML,但现在实际开发中几乎都用 JSON(更轻量、易读)代替 XML,AJAX 只是沿用了历史名称。

核心特点

  • 异步(Asynchronous):发送请求后,浏览器不用等着服务器响应,可以继续做其他事(比如用户还能点击按钮、输入内容),响应回来后再处理;
  • 局部更新:只更新网页需要变化的部分,不是整个页面重新加载,体验更流畅;
  • 无刷新:用户看不到浏览器的刷新动作,交互感更自然。

举例

  • 在电商页面下滑,自动加载更多商品
  • 微博 / 抖音无限滚动加载新内容
  • 输入关键词,实时出搜索建议

这些全是 AJAX。

和传统请求对比

传统网页请求流程:

  1. 用户点击按钮 / 提交表单
  2. 浏览器向服务器发送请求
  3. 服务器返回完整 HTML
  4. 整个页面刷新

AJAX 的流程:

  1. 用户触发操作
  2. JavaScript 在后台发送 HTTP 请求
  3. 服务器返回数据(JSON / XML / HTML)
  4. JavaScript 只更新页面的一部分

简单代码示例(两种常用方式)

方式 1:原生 XMLHttpRequest(AJAX 基础实现)
// 1. 创建 XMLHttpRequest 对象(核心)const xhr =newXMLHttpRequest();// 2. 配置请求:请求方式、请求地址、是否异步(默认true) xhr.open('GET','https://jsonplaceholder.typicode.com/todos/1',true);// 3. 监听请求状态变化(核心) xhr.onreadystatechange=function(){// readyState=4 表示请求完成,status=200 表示响应成功if(xhr.readyState ===4&& xhr.status ===200){// 4. 处理服务器返回的数据(JSON格式)const data =JSON.parse(xhr.responseText); console.log('请求成功,返回数据:', data);// 5. 局部更新页面(比如把数据显示到页面) document.getElementById('result').innerHTML =` <p>任务标题:${data.title}</p> <p>是否完成:${data.completed ?'是':'否'}</p> `;}};// 4. 发送请求 xhr.send();// 页面中需要有一个容器来显示结果// <div></div>
方式 2:现代方案 fetch API(更简洁,推荐)

原生 fetch 是 ES6+ 新增的 AJAX 方案,语法更简洁,支持 Promise:

// 发起 GET 请求fetch('https://jsonplaceholder.typicode.com/todos/1')// 第一步:处理响应,转为 JSON 格式.then(response=>{if(!response.ok){thrownewError('请求失败:'+ response.status);}return response.json();})// 第二步:使用数据,局部更新页面.then(data=>{ console.log('fetch请求成功:', data); document.getElementById('result').innerHTML =` <p>任务ID:${data.id}</p> <p>任务标题:${data.title}</p> `;})// 捕获请求异常.catch(error=>{ console.error('请求出错:', error); document.getElementById('result').innerHTML ='<p>请求失败,请重试</p>';});

AJAX 的实际应用场景

  • 实时表单验证:比如注册时输入用户名,立刻检查是否已被占用(不用提交整个表单);
  • 滚动加载:比如刷朋友圈、抖音,下滑自动加载更多内容;
  • 搜索建议:输入关键词时,实时弹出相关搜索提示(如百度搜索);
  • 实时数据展示:比如股票行情、天气信息、聊天消息的实时更新。

AJAX 对爬虫的影响

AJAX 对爬虫的影响,本质是改变了“数据出现的位置和时机”。

传统爬虫思路:请求 URL → 拿到 HTML → 用 XPath / 正则提取数据。

AJAX 页面:你直接请求 URL,拿到的 HTML 是空壳、没有数据,数据全是 JS 后来异步加载的。

如何判断是否使用了AJAX

1、浏览器开发者工具(F12)
  1. 按 F12(或右键 → 检查)
  2. 切换到 Network(网络) 标签
  3. 在 Filter(过滤器)里输入 XHR 或 Fetch(或者直接勾选 XHR/Fetch 复选框)
  4. 刷新页面(Ctrl + R)

判断标准

  • 如果看到一大堆 JSON 请求(Type 列显示 xhr 或 fetch),而且请求路径带 /api/、/v2/、/feed 等等 → 就是 AJAX!
  • 这些请求返回的数据正是页面显示的内容(预览里能直接看到列表/详情)
  • 同时 Ctrl+U 查看原始 HTML 几乎是空的(只有 <div></div>)→ 确认是 JS 通过 AJAX 加载数据

小技巧

  • 时间线上看:页面 HTML 先加载(Document),然后才出现一堆 XHR → 典型 AJAX 特征
Document 就是你最开始请求的那个网页 HTML
浏览器先把整个页面的骨架(html、head、body、空的 div)一次性下载完,这一步叫 Document 加载完成。
  • 如果 Filter 里什么都没有,只有静态 CSS/JS → 不是 AJAX(可能是 SSR 直出)
2、对比“原始源码” vs “真实页面”
  1. 右键页面 → 查看网页源代码(Ctrl+U)
  2. 搜索你肉眼看到的数据(如商品标题、文章内容)
    • 搜不到 → 数据不在 HTML 里 → 一定是 AJAX(或 WebSocket)
  1. 如果 Network 里又有 XHR JSON → 100% 是 AJAX

AJAX 页面爬虫的解决方案

方法1:直接调用 API(最优方案)

步骤:

  1. 打开浏览器
  2. F12 → Network
  3. 找 Fetch/XHR 请求
  4. 复制接口
判断 API 是否可以直接爬

检查 Request Headers

重点看:

cookie token sign authorization 

分三种情况。

情况1:无鉴权(最简单)

请求类似:

GET https://api.xxx.com/gold 

直接:

import requests url ="https://api.xxx.com/gold" res = requests.get(url).json()print(res)

完成。

情况2:需要 headers

例如:

User-Agent Referer Cookie 

复制浏览器请求头:

headers ={"User-Agent":"...","Referer":"...","Cookie":"..."} requests.get(url, headers=headers)
情况3:接口有加密

当接口存在:

  • sign
  • token
  • 加密参数

例如:

sign=md5(timestamp+secret)

需要:

逆向 JS 算法。

方法2:模拟浏览器

使用:

  • Selenium
  • Playwright

让爬虫 执行 JavaScript。

3、WebSocket

除了 AJAX,还有一种传统爬虫无法直接抓取数据的情况,就是使用了 WebSocket 协议传输数据。

WebSocket 是一种基于 TCP 的全双工双向通信协议,和我们熟悉的 HTTP 有本质区别:

  • HTTP:客户端主动发请求 → 服务端响应 → 连接关闭(请求 - 响应模式,单向 / 被动);
  • WebSocket(WS):客户端与服务端完成一次握手后,建立持久连接,双方可以随时互相发送数据(实时、双向)。

WebSocket 连接建立时,必须先通过 HTTP 协议进行握手(HTTP Upgrade)。客户端发送一个 HTTP 请求,请求升级协议。

示例:

GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: xxxxx Sec-WebSocket-Version: 13

服务器如果同意升级,会返回:

HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade 

然后:

HTTP 连接升级为 WebSocket

后续通信就 不再使用 HTTP,而是 WebSocket 帧协议

因此可以总结为:

WebSocket = HTTP 握手 + 独立通信协议 

端口和网络兼容

WebSocket 通常使用:

协议默认端口
HTTP80
HTTPS443
WS80
WSS443

常见使用 WS 的典型场景:

  • 实时股票/行情(雪球、东方财富、同花顺)
  • 直播弹幕/聊天(抖音直播、B站直播、淘宝直播)
  • 体育比分、电竞数据
  • 在线监控、推送通知(某些银行风控页、游戏对战)
  • 某些 IM 类应用

特点:数据不是一次性加载,而是持续推送。页面初始 HTML 可能完全没数据(或只有骨架),所有内容靠 WS 实时进来。

如何判断网站用了 WebSocket?

1、F12 → Network

  • 切换到 WS 标签(WebSocket)
  • 刷新页面 → 如果出现 ws:// 或 wss:// 的连接,且状态是 101 Switching Protocols → 就是 WS!

2、看 Initiator:很多是 main.js 或 socket.js 发起的持久连接

如何爬取 WebSocket 数据

推荐优先级(从易到难):

方法1:Playwright / Puppeteer(最推荐,新手首选)
Pythonfrom playwright.sync_api import sync_playwright with sync_playwright()as p: browser = p.chromium.launch(headless=False) page = browser.new_page() page.goto("目标网址")# 监听所有 WebSocket page.on("websocket",lambda ws:print("WS 连接:", ws.url))# 监听消息(核心!)defhandle_message(msg):print("收到 WS 数据:", msg)# 这里就是你要的数据 page.on("websocket",lambda ws: ws.on("framereceived", handle_message))input("按回车结束...")# 保持运行

优点:自动处理握手、Cookie、反爬,几乎零逆向。

方法2:纯 Python websocket-client(轻量,适合已知 WS 地址)
Pythonimport websocket defon_message(ws, message):print("实时数据:", message)# 解析 JSON 即可 ws = websocket.WebSocketApp("wss://xxx.com/socket",# 从 Network 复制 ws 地址 on_message=on_message, header={"Cookie":"你的cookie"}# 带登录态) ws.run_forever()

部分网站 WS 连接参数加密(token、sign、device_id),需要先逆向 JS 才能构造 ws url。这时通常结合 Playwright 更稳。

Read more

【花雕学编程】Arduino BLDC 之使用6.5寸轮毂电机的智能动态跟随机器人底盘

【花雕学编程】Arduino BLDC 之使用6.5寸轮毂电机的智能动态跟随机器人底盘

基于Arduino与6.5寸轮毂电机的智能动态跟随机器人底盘,是一种将一体化高扭矩动力单元与实时感知决策系统深度融合的移动平台方案。该方案利用轮毂电机“轮内驱动”的紧凑特性,结合Arduino(或ESP32等兼容主控)的灵活控制能力,旨在实现对人、车或特定目标的平滑、抗扰、低延迟的伴随运动。 一、 主要特点 一体化高扭矩动力架构 直驱/准直驱结构:6.5寸轮毂电机将BLDC电机、行星减速器(常见速比1:10~1:30)、轮毂及轴承高度集成。省去了皮带、链条等中间传动环节,传动效率高(>85%),结构紧凑,底盘离地间隙低,重心稳。 大扭矩低速特性:得益于内置减速,轮毂电机在低转速下可输出极大扭矩(峰值可达8~25 N·m),能轻松驱动30~80kg级底盘,具备良好的爬坡(<5°)和越障(过坎)能力,且低速运行平稳无顿挫。

零代码上手!用 Rokid 灵珠平台,5 步搭建专属旅游 AR 智能体

零代码上手!用 Rokid 灵珠平台,5 步搭建专属旅游 AR 智能体

零代码上手!用 Rokid 灵珠平台,5 步搭建专属旅游 AR 智能体 灵珠平台简介 okid 自研 AI 开发平台,基于多模态大模型与轻量化架构,打造零门槛、全栈化 AI 开发体系。平台提供可视化编排、预置能力组件,支持原型到云端、端侧一站式敏捷部署,并深度适配 Rokid Glasses 智能眼镜,通过专属硬件接口与低功耗优化,实现 AI 应用高效端侧落地,助力开发者快速打造视觉识别、语音交互等穿戴式 AI 应用,拓展 AI + 物理世界的交互边界可视化编排工具,拖拽式快速搭建应用预置丰富能力组件库,涵盖对话引擎、视觉识别等核心模块支持从原型设计到云端、端侧的一站式敏捷部署提供设备专属适配接口,实现硬件深度协同搭载低功耗运行优化方案,保障端侧持久稳定运行 实战:搭建旅游类AR智能体 1、进入灵珠平台 登录灵珠平台后,你将看到简洁直观的工作台界面 点击创建智能体按钮,

宇树G1机器人强化学习训练完整实战教程

宇树G1机器人强化学习训练完整实战教程

0. 前言 人形机器人的运动控制一直是机器人领域的重要挑战,而强化学习为解决这一问题提供了强有力的工具。本教程将基于宇树G1人形机器人,从基础的强化学习环境搭建开始,逐步深入到高自由度模型的训练配置、奖励函数设计与优化,最终实现复杂动作的训练控制。作者看到一个很棒的系列,所以针对性的对文章内容进行了整理和二次理解,方便大家更好的阅读《不同自由度的宇树G1机器人强化学习训练配置及运行实战 + RSL-RL代码库问题修复》、《宇树G1机器人强化学习训练奖励函数代码架构 + 创建新的奖励函数(1)》、《RL指标分析与看板应用 — 宇树G1机器人高自由度模型强化学习训练实战(3)》、《调参解析 — 宇树G1机器人高自由度模型强化学习训练实战(4)》、《舞蹈训练?手撕奖励函数 — 宇树G1机器人高自由度模型强化学习训练实战(5)》。 1. 强化学习训练环境配置 1.1 基础环境搭建 宇树机器人的强化学习训练基于Isaac Gym物理仿真环境和RSL-RL强化学习框架。首先需要确保这两个核心组件正确安装和配置。 在开始训练之前,我们通过简单的命令来启动12自由度G1机器人的基础训练:

Seedance 2.0 × 飞书机器人深度集成:从API鉴权到上下文感知对话,97%开发者忽略的4个关键配置陷阱

第一章:Seedance 2.0 × 飞书机器人深度集成:从API鉴权到上下文感知对话,97%开发者忽略的4个关键配置陷阱 飞书机器人Token与Encrypt Key的双向校验陷阱 飞书机器人启用「事件订阅」后,必须同时验证 token(用于签名比对)与 encrypt_key(用于消息解密),但多数开发者仅配置了前者。若 encrypt_key 为空或未在服务端正确初始化,飞书将返回 400 Bad Request,且错误日志不显式提示原因。 // Go 示例:初始化飞书加解密器(需显式传入 encrypt_key) cipher, err := larksuite.NewAesCipher("your_encrypt_key_here") // ⚠️ 此处不可省略 if err != nil