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

Scrapy爬取时如何将提取的JavaScript数组转换为合法JSON

Scrapy解析JS数组变量为JSON的解决方案

问题核心

你提取到的内容是JavaScript赋值语句,不是标准JSON格式,直接调用json.loads必然失败,不符合JSON规范的点包括:

  • 每行带有datos[索引] = 的赋值前缀、末尾带JS语句结束符分号;,不是纯数组结构
  • 数组末尾使用了JS支持但JSON不识别的单引号空字符串'',JSON标准仅允许双引号包裹字符串值
  • Scrapy本身没有JS执行能力,无法直接运行这段赋值语句拿到变量值

方案1:正则清洗+标准库json解析(无额外依赖,性能最优)

不需要引入任何第三方JS执行库,通过简单的字符串正则清洗,把内容修正为标准JSON格式后即可直接解析,适合大规模数据爬取场景:

import re
import json

# raw_content为你从页面提取到的包含所有datos行的原始字符串
raw_content = """
datos[0] = ["12345","3M YELLOW CAT5E CABLE","6.81","1","A","N","N","N","N","N",0,0,0,0,0,"0","0","0","0","0","P","001-0030","12","40K8957","28396","250","Due: 30-12-1899",0.0000,1,"",''];
datos[1] = ["12346","3M GREEN CAT5E CABLE","7.81","1","A","N","N","N","N","N",0,0,0,0,0,"0","0","0","0","0","P","001-0030","12","40K8957","28396","250","Due: 30-12-1899",0.0000,1,"",''];
"""

products = []
# 正则匹配等号后、分号前的数组片段
pattern = re.compile(r'=\s*(\[.*?\]);', re.S)
for match in pattern.finditer(raw_content):
    array_str = match.group(1)
    # 替换不合法的单引号空串为JSON支持的双引号空串
    array_str = array_str.replace(",'']", ',""]')
    # 直接解析为Python列表
    item = json.loads(array_str)
    products.append(item)

方案2:正则提取+ast.literal_eval解析(容错性更强)

如果页面返回的JS数组存在更多单引号字符串这类兼容Python语法、但不符合JSON规范的内容,可以用Python标准库ast的literal_eval方法解析,不需要逐点修正格式,同时不存在安全风险:

注意:禁止直接使用内置eval()方法解析页面爬取的不可信内容,会存在远程代码注入风险;ast.literal_eval仅会解析字符串、数字、列表、字典这类字面量结构,无安全隐患。

import re
import ast

raw_content = """你的原始提取字符串"""
products = []
pattern = re.compile(r'=\s*(\[.*?\]);', re.S)
for match in pattern.finditer(raw_content):
    array_str = match.group(1)
    # 可直接识别单引号字符串,无需额外替换
    item = ast.literal_eval(array_str)
    products.append(item)

选型建议

  • 优先选方案1,性能最高,依赖最少,完全匹配你当前的数据格式
  • 如果后续页面返回的JS格式有小幅变动、存在更多单引号场景,再换方案2
  • 不要为了这类简单解析需求引入PyExecJS、Selenium等重量级依赖,会大幅降低爬虫爬取效率,提升部署成本

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 07:30:50