当前位置: 首页 > news >正文

用 Python 一键下载并整合统计年鉴 Excel 文件(自动分类合并版)

用 Python 一键下载并整合统计年鉴 Excel 文件(自动分类合并版)

用 Python 一键下载并整合统计年鉴 Excel 文件(自动分类合并版)


背景介绍

如果你经常做数据分析、论文写作或政府数据整理,可能会遇到这样的问题:

📌 统计年鉴官网上有几十甚至上百个 Excel 文件,需要一个个点开下载,还要手动分类整理,非常耗时。

这篇文章要讲的这段 Python 代码,可以帮你:

  • ✅ 自动抓取网页上的所有 Excel 文件
  • ✅ 批量下载到本地
  • ✅ 按文件名前两位数字自动分类
  • ✅ 自动合并为一个 Excel 文件(每个子类作为一个 Sheet)
  • ✅ 自动跳过已下载文件,避免重复下载

⚠️ 重要提醒:

本代码仅供学习交流使用。
请在合法合规前提下使用,遵守网站数据使用规范和相关法律法规。
不要用于任何商业抓取或违反网站协议的行为。


代码功能说明

这段代码做了三件事:

第一步:抓取 Excel 下载链接

从指定网页中,自动提取所有 .xls.xlsx 文件链接。

第二步:批量下载

自动下载所有 Excel 文件到本地文件夹。

第三步:自动整合

根据文件名前两位数字进行“大类分类”,生成:

01_年鉴.xlsx
02_年鉴.xlsx
03_年鉴.xlsx
...

每个文件中:

  • 不同子类放在不同 sheet 中
  • 自动清理非法字符
  • 自动跳过空文件
  • 自动避免 openpyxl 报错

运行完成后,你会在本地看到:

F:\年鉴├── 2023│   ├── excel│   ├── 01_年鉴.xlsx│   ├── 02_年鉴.xlsx├── 2024

运行环境准备

1️⃣ 安装 Python

推荐安装 Python 3.9 以上版本。

检查是否已安装:

python --version

如果没有安装,请到:

👉 https://www.python.org/downloads/

下载并安装(安装时勾选 Add to PATH)。


2️⃣ 创建项目文件夹

例如:

D:\yearbook_project

在该文件夹中新建:

main.py

把下面的代码复制进去。


3️⃣ 安装依赖库

打开命令行(Win + R → 输入 cmd),执行:

pip install requests pandas beautifulsoup4 openpyxl

这些库的作用(用大白话解释):

  • requests:负责“帮你打开网页”
  • beautifulsoup4:负责“从网页里找下载链接”
  • pandas:负责“读取和写入 Excel”
  • openpyxl:负责“生成 Excel 文件”

详细运行步骤


第一步:修改保存路径

找到代码中的:

base_dir = r"F:\年鉴"

👉 修改为你电脑上的路径,例如:

base_dir = r"D:\yearbook_project\data"

注意:必须是存在的磁盘路径。


第二步:保存代码

保存为:

main.py

第三步:运行代码

在项目目录中执行:

python main.py

第四步:观察运行过程

终端会看到类似输出:

[INFO] 2023 年抓取 Excel 链接...
[INFO] 2023 年发现 86 个 Excel 文件
[OK] 下载成功: ...
[OK] 01_年鉴.xlsx 已生成

第五步:验证结果

打开你设置的目录:

D:\yearbook_project\data

你会看到:

  • 每个年份一个文件夹
  • 每个大类一个整合好的 Excel 文件

打开 Excel,可以看到多个 Sheet。


核心代码解析(新手能看懂版)

下面是完整代码(已去除任何私人信息,可直接运行):

