☰
10个Python自动化脚本:从文件重命名到接口测试,告别重复劳动
2026/10/7 4:28:33 网站建设 项目流程

先讲个真实场景。上个月我帮同事处理一批数据,他要手动给300多个文件统一重命名,把「日报-2024-03-01.xlsx」改成「20240301_销售日报.xlsx」。他一个下午都在点鼠标,改到第200个的时候已经分不清哪个文件改过。我说你停手,让我来。我用了三分钟写了一个Python自动化脚本,跑完只用了两秒。就是从那天起,他主动让我教他装Python。

类似这样的重复劳动,每个人身边至少能找出十件:文件重命名、表格合并、每日备份、批量下载、发提醒邮件、清理缓存。这些事情不复杂,但天天做、反复做,就是在白白消耗时间。这篇博客整理的10个Python自动化脚本,覆盖文件处理、数据处理、网络采集、系统维护、自动化测试五类高频场景,全部是从我自己实际工作中抽出来的。有基础的小白可以直接抄,有经验的也可以看看我在异常处理和定时任务上踩过的坑。

1. 先想清楚:这10个Python自动化脚本要解决什么

1.1 三种典型的重复劳动

我习惯把日常琐事分成三类:机械型、拼接型、等待型。

机械型是那种规则固定、纯靠手工重复的动作,比如把一批图片改成统一尺寸、把日志文件按照日期归档。这类工作人的效率极其不稳定,改到第100个文件时大脑已经麻木,非常容易出错。拼接型是多个工具之间倒腾数据,比如从Excel复制到Word、从网页复制到表格,中间没有任何技术含量,但步骤繁琐。等待型则是你明明知道结果会按时出现,却不得不盯着屏幕等待,比如每天上班打开电脑先刷新后台页面、等报表生成后再手动下载。

一个好的Python自动化脚本,通常解决的是这三种问题的组合。我在设计脚本时有个原则:如果一个操作需要重复执行超过三次,且每次规则相同,就值得写成脚本。这不是懒,而是把人的精力留给真正需要判断的事情。

1.2 为什么不是现成软件,而是自己写脚本

有人会问,文件重命名用批量改名工具,表格合并用WPS,定时任务用系统计划任务,为什么非要写Python脚本?

现成工具有它的优势,但有几个绕不开的痛点:第一,每个工具只解决单点问题,数据从一个环节流向下一个环节时要手动衔接;第二,很多工具对格式、命名规则有苛刻限制,遇到稍微特殊的业务场景就无能为力;第三,软件不会告诉你它为什么跑挂了,脚本可以——我能自己加日志,加异常处理,加重试机制。更重要的是,脚本是可复用、可组合的。今天写了一个下载脚本,明天加上解析逻辑就变成了爬虫;今天写了一个文件备份脚本,后天挂到定时任务里就是自动化运维。这种从点到面的能力,现成工具给不了。

2. 脚本的总体设计与工具选型

2.1 十种场景,五个方向

我在选脚本素材时,没有追求花哨,而是尽量选那些解决真实痛点的内容。下面这个表格是十个脚本的目录和依赖,列出来方便你按需取用:

编号脚本名解决场景核心依赖库
1文件批量重命名规范文件名,按规则统一格式os, re
2带日期的自动备份把重要目录复制到带日期的备份目录shutil, datetime
3Excel批量合并与拆分多个表格汇总、按条件分表pandas, openpyxl
4网页数据批量采集从新闻列表、商品页抓取结构化信息requests, beautifulsoup4
5自动发送提醒邮件定时向自己或同事发送报表、提醒smtplib, email
6界面操作自动化模拟鼠标键盘完成重复点击、录入pyautogui
7定时任务与定时提醒让脚本在指定时间自动运行schedule
8批量图片压缩与转换图片体积过大时的压缩、格式批量转换Pillow
9日志与临时文件清理自动清理过期文件,释放磁盘空间glob, shutil
10接口与页面冒烟测试用脚本快速验证服务是否正常requests, pytest

这五个方向背后对应的是五类最常见的工作场景。选择这些脚本,不是因为它们“看起来酷”,而是因为它们在真实环境里反复被需要。比如第6个界面操作自动化,很多人以为只能用来写游戏辅助,其实是HR录入员工信息、财务核对系统数据时的神器。

