网页抓取时遭遇JSONDecodeError错误,寻求解决方案
解决Wayback Machine API调用时的JSONDecodeError问题
我完全懂你这种头疼的感觉——之前好好运行的代码突然报错,自己还没改任何东西,确实摸不着头脑。咱们一步步拆解问题、修复它:
问题重现
你原本想用这段代码通过Wayback Machine的元数据API获取站点最早存档年份:
import json import requests my_list=['www.expedia.it', 'www.fortuneita.com', 'www.finanzaonline.com', 'it-it.facebook.com', 'www.capterra.it', 'www.sportmediaset.mediaset.it', 'www.incredibile.net', 'www.newsrimini.it', 'web.tiscali.it', 'www.dettiescritti.com'] api_url = 'https://web.archive.org/__wb/search/metadata' for url in my_list: data = requests.get(api_url, params={'q': url}).json() min_year = min(data['urls'], key=int)
结果触发了这个错误:
JSONDecodeError: Expecting value: line 1 column 1 (char 0)
错误原因分析
这个错误的核心是API返回的不是有效的JSON数据,大概率是这几个原因导致的:
- Wayback Machine有请求频率限制,你的循环请求太密集,触发了限流,服务器返回了HTML格式的错误页(比如429 Too Many Requests)
- 部分域名没有存档数据,API返回了空或者非JSON格式的响应
- 请求没有携带浏览器标识的请求头,被服务器识别为爬虫,返回了异常内容
修复方案
针对这些问题,我们给代码加几个关键改进:
1. 先校验响应状态,避免直接解析无效内容
在调用.json()之前,先判断响应是否成功(状态码200),失败时打印响应内容方便排查。
2. 添加浏览器请求头,规避爬虫检测
给请求加上模拟浏览器的User-Agent,让请求看起来更像正常用户访问。
3. 增加请求延迟,避免触发限流
在循环中加入短暂延迟,控制请求频率,降低被拦截的概率。
4. 处理空结果场景
如果站点没有存档数据,提前判断并跳过,避免min()函数报错。
完整修复后的代码
import json import requests import time my_list=['www.expedia.it', 'www.fortuneita.com', 'www.finanzaonline.com', 'it-it.facebook.com', 'www.capterra.it', 'www.sportmediaset.mediaset.it', 'www.incredibile.net', 'www.newsrimini.it', 'web.tiscali.it', 'www.dettiescritti.com'] api_url = 'https://web.archive.org/__wb/search/metadata' # 模拟浏览器请求头,避免被识别为爬虫 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' } for url in my_list: try: # 发送带请求头的请求 response = requests.get(api_url, params={'q': url}, headers=headers) # 检查响应状态,非200则抛出异常 response.raise_for_status() data = response.json() # 检查是否存在有效存档数据 if 'urls' in data and data['urls']: min_year = min(data['urls'], key=int) print(f"{url} 的最早存档年份: {min_year}") else: print(f"{url} 未找到存档数据") # 每次请求后延迟1秒,避免触发限流 time.sleep(1) except requests.exceptions.RequestException as e: print(f"请求 {url} 时出错: {str(e)}") # 打印部分响应内容,方便排查问题 if response.content: print(f"响应内容预览: {response.text[:200]}...") except json.JSONDecodeError: print(f"{url} 返回的内容不是有效的JSON格式") print(f"响应内容预览: {response.text[:200]}...")
额外提示
- Wayback Machine没有公开的限流规则,但保持1秒/次的请求频率基本不会被拦截,如果还是遇到问题,可以适当延长延迟时间
- 部分站点可能确实没有被Wayback Machine存档,代码里已经做了空值处理,不会中断整个循环
内容的提问来源于stack exchange,提问作者user14289862
相关产品推荐
相关产品推荐