import os
import re
import requests
import pandas as pd
from bs4 import BeautifulSoup
from collections import defaultdict# ================= 配置 =================
base_dir = r"D:\【your_folder】"
years = [2023, 2024]
base_urls = {2023: "https://oss.henan.gov.cn/sbgt-wztipt/attachment/hntjj/hntj/lib/tjnj/2023nj/zk/lefte.htm",2024: "https://oss.henan.gov.cn/sbgt-wztipt/attachment/hntjj/hntj/lib/tjnj/2024nj/zk/indexce.htm"
}# ================= 工具函数 =================
def get_excel_links(url, year):"""解析页面,返回所有 Excel 文件的完整 URL 列表"""try:resp = requests.get(url, timeout=20)resp.raise_for_status()resp.encoding = 'gb2312'except Exception as e:print(f"[ERROR] 获取网页失败: {url} ({e})")return []soup = BeautifulSoup(resp.text, "html.parser")links = []for a in soup.find_all('a', href=True):href = a['href']if href.lower().endswith(('.xls', '.xlsx')):if href.startswith("http"):links.append(href)else:base = f"https://oss.henan.gov.cn/sbgt-wztipt/attachment/hntjj/hntj/lib/tjnj/{year}nj/zk/"links.append(base + href.lstrip('./'))return linksdef download_file(url, save_path):"""下载文件,如果已存在则跳过"""if os.path.exists(save_path) and os.path.getsize(save_path) > 0:print(f"[SKIP] 已存在: {save_path}")returntry:resp = requests.get(url, timeout=30)resp.raise_for_status()with open(save_path, 'wb') as f:f.write(resp.content)print(f"[OK] 下载成功: {save_path}")except Exception as e:print(f"[ERROR] 下载失败: {save_path} ({e})")def clean_and_merge_by_category(year_folder, output_dir):excel_files = [f for f in os.listdir(year_folder) if f.lower().endswith(('.xls', '.xlsx'))]if not excel_files:print(f"[INFO] 没有 Excel 文件可整合: {year_folder}")returncategory_dict = defaultdict(list)# 这里是“按文件名前两位分组”for f in excel_files:match = re.match(r'(\d{2})(\d{2})', f)if not match:print(f"[WARN] 文件名不符合规则,跳过: {f}")continuemain_cat, sub_cat = match.groups()category_dict[main_cat].append((f, sub_cat))os.makedirs(output_dir, exist_ok=True)for main_cat, files in category_dict.items():sheets_to_write = []for fname, sub_cat in files:path = os.path.join(year_folder, fname)try:with pd.ExcelFile(path) as xl:for sheet_name in xl.sheet_names:df = xl.parse(sheet_name, header=None)if df.empty:continuesheet_name_clean = re.sub(r'[\\/*?:[\]]', '', sub_cat)[:31]sheets_to_write.append((df, sheet_name_clean))except Exception as e:print(f"[ERROR] 处理 {path} 失败 ({e})")if not sheets_to_write:sheets_to_write.append((pd.DataFrame({"提示": ["此大类下无有效数据"]}), "占位"))output_file = os.path.join(output_dir, f"{main_cat}_年鉴.xlsx")if os.path.exists(output_file):os.remove(output_file)with pd.ExcelWriter(output_file, engine='openpyxl') as writer:for df, sheet_name_clean in sheets_to_write:df.to_excel(writer, sheet_name=sheet_name_clean, index=False, header=False)print(f"[OK] {main_cat}_年鉴.xlsx 已生成")# ================= 主流程 =================
for year in years:print(f"\n[INFO] {year} 年抓取 Excel 链接...")url = base_urls[year]links = get_excel_links(url, year)print(f"[INFO] {year} 年发现 {len(links)} 个 Excel 文件")year_folder = os.path.join(base_dir, str(year), "excel")os.makedirs(year_folder, exist_ok=True)for link in links:fname = os.path.basename(link)save_path = os.path.join(year_folder, fname)download_file(link, save_path)output_dir = os.path.join(base_dir, str(year))clean_and_merge_by_category(year_folder, output_dir)print("\n[INFO] 所有年份下载与整合完成!")

用大白话理解核心逻辑

可以理解成:

“打开网页 → 找到所有下载按钮 → 把 Excel 链接抄下来”


② download_file()

可以理解成:

“把链接里的文件保存到本地”

并且:

  • 如果已经下载过 → 自动跳过
  • 避免重复浪费时间

③ clean_and_merge_by_category()

