news 2026/9/10 17:57:42

10个Python自动化脚本:从文件整理到测试通知,告别重复劳动

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
10个Python自动化脚本:从文件整理到测试通知,告别重复劳动

不知道你是不是也这样:每天真正让人心累的,不是搞不定的技术难题,而是那些“不做不行、做了纯粹浪费时间”的重复劳动——下载目录堆了几百个文件,月底十几张Excel等着合并,项目页面刷新了无数遍才等到一个名额。我前后花了两个周末,写了10个Python自动化脚本,把这类事务全部交给电脑执行。这篇文章就把它们完整列出来,从文件整理、数据处理、网页信息监控,到自动化测试脚本和备份通知,每个脚本都给出核心实现和运行思路。适合刚学Python、想快速做出实用工具的开发者,也适合测试、运维以及被日常琐事折磨的办公族参考。

很多朋友拿到脚本第一反应是“我代码复制过去了,怎么跑不起来?”十有八九问题不在代码,而在Python运行环境。所以我不急着上脚本,先把环境这关过了。

1. 先把车修好:Python环境这样配,后面十个脚本才跑得动

1.1 安装Python时最容易踩的三个坑

一直有人问“为什么我在cmd里敲python,弹出来的是微软商店?”这个坑我之前也踩过。如果你从微软商店安装Python,很多时候python命令会被一个“应用安装程序”别名截胡,尤其是Windows 10和Windows 11默认会开启这个别名开关。你看到的热搜词“python was not found; run without arguments to install from the microsoft store”说的就是它。

解决办法很简单:去Python官网下载安装包,不要贪图方便走商店。安装时务必勾选“Add Python to PATH”,否则后面pip命令会直接找不到。装好以后,在命令行里验证一下:

python --version pip --version

如果pip命令提示不存在,不要急,先试试python -m pip --version。能用的话,之后统一用python -m pip install xxx,这样最可靠,不会受PATH顺序影响。

再补一个国内用户的惯用操作:把pip源切到国内镜像,不然下载慢到怀疑人生。执行一次就永久生效:

pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

后面所有pip install都会快很多。这一步不是必需,但强烈建议。

1.2 虚拟环境:让每个脚本的依赖互不打架

前面十个脚本会用到的库五花八门,比如pandas、openpyxl、requests、playwright、schedule。如果你全都装到系统全局Python里,短期内没事,时间长了就会遇到“为了装A库升级了某个依赖,结果B库跑不起来了”的尴尬。虚拟环境就是给每个项目配一个独立的Python解释器和独立的site-packages目录,互不影响。

创建和使用也不复杂:

python -m venv .venv

Windows命令行激活:

.venv\Scripts\activate

macOS/Linux激活:

source .venv/bin/activate

激活后命令行前面会出现.venv字样,之后你再pip install,装的东西都会落到这个虚拟环境里。后面每个脚本都可以单独建一个文件夹、建一个.venv,彻底隔离。不想用了直接删文件夹,干净利落。

1.3 编辑器选VS Code就够,重点是选对解释器

编辑器不必花时间纠结,VS Code免费够用。网上关于“vscode配置python环境”的教程一大堆,核心其实只有一个:按Ctrl+Shift+P,输入Python: Select Interpreter,选择你对应当前目录的.venv解释器。很多新手报错“ModuleNotFoundError: No module named pandas”,不是代码问题,而是运行前没选对解释器,结果用了全局Python跑代码,包自然找不到。

2. 文件处理三件套:下载目录、批量改名、重复文件

文件整理是Python自动化脚本最直观的使用场景,见效极快,而且几乎不依赖第三方库,标准库就够了。

2.1 脚本一:按扩展名自动归档,下载目录从此不再像垃圾堆

我的下载目录以前特别夸张:图片、PDF、压缩包、安装程序混在一起,找一份合同要翻半天。这个脚本做的事情很简单——把Downloads文件夹里的文件按后缀名分类,移动到“图片”“文档”“压缩包”“其他”等子文件夹。