2.2 为什么选这些库,环境怎么准备

很多新手死在第一步,不是代码不会写,而是库装不上。这里我说一下选型和安装思路。

用requests而不是urllib,是因为requests让HTTP请求的代码量少一半,并且自带Session、连接池、超时控制,对新手极其友好。用pandas而不是直接操作CSV,是因为它在处理Excel多Sheet、合并、分组时几乎是一行代码解决问题。用schedule而不是系统crontab,是因为它是纯Python跨平台方案,Windows和macOS、Linux通用,不需要额外配置系统服务。

安装库之前,一定要先确认Python环境已经装好。建议直接去官网下载Python 3.10以上版本,安装时勾选Add Python to PATH。Windows用户尤其注意,安装完成后打开命令行执行python --version能正常输出版本号,说明环境变量配置没问题。接着用国内镜像源安装依赖,速度会有质的提升:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple requests pandas openpyxl beautifulsoup4 pillow schedule pyautogui pytest

装完以后,我强烈建议你创建一个虚拟环境,而不是把包直接装到全局Python里。用venv的好处是,每个项目的依赖互相隔离,不会出现A项目需要pandas 1.2、B项目需要2.0导致互相覆盖的问题。具体操作是:

python -m venv myenv

然后根据操作系统激活它。Windows用myenv\Scripts\activate,macOS/Linux用source myenv/bin/activate。之后的pip install就都装在这个环境里了。

3. 十个脚本逐个拆解与实操

3.1 脚本1:文件批量重命名,从一杯咖啡到秒完成

批量重命名最常见的需求是:去掉文件名的前后缀、替换某些字符、按序号重排。我写过最实用的版本是把“项目名+日期描述”的文件统一成“日期_项目名”的格式。

import os import re from pathlib import Path target_dir = Path("./reports") for f in target_dir.iterdir(): if f.is_file(): new_name = f.name.replace("日报", "销售日报") new_name = re.sub(r"\s+", "_", new_name) f.rename(target_dir / new_name)

这个脚本里隐藏着一个关键细节:使用pathlib的Path对象而不是直接拼字符串路径,可以避免Windows反斜杠、Linux斜杠混用带来的路径错误。我在实际项目中,把300多个文件从“项目周报-第8周-2024-06-15.docx”改成“2024-06-15_项目周报_08.docx”时,用的就是类似的转换逻辑。

这类脚本最大的坑是重命名前没有检查重名。如果两个文件转换后名字一样,脚本会直接覆盖后一个文件,而Python不会给任何提示。所以实操时务必先加一层判断:

if (target_dir / new_name).exists(): print(f"跳过 {f.name}:目标文件名已存在")

这种“先检查再操作”的习惯,几乎适用于本篇文章里所有有副作用的脚本。

3.2 脚本2:带日期的自动备份,给你的数据上保险

备份这件事,最大的难点不是复制,而是怎么让备份目录保持整洁。我见过不少同事的备份目录长这样:备份(最终版)、备份(最终版2)、备份(真的最终版)。用脚本解决就简单了,每天生成一个以日期命名的文件夹,只保留最近N天。

import shutil from datetime import datetime, timedelta from pathlib import Path src = Path("./project") backup_root = Path("./backup") today = datetime.now().strftime("%Y%m%d") dst = backup_root / today # 复制整个目录树,如果目标目录已存在,先删除旧的 if dst.exists(): shutil.rmtree(dst) shutil.copytree(src, dst) # 清理7天前的备份 cutoff = datetime.now() - timedelta(days=7) for d in backup_root.iterdir(): if d.is_dir(): try: d_time = datetime.strptime(d.name, "%Y%m%d") if d_time < cutoff: shutil.rmtree(d, ignore_errors=True) print(f"已清理旧备份:{d}") except ValueError: print(f"跳过非日期目录:{d}")

这里的核心逻辑是日期解析。用strptime反解目录名,能保证只清理真正符合日期格式的目录,不会误删你手工创建的其它文件夹。第一次跑的时候建议先不执行rmtree,而是print出将要删除的目录,确认无误再放行。备份脚本是这个列表里最值得做成定时任务的一条,后面脚本7正好派上用场。