这是核心。

它做了:

  1. 找出所有 Excel 文件
  2. 按文件名前两位数字分组
  3. 每一组生成一个新的 Excel
  4. 每个子类作为一个 Sheet

就像:

把一堆散乱的资料,自动装进不同文件夹。


常见问题解决


❌ 问题1:ModuleNotFoundError

原因:没安装依赖

解决:

pip install requests pandas beautifulsoup4 openpyxl

❌ 问题2:下载失败

可能原因:

  • 网络问题
  • 网站限制
  • 被防爬

解决:

  • 换网络
  • 增加 timeout
  • 合法合规使用

❌ 问题3:路径报错

例如:

FileNotFoundError

原因:路径不存在

解决:

  • 确认磁盘存在
  • 不要写错盘符
  • 不要有中文空格

❌ 问题4:Excel 写入报错

原因:

  • 文件正在打开
  • openpyxl 未安装

解决:

  • 关闭 Excel 再运行
  • 安装 openpyxl

总结

这段代码解决了三个核心问题:

  1. 批量下载
  2. 自动分类
  3. 自动整合

适合:

  • 数据分析人员
  • 写论文的同学
  • 做政府数据研究的人

如果你是新手,只要按照:

环境准备 → 安装依赖 → 修改路径 → 运行 → 查看结果

这五步,就能成功跑起来。


⚠️ 再次提醒:请合法合规使用,仅供学习交流。

http://www.jsqmd.com/news/387426/

相关文章:

  • 题解:洛谷 P5725 【深基4.习8】求三角形
  • 题解:洛谷 P1307 [NOIP 2011 普及组] 数字反转
  • YouGIS顽石工坊空间工具 - 系统总体说明
  • 题解:洛谷 P4956 [COCI 2017/2018 #6] Davor
  • 题解:洛谷 P5726 【深基4.习9】打分
  • 题解:洛谷 P1075 [NOIP 2012 普及组] 质因数分解
  • 书籍-弗可·贝格曼《内蒙古额济纳河流域考古报告》
  • SpringBoot环境配置JDK、Maven、IDEA - 教程
  • 坐标转换工具:结果可直接上图,一键导出多坐标系
  • 5分钟搞定!ComfyUI Photoshop插件终极安装指南:让AI绘画直接在PS中完成 - 详解
  • 现代控制理论(2)—— LQR
  • 盘点螺杆泵主流品牌:从产品性能到官方电话的服务对比,无堵塞自吸泵/卫生级螺杆泵/自吸式计量泵,螺杆泵厂商如何选 - 品牌推荐师
  • 题解:洛谷 P1420 最长连号
  • 互联网大厂Java求职面试实录:核心技术与业务场景解析
  • 题解:洛谷 P1217 [USACO1.5] 回文质数 Prime Palindromes
  • 题解:洛谷 P5724 【深基4.习5】求极差 / 最大跨度值 / 最大值和最小值的差
  • 题解:洛谷 P5722 【深基4.例11】数列求和
  • 题解:洛谷 P5723 【深基4.例13】质数口袋
  • 企业iPaaS选型指南:如何打破数据孤岛实现高效集成
  • 用 ArcPy 批量拆分并投影 Shapefile:自动分组导出 + 合并输出
  • jar 包又冲突了?如何快速确定与哪个 jar 包冲突?
  • 因为 BitMap,白白搭进去 8 台服务器
  • 受聘为2026年度中国知网评审专家库专家
  • 三、Claude Opus 4.6 三体银河纪元 -1
  • 一文搞懂告别繁琐命令行:自研多线程 SSH 极速文件传输助手(附 GitHub 源码):核心原理+实战案例
  • 彻底干掉恶心的 SQL 注入漏洞,一网打尽!
  • 题解:洛谷 P2669 [NOIP 2015 普及组] 金币
  • 一个小小的签到功能,到底用 MySQL 还是 Redis?
  • 题解:洛谷 P1035 [NOIP 2002 普及组] 级数求和
  • 求求你,别在 MySQL 中使用 UTF-8了!