使用BeautifulSoup爬取招聘网站,如何修复JSON内部双引号解析错误?
解决JSON解析错误:不要用正则破坏原始结构化数据
你的问题根源在于错误地用正则提前清理了JSON字符串,反而破坏了它的合法结构——尤其是你把JSON里的转义反斜杠\直接替换为空,导致原本被转义的内部引号(比如"quality control")变成了未转义的状态,直接打破了JSON的语法规则,触发JSONDecodeError。
其实application/ld+json本身就是标准的结构化数据,网站输出的内容大概率是合法的JSON,不需要先做一堆正则清理。正确的做法是:先解析JSON,再针对具体字段清理内容,而不是反过来。
修正后的代码示例
from bs4 import BeautifulSoup from urllib.request import urlopen import json # 获取页面内容 uClient = urlopen("http://www.ethiojobs.net/display-job/227974/Program-Manager---Mental-Health%2C-Child-Care-Gender-%26-Protection.html") page_html = uClient.read() uClient.close() listing_soup = BeautifulSoup(page_html, "lxml") # 直接获取script标签的完整文本,不要用.strings(可能拆分内容) json_script = listing_soup.find("script", {"type":"application/ld+json"}).text try: # 优先尝试直接解析原始JSON json_listing = json.loads(json_script) except json.JSONDecodeError: # 如果网站确实输出不规范的JSON,用更宽容的解析库(需要先安装:pip install json5) import json5 json_listing = json5.loads(json_script) # 解析完成后,再针对具体字段清理HTML内容(比如职位描述) if "description" in json_listing: # 用BeautifulSoup清理HTML标签,比正则可靠得多 clean_desc = BeautifulSoup(json_listing["description"], "lxml").get_text(strip=True) # 可以再做一些轻量的字符替换,比如特殊符号 clean_desc = clean_desc.replace("\u2019", "'").replace("\u25cf", " -") json_listing["description"] = clean_desc # 现在可以正常使用解析后的JSON数据了 print(json_listing["title"]) print(json_listing["description"])
为什么之前的方法会出错?
- 错误提取内容:用
.strings会把脚本内容拆分成多个文本片段,join后可能丢失或打乱原始结构,.text才是获取完整脚本内容的正确方式。 - 正则破坏JSON结构:你的正则把
\\替换为空,而JSON里的\"是用来表示字符串内部引号的转义语法,去掉反斜杠后变成",直接导致JSON语法错误。 - 提前清理HTML标签:在JSON字符串阶段用正则清理HTML标签非常危险,很容易误删JSON的语法字符(比如引号、逗号),应该在解析成JSON对象后,针对具体字段处理。
额外建议
- 尽量信任
application/ld+json的合法性:这类标签是为搜索引擎准备的结构化数据,网站通常会保证其格式正确,你的问题几乎都是正则过度清理导致的。 - 避免用正则处理HTML/JSON:正则不是处理结构化数据的最佳工具,BeautifulSoup(处理HTML)和JSON解析库(处理JSON)才是专业的选择。
- 遇到不规范JSON时用宽容解析库:如果确实遇到网站输出的JSON有语法问题,
json5可以解析一些非标准的格式(比如未转义的内部引号、末尾逗号等)。
内容的提问来源于stack exchange,提问作者Yacob
相关产品推荐
相关产品推荐