3.3 脚本3:Excel批量合并与拆分,告别Ctrl+C/Ctrl+V

处理Excel是办公室需求的重灾区。多个月度报表要合并成一个总表,或者一个总表要根据部门拆成多个小表。pandas配合openpyxl能做到几十秒完成。

import pandas as pd from pathlib import Path src_dir = Path("./sales") all_frames = [] for f in src_dir.glob("*.xlsx"): df = pd.read_excel(f) df["来源文件"] = f.stem all_frames.append(df) merged = pd.concat(all_frames, ignore_index=True) merged.to_excel("merged_sales.xlsx", index=False) # 按“城市”字段拆表 for city, group in merged.groupby("城市"): group.to_excel(f"sales_{city}.xlsx", index=False)

这段代码两个环节都做了:先合并再拆。实际用的时候要注意,如果Excel里有多个Sheet,pd.read_excel默认只读第一个Sheet,需要加sheet_name参数指定。另外,某些表格里日期列会被读成字符串,导致排序错乱,可以在读取时加parse_dates=["日期"]。

我踩过的坑是:pandas读取.xls老格式报错,需要安装xlrd依赖;而.xlsx文件读取则依赖openpyxl。所以你在跑脚本前,一定要先确认自己装的库对上了文件格式。

3.4 脚本4:网页数据批量采集,requests加协程提速

爬虫是很多人学习Python的起点,但网上很多教程要么过于复杂,要么目标网站不适合练习。这里分享一个规范的采集框架:先请求列表页,再解析数据的结构化字段。

import requests from bs4 import BeautifulSoup url = "https://example.com/news" headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"} resp = requests.get(url, headers=headers, timeout=10) resp.encoding = "utf-8" soup = BeautifulSoup(resp.text, "html.parser") for item in soup.select(".news-item"): title = item.select_one(".title").get_text(strip=True) link = item.select_one("a")["href"] print(title, link)

requests负责把网页拿下来,BeautifulSoup负责解析DOM。这里有两个细节:一是必须设置User-Agent,否则很多站点会直接拒绝请求;二是拿到响应后先检查resp.status_code是否为200,再做解析,防止把错误页面当正常内容处理。

如果需要采集大量页面,比如几千条数据,用同步请求会非常慢。Python的协程在这里能显著提速,我用httpx或aiohttp把并发量控制到10左右,几百个页面的采集时间能从十几分钟压缩到几十秒。协程的完整代码略长,重点是不要一次性开几百个并发,否则很容易被目标站点封IP。做个简单限流,每次并发10到20个,既能提速又相对安全。

3.5 脚本5:自动发送提醒邮件,把重复通知交给脚本

邮件提醒在报表推送场景里非常实用。每天统计完数据之后,把结果作为附件发给相关负责人。smtplib配合email库可以完成纯文本、HTML邮件和附件发送。

import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.mime.application import MIMEApplication sender = "alerts@example.com" password = "your_auth_code" # 建议用邮箱提供的授权码,不要用登录密码 receiver = "boss@example.com" msg = MIMEMultipart() msg["Subject"] = "今日销售报表" msg["From"] = sender msg["To"] = receiver body = MIMEText("附件为今日报表,请查收。", "plain", "utf-8") msg.attach(body) with open("merged_sales.xlsx", "rb") as fp: part = MIMEApplication(fp.read()) part.add_header("Content-Disposition", "attachment", filename="merged_sales.xlsx") msg.attach(part) with smtplib.SMTP_SSL("smtp.exmail.com", 465) as server: server.login(sender, password) server.sendmail(sender, receiver, msg.as_string())

这里特别提醒:不要直接拿邮箱登录密码硬编码进脚本。主流邮箱都支持设置“客户端授权码”,用授权码作为密码,即便脚本泄露,别人也只能发邮件,不能改你账号设置。把密码保存在环境变量或者单独的配置文件中,别提交到Git仓库。

3.6 脚本6:界面操作自动化,pyautogui控制鼠标键盘

