如何从网页中安全提取并解析嵌入的 JSON 数据(如 App = {…})-Python教程

本文介绍如何从 html 页面的 `

在现代动态网站中,许多新闻列表、产品数据或配置信息并非通过传统 DOM 元素渲染,而是以 JavaScript 对象字面量(如 App = { … }; 或 window.DATA = {…};)的形式内联在

以下是一个健壮、通用的解析流程,适用于 App = {…}; 类型的嵌入式数据:

✅ 步骤详解与推荐代码

import requests
from bs4 import BeautifulSoup
import json
import re

def extract_json_from_script(html_content: str, var_name: str = "App") -> dict:
    """
    从 HTML 文本中提取指定变量名的 JS 对象,并解析为 Python 字典。

    Args:
        html_content: 完整 HTML 字符串
        var_name: 目标 JS 变量名(默认 'App')

    Returns:
        解析后的字典对象

    Raises:
        ValueError: 未找到变量或 JSON 格式无效
    """
    soup = BeautifulSoup(html_content, "html.parser")

    # 方法1:精确匹配 script 标签中包含 "var_name = {" 的文本节点(推荐)
    script_tag = soup.find("script", string=re.compile(rf"{var_name}\s*=\s*\{{"))
    if not script_tag:
        raise ValueError(f"未找到包含 '{var_name} = {{' 的 script 标签")

    script_text = script_tag.string

    # 使用正则提取最外层 { } 包裹的 JSON 内容(支持嵌套)
    # 注意:此正则可处理多层嵌套花括号,避免被内部 `{` 误截断
    match = re.search(rf"{var_name}\s*=\s*(\{{(?:[^{{}}]|(?R))*\}});", script_text, re.DOTALL | re.VERBOSE)
    if not match:
        # 回退方案:尝试简单匹配到第一个完整闭合的 }
        match = re.search(rf"{var_name}\s*=\s*(\{{.*?\}});", script_text, re.DOTALL)

    if not match:
        raise ValueError(f"无法从 script 中提取有效的 {var_name} JSON 对象")

    json_str = match.group(1)

    try:
        return json.loads(json_str)
    except json.JSONDecodeError as e:
        raise ValueError(f"JSON 解析失败:{e.msg} (位置: {e.pos})\n上下文: {json_str[max(0, e.pos-30):e.pos+30]}")

# 使用示例
if __name__ == "__main__":
    url = "https://polymetalinternational.com/en/investors-and-media/news/press-releases/"
    response = requests.get(url, timeout=10)
    response.raise_for_status()

    try:
        app_data = extract_json_from_script(response.text, "App")

        # 提取新闻标题列表(路径根据实际 JSON 结构调整)
        press_items = app_data.get("components", {}).get("press-release", {}).get("items", [])

        print(f"共获取 {len(press_items)} 条新闻:\n")
        for i, item in enumerate(press_items[:5], 1):  # 仅打印前5条示例
            name = item.get("name", "N/A")
            date_ts = item.get("date", 0)
            link = item.get("link", "")
            themes = ", ".join(item.get("theme", []))
            print(f"{i}. [{name}] ({themes}) — {date_ts} → {link}")

    except Exception as e:
        print(f"解析失败:{e}")

⚠️ 关键注意事项

  • 不要使用 str.replace() 替换 null/false:JS 的 null 和 Python 的 None 语义不同,且 json.loads() 本身不接受 null;但更重要的是,盲目全局替换(如 ‘null’.replace(‘null’, ‘None’))会污染真实字段值(例如 “filename”: “null_report.pdf” 会被错误修改)。
  • 避免硬编码切片(如 [:-1] 或 split(“};”)[0]):原始答案中 app_content.split(“};”)[0] + “}” 在存在多层嵌套或注释时极易失效(如 {“a”: {“b”: {}}}; 中 }; 出现在内部)。正则递归匹配((?R))或使用 ast.literal_eval() 是更可靠的选择(见下文备选方案)。
  • 处理编码与特殊字符:网页返回内容需确保正确解码(response.encoding 或 response.content.decode(“utf-8”)),尤其当页面含 Unicode(如俄文 \u041f\u0440\u0435\u0441\u0441-\u0440\u0435\u043b\u0438\u0437\u044b)时,json.loads() 原生支持 UTF-8,无需额外解码。
  • 异常防御:始终检查 HTTP 状态码、

? 备选方案:使用 ast.literal_eval()(适用于纯 JS 对象字面量)

若确认目标内容是无函数、无 undefined、无注释的纯对象字面量(如 App = {“a”: 1, “b”: null};),可借助 ast.literal_eval() 安全执行(比 eval() 安全,仅允许基本字面量):

夏夕资源网专注于CMS网站模板,主流语言整站网站源码下载,网站建设相关教程分享,好用的软件素材整合下载,提供一站式便捷自助服务。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,默认解压密码为"zy.lucklyus.top",如遇到无法解压的请联系管理员!
夏夕资源网-网站模板_免费源码_资源素材 » 如何从网页中安全提取并解析嵌入的 JSON 数据(如 App = {…})-Python教程
在线时间:12:00 - 22:00
关注微信公众号:微信公众号
站长邮箱:[email protected]
  • 运营天数: 1391+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 3994093+
  • 本周更新: 0+
  • 最后更新: 2026-03-16

本站指数

×
  • 运营天数: 1391+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 3994093+
  • 本周更新: 0+
  • 最后更新: 2026-03-16