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

无公开API时如何抓取DCRA政府站点动态加载的承包商数据

华盛顿特区通用承包商数据爬取操作指导

第一步:提取实际数据接口的请求信息

打开目标站点,按F12调出开发者工具,切换到「Network」标签,筛选「XHR」类型的请求。手动点击站点的翻页按钮,找到翻页时触发的对应请求,记录以下信息:

  • 请求的实际URL(注意不是浏览器地址栏的页面URL,是XHR请求的接口地址)
  • 请求方法(GET/POST,这类查询站点一般是POST)
  • 请求头中必要字段:User-Agent、Content-Type、Referer,如果有X-CSRFToken类的校验字段也一并记录
  • 请求参数:GET请求的URL参数、POST请求的请求体参数,重点找页码参数、每页返回条数参数、查询类型参数(对应你要爬的General Contractor类型)

第二步:验证接口可独立调用

  • 右键你找到的XHR请求,选择「Copy」→「Copy as cURL (bash)」,把内容转换为Python requests代码,也可以手动按照记录的参数写请求代码
  • 修改请求参数中的页码值,发送测试请求,看是否能正常拿到其他页的数据。如果接口支持调整每页返回条数,尽量调到最大值(比如从默认10条调到100条),减少后续请求次数
  • 如果返回403/401错误,检查是否漏了校验头或者cookie,用requests.Session()创建会话,先访问一次站点首页获取有效cookie后再调用数据接口,可解决大部分会话校验问题

第三步:编写批量爬取脚本

以下是最简Python示例逻辑,你可以根据自己拿到的接口参数修改:

import requests
import time
import csv

# 替换为你拿到的实际接口地址
api_url = "https://govservices.dcra.dc.gov/xxx/xxx"
session = requests.Session()
# 先请求首页获取会话cookie
session.get("https://govservices.dcra.dc.gov/contractorratingsystem/BuildingProfessionals/BuildingProfessional?profType=General%20Contractor&profName=")
# 替换为你拿到的实际请求头
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",
    "Content-Type": "application/json"
}
all_data = []
# 先请求第一页获取总条数,计算总页数
# 替换为实际的第一页请求参数
first_page_data = {
    "page": 1,
    "size": 100,
    "profType": "General Contractor"
}
resp = session.post(api_url, json=first_page_data, headers=headers)
resp_json = resp.json()
# 替换为实际返回结构里的总页数字段
total_pages = resp_json["data"]["totalPages"]
all_data.extend(resp_json["data"]["list"])

# 从第二页开始循环爬取
for page in range(2, total_pages + 1):
    time.sleep(2) # 控制请求频率,避免被封IP
    page_data = first_page_data.copy()
    page_data["page"] = page
    try:
        resp = session.post(api_url, json=page_data, headers=headers)
        resp.raise_for_status()
        current_page_data = resp.json()
        all_data.extend(current_page_data["data"]["list"])
        print(f"已爬取第{page}/{total_pages}页")
    except Exception as e:
        print(f"第{page}页爬取失败,错误:{e}")
        # 可自行添加失败重试逻辑

# 保存为csv文件
with open("dc_general_contractors.csv", "w", encoding="utf-8", newline="") as f:
    # 替换为实际的字段名
    writer = csv.DictWriter(f, fieldnames=all_data[0].keys())
    writer.writeheader()
    writer.writerows(all_data)

注意事项

  • 不要爬取过快,每次请求间隔1-2秒,避免给站点服务器造成压力同时防止IP被封禁
  • 爬取过程中如果出现验证码或者访问拦截,可以适当增加间隔时间,或者更换IP后继续
  • 拿到数据后建议根据承包商唯一ID字段去重,避免翻页时出现的重复数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 01:24:01