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

Python爬取sec.gov的XML文件无法转为正常字符串问题排查

问题原因

你遇到的报错和乱码字节来自三个核心问题:

  • 你看到的b'\x1f\x8b'开头的字节是gzip格式的压缩响应:你在请求头里声明了接受gzip/deflate压缩的返回内容,但urllib.request.urlopen默认不会自动解压这类压缩数据,直接读取拿到的是压缩后的二进制包,不是原始XML文本。
  • ElementTreeAPI使用逻辑错误:ElementTree.tostring()的作用是把已经解析完成的XML元素对象序列化为字符串,你直接把原始字节作为参数传入,字节对象不存在元素才有的iter属性,自然抛出属性错误。
  • 额外代码问题:你定义了两次Cache-Control请求头,后者会覆盖前者;且SEC官方要求请求的User-Agent必须填写可联系的真实邮箱,占位符格式的UA会被直接拦截。
修复方法

两种处理路径可选:

  • 最简方案:直接删除请求头里的Accept-Encoding配置,让服务器返回未压缩的明文XML内容,省去手动解压步骤。
  • 保留压缩支持(节省传输带宽):读取响应后先判断压缩格式,手动解压后再做XML解析。

修复后的可运行代码如下:

#!/usr/bin/python3
import gzip
from urllib.request import Request, urlopen
from xml.etree import ElementTree
from time import sleep

def parse_finance_page():
    target_url = "https://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&CIK=0001430306&type=&dateb=&owner=include&start=0&count=40&output=atom"
    headers = {
        "Accept-Language":"en-GB,en;q=0.9,en-US;q=0.8,ml;q=0.7",
        "Connection":"keep-alive",
        "Pragma":"no-cache",
        "Host":"www.sec.gov",
        "Referer":"https://www.sec.gov",
        "Upgrade-Insecure-Requests":"1",
        "User-Agent":"替换为你的真实联系邮箱@xxx.com"
    }

    for retries in range(5):
        try:
            request = Request(target_url, headers=headers)
            with urlopen(request) as resp:
                raw_content = resp.read()
            # 识别gzip压缩内容自动解压
            if raw_content[:2] == b'\x1f\x8b':
                raw_content = gzip.decompress(raw_content)
            # 正确解析流程:先将原始字节解析为XML元素对象
            xml_root = ElementTree.fromstring(raw_content)
            # 再序列化为完整XML字符串
            xml_string = ElementTree.tostring(xml_root, encoding='unicode')
            print(xml_string)
            break
        except Exception as e:
            print(f"第{retries+1}次请求失败,错误信息:{e}")
            sleep(1)
            continue

if __name__ == "__main__":
    parse_finance_page()
优化建议
  • 避免用html、xml这类和导入模块同名的变量名,防止覆盖模块引用引发异常。
  • SEC接口有严格的速率限制,两次请求间隔至少保持1秒,高频请求会被封禁IP。
  • 如果不想手动处理压缩、编码问题,可以直接用requests库,它默认自动处理gzip/deflate解压、编码适配,代码会更简洁:
import requests
from xml.etree import ElementTree
from time import sleep

headers = {"User-Agent": "替换为你的真实联系邮箱@xxx.com"}
target_url = "https://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&CIK=0001430306&type=&dateb=&owner=include&start=0&count=40&output=atom"

for i in range(5):
    try:
        resp = requests.get(target_url, headers=headers, timeout=10)
        resp.raise_for_status()
        xml_root = ElementTree.fromstring(resp.text)
        xml_string = ElementTree.tostring(xml_root, encoding='unicode')
        print(xml_string)
        break
    except Exception as e:
        print(f"请求失败:{e}")
        sleep(1)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 18:09:20