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

如何用Python爬取iframe内动态表格的全量30万行数据

中国海关站点30万全量数据Python抓取可行方案

核心实现逻辑

别上来就用自动化工具逐页翻200条,1500页爬完效率极低还容易被封。这类政府统计站点的导出、分页限制基本都是前端写死的,后端很少做严格的参数拦截,只要维持住校验通过的合法会话,直接改接口参数就能拿全量数据。

  • 第一步:会话初始化与校验
    用requests.Session()创建持久化会话,所有请求都走这个会话自动带cookie,不要用零散的requests请求。
    先访问目标站点拿初始cookie,再模拟两次维度选择的请求——打开浏览器开发者工具,正常点两次选维度的按钮,看Network里对应的请求地址、参数,直接照搬就行,请求头里的UA、Referer要和你浏览器里的一致,别用requests默认的UA,容易被拦。
    验证码部分不用搞复杂的深度学习方案,两种处理方式:要么用ddddocr库做本地识别,这类站点的验证码都是简单的数字字母组合,准确率能到95%以上;要是识别报错率高,就写几行代码把拿到的验证码图片弹出来手动输入,一次校验通过后,cookie有效期内不用再重复验。

    注意:验证码图片的请求必须用同一个Session发,不然验证码和会话不绑定,输对了也会提示校验失败。

  • 第二步:定位数据接口
    校验通过进入数据表格页后,在开发者工具里过滤XHR/Fetch请求,手动翻一页表格,找返回表格数据的接口,重点看参数里的分页字段,一般是pageNum、pageSize、offset、limit这类命名。自带导出功能限1万条,本质是前端调用导出接口时把limit参数写死成了10000,后端大概率没卡这个值。
  • 第三步:全量数据拉取,两种方案按需选
    1. 接口直连方案(效率最高,优先选)
      找到数据查询或者CSV导出的接口,先试直接把limit参数改成300000发请求,如果能正常返回全量就直接存;如果后端做了单次请求上限拦截,就分30次请求,每次偏移1万条拉1万条数据,最后本地拼接成完整文件就行,比逐页爬200条快十多倍。
      参考代码片段:
      import requests
      import csv
      import ddddocr
      
      # 初始化持久会话
      sess = requests.Session()
      sess.headers.update({
          "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
          "Referer": "http://43.248.49.97/indexEn"
      })
      
      # 访问首页拿初始cookie
      sess.get("http://43.248.49.97/indexEn")
      
      # 验证码识别,接口地址替换成你抓包拿到的实际地址
      captcha_resp = sess.get("http://43.248.49.97/xxx/captcha")
      ocr = ddddocr.DdddOcr(show_ad=False)
      captcha_code = ocr.classification(captcha_resp.content)
      # 要是识别不准就把下面这行放开,手动输验证码
      # from PIL import Image
      # import io
      # Image.open(io.BytesIO(captcha_resp.content)).show()
      # captcha_code = input("请输入验证码:")
      
      # 提交两次维度选择+验证码校验,接口地址和参数替换成抓包拿到的内容
      # sess.post("http://43.248.49.97/xxx/dim1", data={"dim_code": "你选的一级维度值"})
      # sess.post("http://43.248.49.97/xxx/dim2", data={"dim_code": "你选的二级维度值", "captcha": captcha_code})
      
      # 分块拉取全量数据
      all_rows = []
      chunk_size = 10000 # 按站点自带的单次导出上限分块,避免触发拦截
      total_count = 300000
      for offset in range(0, total_count, chunk_size):
          resp = sess.post(
              "http://43.248.49.97/xxx/data/list", # 替换成实际数据接口地址
              data={
                  "offset": offset,
                  "limit": chunk_size,
                  # 其余筛选参数完全照搬浏览器正常请求的内容
              }
          )
          # 按接口实际返回格式解析数据
          chunk_rows = resp.json()["data"]["records"]
          all_rows.extend(chunk_rows)
      
      # 保存为本地CSV,用utf-8-sig编码避免Excel打开乱码
      with open("customs_full_data.csv", "w", encoding="utf-8-sig", newline="") as f:
          writer = csv.DictWriter(f, fieldnames=all_rows[0].keys())
          writer.writeheader()
          writer.writerows(all_rows)
      
    2. 浏览器自动化兜底方案(适合接口有动态签名不好逆向的情况)
      要是接口参数带动态加密签名,逆向成本太高,就用playwright做自动化模拟,比Selenium稳定不用手动配浏览器驱动。启动浏览器后手动/自动过验证码,选好维度,定位到iframe里的表格和分页按钮,自动翻页抓取每一页的表格内容追加到结果集。1500页的话每次翻页加1-2秒的随机延时,半小时左右就能爬完,不会触发反爬。
  • 避坑提醒
    • 所有请求必须在同一个会话上下文里,cookie丢了就会跳回验证页面,之前的操作全白费
    • 别一开始就把请求块大小设成30万,很容易触发后端超时或者IP拦截,按1万的块长拉最稳
    • 保存文件别用utf-8编码,不然Excel打开中文全是乱码,用utf-8-sig
    • 爬的时候别请求太频繁,政府站点服务器带宽和性能都一般,频率太高容易把IP封了

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 20:09:25