当目标软件没有API也没有命令行接口时,唯一的自动化手段就是模拟人工操作。pyautogui能控制鼠标移动、点击、键盘输入和屏幕截图。

import pyautogui import time pyautogui.PAUSE = 1.0 # 每次操作间隔1秒 pyautogui.FAILSAFE = True # 鼠标快速移到左上角可紧急停止 def fill_form(name, date): # 假设表单第1个输入框在坐标(400, 300) pyautogui.click(400, 300) pyautogui.typewrite(name, interval=0.1) # 按Tab跳到下一个输入框 pyautogui.press("tab") pyautogui.typewrite(date, interval=0.1) pyautogui.press("tab") fill_form("张三", "2024-08-01")

这段代码最关键的设置是FAILSAFE=True。它相当于自动化的“急停按钮”,当你发现脚本失控,立刻把鼠标甩到屏幕左上角,程序会抛出异常终止。否则,脚本可能会在后台乱点一气,很难停下来。

另外,坐标定位要考虑屏幕分辨率和窗口位置。我的习惯是先让窗口最大化,再根据固定坐标操作。如果脚本需要跨不同分辨率的机器运行,最好截图后用图像识别库来定位元素。pyautogui内置的locateOnScreen能查找图片在屏幕上的位置,虽然速度不如坐标,但通用性更好。

3.7 脚本7:定时任务与定时提醒,让脚本自己“活”起来

写好了脚本,怎么让它按时跑起来?比较稳妥的方案是在脚本内部使用schedule库,简单直观,跨平台。

import schedule import time import subprocess def job(): print("开始执行每日备份...") subprocess.run(["python", "backup.py"], check=True) print("备份完成") schedule.every().day.at("22:00").do(job) schedule.every().monday.at("09:00").do(weekly_report) while True: schedule.run_pending() time.sleep(1)

schedule的写法非常语义化:every().day.at("22:00")就代表每天22点执行。相比系统的crontab和Windows任务计划程序,schedule把定时逻辑直接写在Python代码里,版本可控、调试方便。缺点是这个进程必须常驻,如果电脑关机,脚本不会自己补跑。

对于真正生产环境的定时任务,我更推荐用系统的crontab或者Windows任务计划程序来调度独立的Python脚本,这样即使Python进程崩溃,系统也能重新拉起。我的经验是:小需求用schedule,正式服务用系统级定时任务。

3.8 脚本8:批量图片压缩与格式转换,Pillow轻轻松松

运营同学经常会遇到一个场景:几百张产品图需要从PNG转成JPG、把超过500KB的图片压缩到200KB以内。用Pillow库做这件事很顺手。

from PIL import Image from pathlib import Path src_dir = Path("./images") dst_dir = Path("./images_compressed") dst_dir.mkdir(exist_ok=True) max_size_kb = 200 for f in src_dir.glob("*.png"): img = Image.open(f) img = img.convert("RGB") # PNG带透明通道,转JPG前必须先转RGB quality = 85 out_path = dst_dir / f.with_suffix(".jpg").name img.save(out_path, "JPEG", quality=quality) # 如果压缩后体积仍超标,逐步降低质量 while out_path.stat().st_size / 1024 > max_size_kb: quality -= 10 img.save(out_path, "JPEG", quality=quality)

这里有两个容易忽略的细节。第一,PNG图片如果带Alpha透明通道,直接保存成JPG会报错,必须先convert("RGB")。第二,CDN或者网页上的图片加载对体积有硬性要求,所以压缩循环里的while是非常实用的兜底逻辑。质量从85开始逐步下调,直到满足大小限制。另外,Pillow的resize适合批量改尺寸,比如统一宽度900像素,可以加上img.thumbnail((900, 900)),thumbnail会保持宽高比,不会把图片拉变形。

3.9 脚本9:日志与临时文件清理,给磁盘腾地方

服务跑久了,根目录越来越小,罪魁祸首通常是日志和临时文件。用Python写一个按过期时间清理的脚本特别方便。

from pathlib import Path import time log_dir = Path("./logs") max_age_days = 14 now = time.time() for f in log_dir.rglob("*.log"): mtime = f.stat().st_mtime age_days = (now - mtime) / 86400 if age_days > max_age_days: print(f"删除过期日志:{f}") f.unlink()