from pathlib import Path import shutil src = Path.home() / "Downloads" mapping = { ".jpg": "图片", ".png": "图片", ".gif": "图片", ".docx": "文档", ".pdf": "文档", ".xlsx": "表格", ".zip": "压缩包", ".rar": "压缩包", } for file in src.iterdir(): if file.is_file(): target_dir = src / mapping.get(file.suffix.lower(), "其他") target_dir.mkdir(exist_ok=True) shutil.move(str(file), str(target_dir / file.name))

Path.home()拿到用户主目录,不需要写死绝对路径。mkdir(exist_ok=True)保证目标文件夹已经存在,不会反复报错。第一次跑之前建议先加一行print(file.name)看预览,确认文件会移动到预期位置再真正执行移动。我自己吃过“所有文件都移到了‘其他’”的亏,原因是后缀没考虑大写.PDF,所以`.

最后一行if file.is_file()一定要保留,否则碰到子文件夹,shutil.move会把整个目录移走,结果就乱了。

2.2 脚本二:批量重命名照片/报表,给文件加上规律编号

拍照导出经常出现IMG_20240101_123456.jpg这种名字,或者一堆报表叫新建文本文档 (2).txt。手动改又慢又容易漏。批量重命名脚本可以按你的规则统一处理。

from pathlib import Path folder = Path("E:/照片") prefix = "2025-" for i, file in enumerate(folder.iterdir(), start=1): if file.is_file() and file.suffix.lower() in {".jpg", ".jpeg", ".png"}: new_name = f"{prefix}{i:03d}{file.suffix.lower()}" new_path = file.with_name(new_name) print(file, "->", new_path) # file.rename(new_path) # 确认无误后解除注释

核心是file.with_name()——它只替换文件名部分,保留父目录路径。{i:03d}把序号补成三位,比如001012,排序时看着舒服。脚本里故意把真正改名的rename注释掉了,先打印预览,防止你把文件名改成不可逆的样子。这个习惯我到现在都保留:任何批量操作,先dry-run,再actual-run。

2.3 脚本三:基于哈希值的重复文件清理,别靠文件名猜

文件名字不一样不代表内容不一样,可能是文档(1).pdf文档(2).pdf这种同内容副本。要准确判断重复,不能只看文件名和大小,要用哈希值。

import hashlib from pathlib import Path def md5_chunk(file_path, chunk_size=8192): h = hashlib.md5() with open(file_path, "rb") as f: while chunk := f.read(chunk_size): h.update(chunk) return h.hexdigest() folder = Path("E:/备份") seen = {} for file in folder.iterdir(): if file.is_file(): digest = md5_chunk(file) if digest in seen: print("重复:", file, ",与", seen[digest], "内容相同") else: seen[digest] = file

大文件一次性全部读入内存会卡死,所以用分块读取。while chunk := f.read(8192)里的海象运算符会让部分新手懵,简单理解就是“每次读8192字节,读完为止”。如果你用的Python版本低于3.8,把这个语法改成while True再加普通赋值也行。判断出重复文件后,建议先保留在打印阶段,手动确认后再加删除逻辑。因为哈希判重很可靠,但万一你算的是同一个超大压缩包的分卷文件,哈希不同,所以“确认后再删”是唯一不会让你后悔的做法。

3. 数据处理和网页监控:把“找数据”变成“等数据”

文件整理只是开胃菜。日常办公里最耗精力的其实是数据处理,以及盯着网页看状态变化。这部分也正好是搜索引擎热词里“Python数据分析与可视化”“python爬虫”这些方向的实际应用。

3.1 脚本四:多个Excel表自动合并,月底汇总不再加班

我见过太多人月底手动打开5个分公司的Excel,逐行复制到一个汇总表里。如果有20个文件,光复制粘贴就能耗掉一个下午。用pandas合并其实就十几行:

import pandas as pd from pathlib import Path files = list(Path("sales_data").glob("*.xlsx")) frames = [] for f in files: df = pd.read_excel(f) frames.append(df) result = pd.concat(frames, ignore_index=True) result.drop_duplicates(inplace=True) result.to_excel("汇总.xlsx", index=False)

这里有个隐性问题:每个分公司的表头如果完全一致,合并就没问题;如果表头顺序不一样,pandas默认按列名对齐,反而正好是你想要的。drop_duplicates去重依赖整行数据一致,如果各公司数据格式不统一,建议先去重再处理。更稳妥的做法是合并前先打印每个文件的列名,确认无误再进行下一步。

如果你的环境里没有pandas,先执行pip install pandas openpyxl。openpyxl是pandas读取xlsx文件时的后端引擎,漏装会报错Missing optional dependency 'openpyxl'

3.2 脚本五:CSV/日志定时清洗,把脏数据变成规范格式

服务器日志、数据库导出的CSV经常夹杂多余空格、空行、重复分隔符。手工清洗没有意义,写个脚本加个定时任务就行。

import csv from pathlib import Path input_file = Path("raw.log") output_file = Path("clean.csv") with input_file.open("r", encoding="utf-8", errors="ignore") as fin, \ output_file.open("w", newline="", encoding="utf-8") as fout: reader = csv.reader(fin, delimiter=" ") writer = csv.writer(fout) for row in reader: row = [x.strip() for x in row if x.strip()] if row: writer.writerow(row)

errors="ignore"意味着遇到无法解码的字节会跳过,适合日志这种编码不干净的输入;但对重要数据,千万别用这个参数,宁可让它报错暴露问题。这个脚本只做“清洗成结构整齐的CSV”,后续要分析、入库,都交给下一个环节。定时运行可以配合后面的schedule库,或者直接用Windows任务计划程序/crontab。

3.3 脚本六:把“抢课”改成“名额监控提醒”,合规又能用

搜索热词里“python自动化抢课脚本”确实很火,但我必须说句实话:直接写脚本自动提交选课,既不符合校园网络使用规范,也可能让你的账号被限制登录。更稳妥、也不惹麻烦的做法是做一个“名额监控提醒”脚本——程序负责盯着课程页面或接口,一旦发现状态变成“可选”,立刻通过桌面通知喊你,你自己去提交选课。这样既节省了反复刷新页面的时间,又把安全边界控制住了。

import time import requests from plyer import notification url = "https://course.example.com/api/select-status" previous = "" while True: try: data = requests.get(url, timeout=5).json() status = data.get("status", "") if status != previous and status == "可抢": notification.notify( title="课程名额提醒", message="检测到有名额了,快去提交选课!", timeout=10, ) previous = status except Exception as e: print("请求失败:", e) time.sleep(30)

核心思路是保存上一次的状态,只在状态变化且变成“可选”时才通知你,避免每30秒轰炸一次。要特别注意:请求频率不要太高,30秒一次已经算保守了。如果接口需要登录cookie,你还要处理登录态过期的问题。更优雅的方式是用requests.Session()配合登录接口,而不是每次请求都重新认证。plyer这个库在Windows、macOS、Linux上都能发桌面通知,比写死平台API省事。

4. 自动化测试脚本:UI录制和接口测试,真正减少重复劳动

自动化测试脚本在热搜里占了不小的比重,很多测试同学也问:到底怎么入门?我自己的路径是先会写接口测试,再补UI自动化。UI自动化麻烦在定位元素和浏览器驱动,但近几年工具进步很快,录制生成脚本已经非常成熟。

4.1 脚本七:用Playwright的codegen录制生成UI自动化脚本,省掉手写选择器

提到“ui自动化录制生成脚本的开源项目”,我首推Playwright。它比Selenium的安装更省心,而且自带一个录制工具,能把你浏览器里的操作直接录成Python脚本。安装和使用:

pip install playwright playwright install chromium playwright codegen https://example.com

执行playwright codegen后会弹出一个操作窗口和一个代码窗口。你在浏览器里点击、输入、跳转,代码窗口里的Python代码会实时更新。录完以后,把代码保存成.py文件,后续可以直接运行。下面是一个典型的录制结果:

from playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.launch(headless=False) page = browser.new_page() page.goto("https://example.com") page.click("text=登录") page.fill("input[name='username']", "test_user") page.click("button[type='submit']") browser.close()

录制生成的脚本有一个天然问题:选择器可能写得比较随意。比如page.click("text=登录"),当页面上出现多个“登录”字样时,就容易点错。我会在录制后手动把关键元素改用稳定的>import requests import pytest BASE_URL = "https://api.example.com" def test_get_user(): resp = requests.get(f"{BASE_URL}/users/1") assert resp.status_code == 200 data = resp.json() assert "name" in data assert isinstance(data["name"], str) def test_create_order(): payload = {"item_id": 10, "quantity": 2} resp = requests.post(f"{BASE_URL}/orders", json=payload) assert resp.status_code == 201 assert resp.json()["quantity"] == 2

运行命令:

pytest test_api.py --junitxml=report.xml

为什么用pytest而不是直接写一堆if断言?因为pytest在用例失败时会给出清晰的assert对比信息,还能用@pytest.mark.parametrize把多条测试数据塞进同一个用例里。比如测试同一个下单接口的不同数量参数,加一行装饰器就行,不用复制出5个函数。CI里最常见的做法是把report.xml交给Jenkins/GitLab CI解析,单测结果直接呈现在流水线页面上。测试数据尽量放在fixture或外部文件里,别写在测试函数内部,后期维护能省很多事。

5. 收尾闭环:运行完通知我,再把数据备份好

十个脚本里前九个是“干活”,最后一个负责“善后”。自动化脚本跑完如果不通知人,那它到底跑没跑、成不成,你都得靠猜。配合定时任务,这套组合才真正形成闭环。

5.1 脚本九:脚本执行结束发通知(邮件/Server酱/钉钉机器人)

我自己的习惯是每个重要脚本跑完后,都往手机推一条消息。本地开发可以用plyer,服务器上更推荐邮件或Server酱。

邮件实现最通用,核心代码:

import smtplib from email.mime.text import MIMEText def send_mail(subject, content, to_addr): msg = MIMEText(content, "plain", "utf-8") msg["Subject"] = subject msg["From"] = "sender@example.com" msg["To"] = to_addr with smtplib.SMTP_SSL("smtp.example.com", 465) as server: server.login("sender@example.com", "你的授权码") server.send_message(msg)

注意:QQ邮箱、163邮箱这里要填的“密码”不是登录密码,而是邮箱设置里生成的那个授权码。直接用邮箱登录密码会被服务器拒绝,这个坑拦住过很多人。Server酱更简单——注册后拿到一个SendKey,用GET请求就能推送:

import requests SEND_KEY = "你的SendKey" requests.get( f"https://sctapi.ftqq.com/{SEND_KEY}.send", params={"title": "备份任务完成", "desp": "今天的备份已生成"} )

把通知功能单独封装成函数后,前面所有脚本执行完都可以调用它。失败时候也发一条,标题写“脚本失败”,这样你就不用一直盯着终端的输出界面。

5.2 脚本十:本地文件自动备份,并按时间清理旧备份

备份脚本的原则是“不覆盖旧备份,只按份数保留”。每天备份一次,只保留最近7份,既安全又不会把磁盘撑爆。

import shutil from pathlib import Path from datetime import datetime project = Path("E:/projects/myapp") backup_root = Path("E:/backups") stamp = datetime.now().strftime("%Y%m%d_%H%M%S") archive_name = backup_root / f"myapp_backup_{stamp}" shutil.make_archive(str(archive_name), "zip", project) backups = sorted(backup_root.glob("*.zip"), key=lambda x: x.stat().st_mtime, reverse=True) for old in backups[7:]: old.unlink()

shutil.make_archive会把整个目录压缩成zip,文件名带时间戳,保证每次生成的都是独立版本。清理逻辑是先按修改时间倒序排列,留下前7个,剩下的删除。sortedkey=lambda x: x.stat().st_mtime可能对新手有点绕,其实就是在告诉sorted“按文件的最后修改时间排序”。这个脚本在Windows任务计划程序里每天9点跑一次,或者Linux crontab里0 9 * * *跑一次,我基本上就再也没手动备份过项目目录。

6. 十个脚本跑下来,我替你踩过的坑

脚本能跑是一回事,跑得稳是另一回事。我把自己在重复“复现、修改、调试”过程中踩过的坑集中写在这里,希望对你有实际帮助。

6.1 环境变量和Microsoft Store的Python陷阱

前文说过微软商店那个坑。还有一个常见问题是pip install成功,但命令行的pip提示找不到。原因大概率是Python的Scripts目录没有加进PATH。解决办法不是手动去改环境变量,而是放弃直接使用pip,统一使用python -m pip。这样无论PATH怎么乱,只要有python在,就能走通。

如果python命令本身都被系统“截胡”到了微软商店,你需要去“设置 -> 应用 -> 应用执行别名”里,把“python.exe”和“python3.exe”的开关关掉。然后再用官网安装包重新装一个Python。装完再执行python --version,如果依然提示找不到,就检查安装时是否勾选了“Add Python to PATH”。

6.2 路径、编码、权限,这三个隐形杀手必须记住

Windows下写路径,最烦的是反斜杠转义问题。"E:\new\test"里的\n会被当成换行符。我建议统一用Path对象或pathlib,不要自己拼字符串路径。已经存在的代码里如果用了字符串路径,建议写成raw字符串r"E:\new\test"

编码问题主要出现在读取文件时。默认open()在Windows会用系统编码GBK去读文件,遇到UTF-8内容就容易乱码。除非你有明确理由,否则打开文本文件都加上encoding="utf-8",遇到历史遗留日志再考虑errors="ignore"

权限问题通常表现为“脚本手动跑没问题,但双击或任务计划里运行就报错‘拒绝访问’”。原因可能是目标文件夹需要管理员权限。可以先在脚本里判断目标目录是否有写权限,更省事的做法是给任务计划程序勾选“使用最高权限运行”。

6.3 定时任务不执行,大多是这三个原因

脚本在本机能跑,放进Windows任务计划程序却“罢工”,最常见的原因有三个:

第一,任务计划里的“起始于(Start in)”目录是空的,脚本里的相对路径找不到文件。解决办法是脚本开头把工作目录改成脚本所在目录:

import sys from pathlib import Path BASE_DIR = Path(__file__).parent

后面所有相对路径都基于BASE_DIR计算,不再依赖当前工作目录。

第二,任务计划程序用的Python解释器跟你命令行激活的虚拟环境不是同一个。在“程序或脚本”这一栏,不要只填python.exe,最好填虚拟环境里的绝对路径,比如E:\scripts\.venv\Scripts\python.exe,参数写脚本的绝对路径。

第三,账号权限不够。测试时可以用“只在用户登录时运行”,生成环境再用“不管用户是否登录都要运行”,同时勾选“使用最高权限”。注意权限提升后程序的工作目录可能再次变化,所以第一条的绝对路径处理非常重要。

6.4 自动化测试脚本“刚开始能用,过几天就挂”

UI自动化测试最折磨人的地方不是写脚本,而是抗不过页面改版。今天input[name='username']还能定位,明天前端改成id='username',脚本就挂了。定位元素时优先使用有业务含义的>

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 17:52:37

React Native鸿蒙迁移:bundle白屏根因与排查

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 17:51:19

多隐层神经网络的数理本质:每一层在算什么

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 17:50:20

Python爬虫构建Markdown语法速查字典实战

1. 为什么需要Markdown语法速查字典? 作为一个每天和文档打交道的开发者,我深刻体会到Markdown语法速查的重要性。虽然Markdown本身语法简单,但不同平台(如GitHub、Typora、VS Code)对Markdown的扩展支持各不相同。比如…

作者头像 李华