You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从HTML的JSON子节点提取数据?解决JSONDecodeError问题

解决Bergzeit网站商品数据提取的JSON解析错误

问题根源

爬取https://www.bergzeit.de/marken/salewa/商品数据时,原代码直接用json.loads解析包含elementsList的脚本报错,核心原因有两个:

  • 目标脚本是JavaScript代码片段,不是纯JSON——它是赋值给window.__initialAppState的对象,开头带window.__initialAppState = ,结尾有;,不符合JSON格式要求。
  • 脚本里存在JSON.parse("\"Salewa\"")这类JS函数调用,JSON规范不允许这种语法结构。

修复步骤与代码

1. 提取脚本中的纯对象内容

先过滤出包含window.__initialAppState的脚本,再用正则截取等号之后、分号之前的对象部分。

2. 兼容JS语法到JSON

把脚本里的JSON.parse调用替换成JSON能识别的字面量值。

3. 解析并提取目标数据

完整代码示例:

import json
import re

# 假设response是Scrapy的响应对象
scripts = response.xpath('//script/text()').getall()

# 定位目标脚本
target_script = next((s for s in scripts if 'window.__initialAppState' in s), None)

if target_script:
    # 截取JS对象部分
    match = re.search(r'window.__initialAppState = ({.*?});', target_script, re.DOTALL)
    if match:
        data_str = match.group(1)
        # 替换JSON.parse调用为JSON兼容值
        data_str = re.sub(r'JSON.parse\("\\"(.*?)\\"\)"', r'"\1"', data_str)
        data_str = re.sub(r'JSON.parse\("null"\)', 'null', data_str)
        
        # 解析JSON
        try:
            app_data = json.loads(data_str)
            # 获取商品列表
            products_list = app_data['modules']['productsListPage']['elementsList']
            
            # 提取所需字段
            for item in products_list:
                product = item['data']
                # 基础信息
                name = product['name']
                current_price = product['price']['current']
                full_url = f"https://www.bergzeit.de{product['url']}"
                
                # 提取颜色和尺寸
                available_colors = []
                available_sizes = []
                for var in product['variations']:
                    if var['colorVariation']:
                        # 筛选可选颜色
                        available_colors = [opt['label'] for opt in var['options'] if opt['isAvailable'] or opt['isAnyAvailable']]
                    else:
                        # 筛选可选尺寸
                        available_sizes = [opt['label'] for opt in var['options'] if opt['isAvailable'] or opt['isAnyAvailable']]
                
                # 输出或存储数据
                print(f"商品名称: {name}")
                print(f"当前价格: {current_price}")
                print(f"商品链接: {full_url}")
                print(f"可选颜色: {', '.join(available_colors) if available_colors else '暂无'}")
                print(f"可选尺寸: {', '.join(available_sizes) if available_sizes else '暂无'}")
                print("------------------------")
        except json.JSONDecodeError as e:
            print(f"解析失败: {str(e)}")
else:
    print("未找到包含商品数据的脚本")

代码说明

  • 用next()快速定位目标脚本,避免无意义遍历。
  • 正则替换处理JS的JSON.parse语法,确保内容符合JSON规范。
  • 从modules.productsListPage.elementsList拿到商品数据,再从variations字段分离颜色和尺寸,筛选出可选的选项。

内容的提问来源于stack exchange,提问作者Vaidas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 15:35:53