导读:本期聚焦于杨子江创作的《如何高效抓取动态加载的网页内容:以BeautifulSoup与XHR请求为例》,敬请观看详情。页面明明在浏览器里能看到数据,用requests拉下来的HTML却是一堆空壳,这是做爬虫时最经典的困惑之一。问题的根源在于大量现代网站依靠JavaScript通过XHR请求异步加载数据,原始HTML里根本没有目标内容。本文将带你理解动态渲染与静态页面的区别,学会用浏览器开发者工具的Network面板定位真实的XHR数据接口,再用Python构造请求直接获取JSON结果,最后结合BeautifulSoup处理少量仍需解析的HTML片段。文中还会对比分析XHR直连与Selenium模拟渲染两种方案的适用场景、性能差异和反爬应对技巧,帮助你用最少的资源稳定抓到想要的数据。

用requests请求一个商品列表页,返回的HTML里只有几个空div,价格、标题、评论数统统不见踪影,但浏览器里明明显示得好好的。这个现象几乎每个写爬虫的人都遇到过。原因很简单:现代网站大量使用JavaScript在页面加载后再通过XHR请求从后端拉取数据,再用脚本填充到DOM里。requests只负责发HTTP请求,不执行JavaScript,自然拿不到这些内容。本文就来拆解这个问题,介绍如何定位XHR接口、直接请求数据,并结合BeautifulSoup完成解析。

如何高效抓取动态加载的网页内容:以BeautifulSoup与XHR请求为例

一、先搞清楚:静态页面与动态加载页面的区别

传统的静态页面,所有内容都直接写在服务器返回的HTML源码里。你用requests拿到响应后,BeautifulSoup一顿解析就能提取出全部数据,这种方式简单可靠,也不容易被反爬针对。

而动态加载页面则不同。服务器返回的初始HTML往往只有一个页面骨架,里面嵌着JavaScript脚本。浏览器执行这些脚本后,会向服务器发送额外的异步请求(也就是XHR,XMLHttpRequest,或者基于fetch API的请求),拿到JSON或HTML片段后再动态插入页面。典型的标志是:在浏览器里右键查看源代码(Ctrl+U)时找不到你在页面上看到的数据,这就是判断一个页面是否动态加载的最快捷方法。

举个例子,某电商平台的商品列表,页面源码里搜不到商品标题,但在Network面板里却能找到一个返回商品数据的接口。遇到这种情况,直接解析初始HTML就是死路一条,必须换思路。

二、用开发者工具定位真实的XHR数据接口

Chrome开发者工具的Network面板是定位XHR接口的核心武器。操作步骤:按F12打开工具,切换到Network标签,筛选类型选择XHR或Fetch,然后刷新页面或触发滚动加载、点击翻页等操作,观察新出现的请求。

重点看这几个字段:请求的URL、请求方法(GET还是POST)、请求参数(Query String Parameters或Form Data)、以及响应内容(Response)。如果响应是一段JSON,里面恰好包含你要抓的数据,恭喜,接口找到了。

一个实用技巧是搜索法:在Network面板的搜索框里输入页面上看到的某个具体数据值(比如某个商品名),工具会帮你定位到包含这个值的请求,比逐个点击请求快得多。另外注意有些接口会带时间戳签名或token参数,这类参数需要进一步分析其生成逻辑,必要时可以先用Selenium拿到初始cookie和token,再切换到requests模式。

三、用Python直接请求接口并解析数据

找到接口后,用requests模拟这个请求即可。通常需要带上合适的请求头,尤其是User-Agent、Referer和Cookie,缺了可能直接返回403或空数据。下面是一个完整示例:

import requests
from bs4 import BeautifulSoup
import json

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
    "Referer": "https://www.ipipp.com/list",
    "Cookie": "sessionid=xxxx"
}

# 直接请求XHR接口,返回JSON数据
url = "https://www.ipipp.com/api/goods/list"
params = {"page": 1, "size": 20, "sort": "sales"}

resp = requests.get(url, headers=headers, params=params, timeout=10)
data = resp.json()

for item in data["result"]:
    print(item["title"], item["price"])

如果接口返回的不是JSON而是HTML片段(有些网站习惯返回渲染好的局部HTML),这时候BeautifulSoup就派上用场了:

# 假设接口返回的是HTML片段
resp = requests.get(url, headers=headers, params=params, timeout=10)
soup = BeautifulSoup(resp.text, "lxml")

# 解析返回的HTML片段
for card in soup.select("div.goods-card"):
    title = card.select_one("span.title").get_text(strip=True)
    price = card.select_one("em.price").get_text(strip=True)
    print(title, price)

两种形态的处理思路都一样:先看响应内容的结构,再决定用json模块还是BeautifulSoup。lxml解析器速度比默认的html.parser快不少,建议安装后优先使用。

四、XHR直连方案与Selenium的取舍

拿到接口后直连请求,优点非常明显:速度快、资源占用低、代码简单、稳定性好。一个requests请求几十毫秒就能完成,而Selenium启动一个浏览器实例要好几秒,内存占用也是数量级的差距。对于大规模抓取任务,能走接口就绝不要开浏览器。

但XHR方案也有短板。一是接口参数可能加密,分析成本高;二是接口没有文档,字段含义靠猜;三是反爬检测可能针对接口做频控和签名校验。而Selenium或Playwright模拟真实浏览器,能执行JavaScript、绕过大部分前端渲染问题,对加密参数的网站反而是更省事的选择。

实践中常见的组合策略是:用Selenium登录并获取cookie,再把cookie塞进requests的会话里做后续批量抓取;或者发现接口签名难以逆向时,退而求其次用headless浏览器渲染页面,再用BeautifulSoup解析渲染后的完整HTML。两者配合,往往能兼顾效率与可行性。

五、稳定性与合规的几点建议

抓取动态页面时,控制请求频率很重要。加上随机延时,比如每次请求间隔1到3秒,避免触发限流。使用Session对象复用TCP连接和cookie,能显著提升效率。遇到返回空数据或状态码异常时,做好重试与日志记录。

import time
import random

session = requests.Session()
session.headers.update(headers)

def fetch_page(page):
    for attempt in range(3):
        try:
            resp = session.get(url, params={"page": page}, timeout=10)
            if resp.status_code == 200:
                return resp.json()
        except requests.RequestException:
            pass
        time.sleep(random.uniform(1, 3))
    return None

最后提醒一点:抓取前先查看目标网站的robots.txt和服务条款,遵守数据获取的边界,不抓取涉及个人隐私的数据,不对服务器造成过大压力。技术本身是中性的,合规使用才能走得长远。掌握XHR分析加BeautifulSoup解析这套组合拳,绝大多数动态页面的数据获取问题都能迎刃而解。

动态网页抓取BeautifulSoupXHR请求修改时间:2026-09-05 00:34:38

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260905/50566.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。