这里用的是文件修改时间mtime,而不是文件名里的日期,好处是不会因为日期命名不规范而漏删。rglob能递归匹配所有子目录下的.log文件。如果你要清理的是临时文件tmp目录,把rglob(".log")改成rglob("")即可,但一定要加白名单机制,比如跳过正在被占用的文件。在Windows上,删除被占用的文件会抛PermissionError,所以用try/except把异常包住,或者改用with suppress(PermissionError)。

我在做这个脚本时遇到过一个问题:有些日志文件虽然修改时间很旧,但进程依然持有文件句柄。用unlink删除后,磁盘空间并不会立即释放,而是等句柄释放后才回收。所以“删了半天空间没变”不是脚本无效,而是文件被占用。这时可以把脚本放到定期重启服务的流程里执行。

3.10 脚本10:接口与页面冒烟测试,pytest快速验证

自动化测试脚本是很多测试同事的刚需。用pytest写接口级冒烟测试,比手动用Postman一个个点要可靠得多。

import requests import pytest BASE_URL = "https://example.com/api" def test_login_api(): resp = requests.post(f"{BASE_URL}/login", json={"user": "admin", "pwd": "123456"}) assert resp.status_code == 200 assert resp.json()["code"] == 0 def test_list_api(): resp = requests.get(f"{BASE_URL}/list", params={"page": 1}) assert resp.status_code == 200 assert "data" in resp.json()

然后直接在命令行执行:

python -m pytest test_api.py -v

pytest会收集test开头的函数并运行,-v输出每条用例的通过情况。这种测试脚本的好处是,等接口上百个之后,手动点一遍可能要半小时,脚本统计运行只要一两分钟,还能接入CI流水线,每次部署后自动跑一遍。

如果要做页面级UI自动化,可以用Selenium操作真实浏览器。但我的建议是不到万不得已别用UI自动化,它脆弱且效率低,一个按钮样式调整可能导致脚本失灵。优先用API层做自动化,维护成本低一个量级。

4. 运行这些脚本时踩过的坑

4.1 环境安装的几个老大难

环境问题排在所有坑的第一位。最常见的是pip安装慢、超时。我看到很多同学直接pip install,然后卡在进度条上,最后一大堆红色报错。其实用国内镜像源就行,前面已经给过命令,这里再强调一遍,把它写进你的pip.ini或者~/.pip/pip.conf里,以后就不用每次都指定镜像了。

还有一类问题是“明明装了库,import却报ModuleNotFoundError”。这通常是因为你装了多个Python版本,pip装到了Python3.8,而命令行运行的脚本用的是Python3.10。排查方法很简单:在代码里先输出sys.executable,看看解释器路径和pip --version所在的路径是否一致。保持一致后,问题基本解决。

Linux系统上如果提示缺libpython依赖,需要先安装python3-venv和python3-dev这种包。我用Debian时遇到过Pillow编译失败,因为没有安装libjpeg-dev和zlib1g-dev,装上之后重新pip install Pillow就正常了。这种系统级依赖问题在Windows上反而不常见。

4.2 路径、编码和权限问题

路径问题最坑的是Windows下的反斜杠。比如open("data\2024.xlsx"),Python里\是转义符,会被解读成回车等不可见字符。所以写路径一律用原始字符串r"data\2024.xlsx",或者直接用正斜杠"data/2024.xlsx",因为Windows底层API和Python都兼容正斜杠。

编码问题主要出现在读写文件时。某些Excel或文本文件是GBK编码,Python打开时默认用UTF-8会报UnicodeDecodeError。读取时指定encoding="gbk",或者更稳妥地用encoding="utf-8", errors="ignore"跳过无法解析的字符。爬虫抓取网页时,网站可能返回gbk编码,记得用resp.encoding = resp.apparent_encoding来动态判断。

权限问题则是另一个大坑。在Linux上用crontab调用脚本时,脚本里如果用相对路径如./logs,会原样以当前用户home目录作为基准,导致找不到文件。我的经验是一律在脚本开头用Path(file).parent获取脚本所在目录,再改为绝对路径:

