如何用Scrapy提取HTML script标签内的JSON数据并转换为Python字典
问题原因
- 提取内容错误:调用
.get()获取到的是完整的<script>标签HTML字符串,包含标签本身的代码,不是标签内部的JSON纯文本,直接传入json.loads()会因为格式不符合JSON规范解析失败。 - 正则匹配逻辑错误:
\{[^}]*\}的匹配逻辑是遇到第一个}就终止匹配,无法适配JSON内部有嵌套大括号的场景;同时之前写的正则匹配规则没有匹配script标签的type属性,完全匹配不到目标标签内容。
正确解决方案
方法1:直接提取标签内文本(推荐)
直接用Scrapy选择器的::text伪元素提取标签内部纯文本,无需手动处理标签和正则匹配:
import scrapy import json class SomeSpider(scrapy.Spider): name = 'test' start_urls = [ '替换成你的目标URL' ] def parse(self, response, **kwargs): # 增加type属性筛选,避免匹配到其他script标签,同时提取标签内文本 json_text = response.css('div.rich-snippet script[type="application/ld+json"]::text').get().strip() # 解析为Python字典 json_data = json.loads(json_text) # 按需返回处理后的数据 yield json_data
方法2:正则匹配方案(仅当第一种方法失效时使用)
如果确实需要用正则匹配,要修改匹配规则适配嵌套大括号和标签属性:
# 先获取完整的标签字符串 script_str = response.css('div.rich-snippet script[type="application/ld+json"]').get() # 匹配最外层大括号包裹的所有内容,支持嵌套结构 json_text = response.css('div.rich-snippet script[type="application/ld+json"]').re(r'<script[^>]*>([\s\S]*)</script>')[0].strip() json_data = json.loads(json_text)
注意事项
- 如果页面存在多个
application/ld+json标签,把.get()替换为.getall()遍历处理每一个标签即可。 - 部分网站的JSON内容可能存在Unicode转义或者多余的换行符,
strip()方法可以处理大部分首尾空白问题,特殊场景可以额外做字符串清洗。
内容的提问来源于stack exchange,提问作者zoommer
相关产品推荐
相关产品推荐

