使用BeautifulSoup爬取SEC站点XSD链接多次运行结果不一致问题咨询
核心问题原因
- 未匹配SEC站点的爬取校验规则。SEC要求自动爬取请求必须携带包含个人/机构联系信息的
User-Agent头部,缺失该配置时站点会随机返回截断HTML、403拦截页甚至空响应,直接导致每次拉取到的页面内容不一致,最终解析结果随机波动。 - 链接匹配逻辑错误。现有代码通过匹配链接可见文本(
link.text)中的.xsd后缀筛选目标链接,但SEC索引页的大量XSD链接的可见文本为截断的文件名片段,甚至部分链接文本为空,真实的XSD后缀存储在链接的href属性中,现有逻辑会出现大量漏判。 - 无基础的请求容错与状态校验。代码拿到请求响应后直接解析内容,未校验响应状态、未配置重试机制,遇到临时网络波动、限流拦截时会直接将错误页内容作为有效页面解析,进一步放大结果的随机性。
修正方案
- 配置符合SEC要求的请求头,搭建带自动重试的请求会话,应对临时网络异常:
import requests from bs4 import BeautifulSoup from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry # 替换为你自己的联系信息,必须符合SEC爬取规则要求 HEADERS = { "User-Agent": "学术研究用途 联系邮箱your-email@example.com", "Accept-Encoding": "gzip, deflate" } # 配置3次自动重试,应对临时请求失败 session = requests.Session() retry_rule = Retry( total=3, backoff_factor=1, status_forcelist=[429, 500, 502, 503, 504] ) session.mount("https://", HTTPAdapter(max_retries=retry_rule)) - 修正
getxsd函数的链接匹配逻辑,增加请求状态校验:def getxsd(indexurl): response = session.get(indexurl, headers=HEADERS, timeout=10) # 请求失败直接抛出异常,避免解析错误页内容 response.raise_for_status() soup = BeautifulSoup(response.text, "lxml") xsd_links = [] for a_tag in soup.find_all("a"): href = a_tag.get("href", "") # 直接从href属性匹配.xsd后缀,不受显示文本截断影响 if href.endswith(".xsd"): xsd_links.append(href) return xsd_links - 调整循环调用逻辑,增加异常捕获,避免单页面处理失败中断整个流程:
all_results = [] for filing_url in filings: try: page_links = getxsd(filing_url) all_results.extend(page_links) except Exception as e: print(f"处理页面{filing_url}失败: {str(e)}") print(f"累计提取有效XSD链接数量: {len(all_results)}")
注意:SEC站点对高频爬取的拦截规则较严格,建议每次请求间隔1-2秒,避免IP被临时封禁。
内容的提问来源于stack exchange,提问作者jmaloney13
相关产品推荐
相关产品推荐

