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

如何使用Python抓取隐藏在按钮后的CSV文件:批量获取加拿大统计局网站500+CSV文件技术问询

批量下载StatCan 2016 Census CSV文件的Python方案

我明白你要处理的是多层链接嵌套的CSV批量下载问题,这种重复性任务用Python自动化完全能搞定。下面是一步步的解决方案,包含完整代码和关键细节说明:

核心流程拆解

整个任务分为三个关键步骤,逐层穿透链接获取最终的CSV文件:

  • 第一步:从初始结果页抓取所有地区详情页的链接
  • 第二步:从每个详情页跳转至对应的下载页面
  • 第三步:从下载页面提取CSV文件的直接下载链接并保存

所需依赖

先安装必要的Python库:

pip install requests beautifulsoup4

完整代码实现

import requests
from bs4 import BeautifulSoup
import os
import time

# 基础配置
BASE_DOMAIN = "https://www12.statcan.gc.ca"
INITIAL_PAGE_PATH = "/census-recensement/2016/dp-pd/prof/search-recherche/lst/results-resultats.cfm?Lang=E&TABID=1&G=1&Geo1=&Code1=&Geo2=&Code2=&GEOCODE=35&type=0#"
DOWNLOAD_DIR = "statcan_2016_census_csvs"

# 创建下载文件夹(不存在则自动创建)
os.makedirs(DOWNLOAD_DIR, exist_ok=True)

# 模拟浏览器请求头,避免被服务器拦截
REQUEST_HEADERS = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"
}

def fetch_detail_page_links():
    """从初始结果页抓取所有地区详情页的链接"""
    response = requests.get(BASE_DOMAIN + INITIAL_PAGE_PATH, headers=REQUEST_HEADERS)
    soup = BeautifulSoup(response.text, "html.parser")
    # 通过页面元素特征定位详情页链接(可根据实际页面结构调整选择器)
    detail_links = []
    for link in soup.select("a[href*='page.cfm']"):
        full_link = BASE_DOMAIN + link.get("href")
        if full_link not in detail_links:
            detail_links.append(full_link)
    print(f"共找到 {len(detail_links)} 个地区详情页链接")
    return detail_links

def get_download_page_url(detail_url):
    """从地区详情页获取下载页面的跳转链接"""
    response = requests.get(detail_url, headers=REQUEST_HEADERS)
    soup = BeautifulSoup(response.text, "html.parser")
    # 定位页面顶部的下载箭头按钮对应的链接
    download_btn = soup.select_one("a[href*='page_Download-Telecharger.cfm']")
    return BASE_DOMAIN + download_btn.get("href") if download_btn else None

def extract_csv_download_link(download_page_url):
    """从下载页面提取选项1的CSV文件直接下载链接"""
    response = requests.get(download_page_url, headers=REQUEST_HEADERS)
    soup = BeautifulSoup(response.text, "html.parser")
    # 定位"选项1"下的CSV下载按钮链接
    csv_btn = soup.select_one("a[href*='.csv']")
    return BASE_DOMAIN + csv_btn.get("href") if csv_btn else None

def save_csv_file(csv_url, file_name):
    """下载并保存CSV文件到指定目录"""
    response = requests.get(csv_url, headers=REQUEST_HEADERS)
    file_path = os.path.join(DOWNLOAD_DIR, file_name)
    with open(file_path, "wb") as file:
        file.write(response.content)
    print(f"已成功保存:{file_name}")

def main():
    detail_links = fetch_detail_page_links()
    for index, detail_url in enumerate(detail_links, 1):
        print(f"\n正在处理第 {index}/{len(detail_links)} 个地区:{detail_url.split('Code1=')[1].split('&')[0]}")
        # 获取下载页面链接
        download_page_url = get_download_page_url(detail_url)
        if not download_page_url:
            print(f"⚠️ 无法找到该地区的下载页面链接,跳过")
            continue
        # 获取CSV下载链接
        csv_download_url = extract_csv_download_link(download_page_url)
        if not csv_download_url:
            print(f"⚠️ 无法找到该地区的CSV下载链接,跳过")
            continue
        # 生成有辨识度的文件名(用地区编码+索引)
        region_code = detail_url.split('Code1=')[1].split('&')[0]
        csv_filename = f"census_2016_{region_code}_{index}.csv"
        # 下载保存文件
        save_csv_file(csv_download_url, csv_filename)
        # 添加延迟,避免请求过于频繁触发反爬机制
        time.sleep(1.5)

if __name__ == "__main__":
    main()

关键注意事项

  • 选择器适配:如果某一步骤无法找到链接,需要打开浏览器开发者工具,重新定位对应元素的CSS选择器(比如调整select或select_one的参数),网页结构可能会有微小变动。
  • 反爬应对:代码中添加了浏览器请求头和请求延迟,如果还是被拦截,可以适当延长time.sleep的时长,或者考虑使用代理IP池。
  • 文件名优化:示例中用地区编码+索引命名文件,你也可以从详情页提取地区名称作为文件名,让文件更易识别(可在fetch_detail_page_links时同步抓取地区名称)。
  • 异常处理:代码包含基础的空值判断,你可以根据需求添加更多异常捕获逻辑(比如请求超时、文件写入失败等)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 20:14:07