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

Python爬取SEC filings循环遍历CIK时随机报JSONDecodeError 单请求正常

问题根因与修复方案

核心原因

结合你描述的“之前能正常运行、报错位置随机、单独请求报错URL就不会出问题”的特征,这个异常不是代码逻辑bug,是SEC平台的访问限流与拦截机制触发导致的:

  • SEC的EDGAR系统对单IP的请求频率有严格限制,当你循环连续发起请求时,短时间内请求密度超过平台阈值,服务器会直接返回空响应体,或者返回一段无JSON结构的拦截提示HTML。这个时候调用response.json()会因为拿到的内容开头不符合JSON语法,直接抛出Expecting value: line 1 column 1 (char 0)的错误。
  • 报错位置随机的特性,背后的逻辑是限流计数动态波动:和你本地网络延迟、当前SEC节点的负载、同IP其他请求的密度都有关系,有时候连续发3个请求就会触发拦截,有时候发10个才触发,没有固定规律。
  • 单独提取报错URL就能正常访问的原因,是单独请求时你和上一次请求已经间隔了数秒,IP的限流计数已经过了生效窗口,服务器自然会正常返回JSON内容。

落地修复步骤

  1. 配置合规的请求头,通过SEC的基础校验
    SEC明确要求访问EDGAR接口必须携带可标识访问者身份的User-Agent,不能直接使用requests默认的python-requests/xxx标识,否则很容易被判定为恶意爬虫直接拦截:
    headers = {
        "User-Agent": "你的姓名 你的联系邮箱@example.com",
        "Accept-Encoding": "gzip, deflate"
    }
    
    发起请求时把headers传入参数即可。
  2. 给循环请求增加随机延迟,压低请求频率
    每个请求之间增加0.2-0.8秒的随机休眠,把整体请求频率控制在SEC要求的10次/秒阈值以内,从根源上避开限流拦截:
    import time
    import random
    
    for cik_number in ciks['public_ciks']:
        url = f'{base_url}{cik_number}/index.json'
        time.sleep(random.uniform(0.2, 0.8))
        response = requests.get(url, headers=headers, timeout=10)
    
  3. 增加容错校验,避免偶发拦截打断全量循环
    不要直接调用response.json(),在解析前先做基础合法性校验,遇到拦截场景直接跳过当前请求即可:
    from requests import JSONDecodeError
    
    # 非200状态码直接跳过
    if response.status_code != 200:
        continue
    # 空响应直接跳过
    if len(response.content) == 0:
        continue
    # JSON解析失败直接跳过
    try:
        decoded_content = response.json()
    except JSONDecodeError:
        continue
    
  4. 删除冗余的无效解析逻辑
    原代码中拿到响应后用BeautifulSoup做lxml解析的逻辑,后续完全没有用到soup对象,可以直接删掉,减少不必要的计算消耗。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 23:15:03