如何用Python抓取美国众议院财务披露网站指定年份的PDF并按Filing筛选?
美国众议院财务披露PDF抓取实现方案
核心思路
该网站的搜索功能通过POST请求提交筛选参数返回结果页面,我们只需模拟这个请求流程,解析页面提取PDF链接,最后批量下载即可。
步骤1:安装依赖库
先安装所需的Python工具库:
pip install requests beautifulsoup4 tqdm
步骤2:完整代码实现
以下是可直接运行的代码,支持按年份筛选,也可指定归档类型(如年度报告):
import requests from bs4 import BeautifulSoup import os import time from tqdm import tqdm # 基础配置 BASE_URL = "https://disclosures-clerk.house.gov" SEARCH_ENDPOINT = "/FinancialDisclosure/ViewMemberSearchResult" HEADERS = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", "Referer": "https://disclosures-clerk.house.gov/FinancialDisclosure" } def fetch_pdf_links(year, filing_type=""): """获取指定年份、归档类型的所有PDF链接""" pdf_links = [] params = { "filingYear": str(year), "filingType": filing_type, # 留空则不筛选归档类型,可选值:Annual/Periodic/Termination等 "lastName": "", "firstName": "", "state": "", "district": "", "office": "", "page": "1" } # 请求第一页 response = requests.post(BASE_URL + SEARCH_ENDPOINT, data=params, headers=HEADERS) response.raise_for_status() soup = BeautifulSoup(response.text, "html.parser") # 提取第一页PDF链接 for link in soup.select("a[href^='/FinancialDisclosure/ViewPDF']"): pdf_links.append(BASE_URL + link["href"]) # 处理分页结果 pagination = soup.select_one(".pagination") if pagination: # 从分页栏提取总页数 total_pages = int(pagination.find_all("li")[-2].text) for page in range(2, total_pages + 1): params["page"] = str(page) time.sleep(1) # 加延时避免触发反爬机制 page_response = requests.post(BASE_URL + SEARCH_ENDPOINT, data=params, headers=HEADERS) page_response.raise_for_status() page_soup = BeautifulSoup(page_response.text, "html.parser") for link in page_soup.select("a[href^='/FinancialDisclosure/ViewPDF']"): pdf_links.append(BASE_URL + link["href"]) return pdf_links def download_pdfs(pdf_links, save_dir): """批量下载PDF到指定目录""" os.makedirs(save_dir, exist_ok=True) for url in tqdm(pdf_links, desc="下载PDF中"): try: time.sleep(0.5) pdf_response = requests.get(url, headers=HEADERS) pdf_response.raise_for_status() # 用链接中的唯一ID作为文件名 file_name = f"disclosure_{url.split('id=')[-1]}.pdf" with open(os.path.join(save_dir, file_name), "wb") as f: f.write(pdf_response.content) except Exception as e: print(f"下载失败 {url}: {str(e)}") if __name__ == "__main__": # 示例:抓取2024年的年度报告PDF target_year = 2024 target_filing_type = "Annual" # 改为""则不筛选归档类型 links = fetch_pdf_links(target_year, target_filing_type) download_pdfs(links, f"house_disclosures_{target_year}") print(f"完成!共抓取{len(links)}份PDF")
关键说明
- 归档类型参数:
filingType的可选值对应网站下拉菜单,可通过查看页面源码的<select>标签获取,常见值包括:- "Annual":年度财务披露报告
- "Periodic":定期更新报告
- "Termination":离职披露报告
- 反爬规避:代码中加入了
time.sleep()控制请求频率,避免短时间内大量请求被封禁IP;如果仍被限制,可增加延时或使用代理。 - 错误处理:下载环节加入了异常捕获,单个PDF下载失败不会中断整个任务,会打印错误信息以便后续排查。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