BASE_DIR = Path(__file__).resolve().parent

这样不管脚本在哪里被执行,它都能找到自己的家。

4.3 脚本异常时的“失命”坑

自动化脚本更严重的问题是无声失败。比如备份脚本复制到一半磁盘满了,如果不处理异常,脚本中断后你可能以为备份成功了,结果半个月后发现数据没备份上。所以每个关键操作后面都要有状态检查。

我习惯在脚本里定义一个简单的日志包装函数,把执行情况同时输出到控制台和日志文件:

import logging logging.basicConfig( filename="auto_task.log", level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s" )

然后在每个关键节点logging.info("已完成XXX")。如果放到定时任务里,它会帮你在深夜发现脚本有没有正常执行。排查定时任务没跑时,第一步不是看代码,而是看日志文件和系统计划任务的执行记录。

下表是我整理的最高频问题速查:

现象最可能原因解决思路
pip安装超时默认源在国外切换国内镜像源
import报ModuleNotFoundError多个Python版本混用统一解释器路径
Excel读取中文乱码文件编码非UTF-8指定encoding
脚本定时执行找不到文件相对路径变化用__file__拼绝对路径
pyautogui点击位置不对屏幕分辨率不同先窗口最大化再定位
删除文件提示权限错误文件被占用加PermissionError异常处理
cron中环境变量缺失系统PATH与用户不同crontab里用绝对路径
爬虫被拒绝访问缺少User-Agent设置请求头

5. 把脚本变成真正的生产力工具

5.1 给脚本加一点“重试”和“幂等”思维

自动化脚本在跑的时候,网络波动、系统卡顿、文件被别人占用的问题都会出现。一次失败就退出,不是好的自动化。我给下载类脚本加过一个简单的重试装饰器:

import functools import time def retry(times=3, delay=2): def decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): for i in range(times): try: return func(*args, **kwargs) except Exception as e: print(f"第{i+1}次失败:{e}") time.sleep(delay) return None return wrapper return decorator @retry(times=3, delay=1) def download_file(url): ...

另外,好的脚本应该是幂等的——无论跑一次还是跑十次,结果一致。比如批量重命名前先检查目标文件是否已存在、备份脚本先清理再复制,这些都是为了幂等性。当你把这些习惯沉淀下来,脚本会从“能用”进化到“可靠”。

5.2 把脚本串联成流水线

单个脚本解决一个问题,多个脚本串起来就是一个完整的自动化流水线。举个例子,我每天早晨的工作流是:脚本9清理昨天的日志,脚本2把前一天的重要目录备份到当天日期文件夹,脚本3合并所有报表,脚本5把合并后的报表发到邮箱。这几个脚本单独看都很普通,但串在一起,每天早晨到公司只需要看邮箱,报表已经在里面等我了。

串联的方式很简单,用一个调度脚本依次调用子脚本,与脚本7互相配合。你也可以用subprocess.run以子进程方式执行每一个模块,这样任何一个脚本崩溃都不会把主进程拖垮,还能拿到每个脚本的返回码。返回码非0就说明某个环节挂了,日志里能直接看到。

5.3 从脚本到服务:还可以扩展什么

你要是把这些脚本玩熟了,肯定会想扩展。比如第4个爬虫脚本加上数据清洗后,再对接数据库存储,就是一个完整的数据管道;第10个测试脚本接入GitLab CI,就是持续集成的一部分。至于量化交易策略代码、爬虫进阶、数据库读写这些方向,都是同一个逻辑:先用Python替换重复劳动,再把劳动过程中的数据沉淀下来,最后让数据帮助你做决策。

我做自动化三年多,最大的体会是:写脚本之前先想清楚边界。不需要一上来就搞一个庞大框架,从一个10行的重命名脚本开始,跑通一个场景,再慢慢叠加。等到你手里的脚本数量超过20个时,你会发现很多原来觉得“技术含量低”的重复工作,其实是最适合被自动化的肥肉。

最后分享一个我的操作习惯:每个脚本文件开头都用docstring写清楚用途、用法、依赖库和最近修改日期。半年后你回来看,会感谢当初的自己。自动化解放的是双手,写清楚注释解放的是未来几天的自己。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询