我要提问
ARTICLE DETAIL

资讯详情

前沿编程新知与开发实战干货的深度解读。

10个实用Python自动化脚本:从文件整理到定时提醒,告别重复劳动

10个实用Python自动化脚本:从文件整理到定时提醒,告别重复劳动 我最早写Python自动化脚本不是跟风也不是为了把电脑搞得花里胡哨纯粹是被重复劳动逼的。每天从下载文件夹里捞文件、每周人工合并十几个Excel表、每回翻日志找一条报错这些事又机械又费时间干多了人会很烦。后来我把它们一个个用Python自动化脚本解决掉大概也就花了一个周末。今天这篇就整理我实际用过、改过、还在跑的10个Python自动化脚本覆盖文件整理、数据备份、数据采集、报表生成、系统监控和定时提醒这几类高频场景。对上班族、运维同学、数据搬砖工都挺有用新手跟着敲一遍也能跑老手可以直接拿我给的坑来避雷。1. 为什么攒下这10个Python自动化脚本1.1 不是炫技是痛点实在顶不住很多教程喜欢一上来就摆“高大上”的框架但真实情况是大部分人的自动化需求根本不需要多么复杂的架构就是不想每天在琐事上白白浪费时间。我自己最早踩的坑是下载文件夹——软件安装包、PDF文档、临时截图、压缩包堆在一起过两周找一份合同得翻半天。用脚本按照扩展名归类之后整理时间从十分钟变成了三秒钟而且这件事是机器干的不会偷懒也不会漏。另一个典型场景是日报。以前每天下班前要手动统计订单数、报错次数、日报链接复制粘贴到企业聊天软件里天天如此。写脚本自动抓数据、生成文案之后每天只花一分钟检查一遍数据对不对剩下的事都交给Python。说白了自动化第一步不是“我要学一个多厉害的技术”而是“这件事我做第二遍的时候就已经烦了”。这篇文章的10个脚本全部是我在真实任务里反复跑过的不是拼凑出来凑数的。1.2 选脚本的三个标准高频、机械、低风险为什么偏偏是这10个而不是更花哨的人脸识别、语音控制对我来说有三个筛选标准高频要么每天用要么每周用。频率低到一个月一次的任务维护脚本的成本可能比手工还高。纯机械不需要做复杂判断逻辑可以用简单的“如果路径后缀是.jpg就移动”来描述这种活最适合自动化。低风险操作的都是可以恢复或不太重要的数据。涉及核心机密、唯一副本的操作我不会拿脚本乱开刀。按这个标准选下来的10个脚本分布在五个大方向文件整理、数据备份、数据采集、报表生成、系统监控与提醒。每一个都独立可用互相之间不依赖你完全可以只挑自己需要的那几个抄走。2. 动手前先把环境备好2.1 装环境Python版本与虚拟环境我建议直接用Python 3.9以上的版本我本机用的是3.10下面的脚本都没有用太高阶的语法3.8也能跑。如果你电脑上同时有多个Python版本强烈建议用虚拟环境隔离别一股脑装到全局。python -m venv auto_env auto_env\Scripts\activate # Windows source auto_env/bin/activate # macOS / Linux踩过的一个坑不建虚拟环境直接往系统Python里pip安装依赖结果某个库升级后把另一个项目的运行环境搞坏了。版本冲突这件事遇到一次就长记性了。建好虚拟环境后后续所有的pip install都装在这个环境里互不干扰。2.2 依赖清单装好这些库10个脚本全覆盖一整串脚本用到的库不算多但提前装好比写到一半再补省事。常用的roster如下库名主要用途配套脚本pathlib / shutil / os标准库文件路径与复制移动脚本1、2、4pandas / openpyxlExcel读写、合并、网页表格解析脚本3、6Pillow图片压缩处理脚本9psutil获取磁盘、内存、CPU占用率脚本5schedulePython内定时循环辅助调度requests / beautifulsoup4网页内容抓取脚本6python-docx生成或修改Word文档脚本8smtplib / email发送邮件脚本10一次性安装pip install pandas openpyxl pillow psutil schedule requests beautifulsoup4 python-docx这里多说一句pandas是个相对重的依赖如果你日常只需要Excel合并单独装openpyxl其实就够但pandas在脚本6采集网页表格时太好用了所以我还是会装。如果你硬盘空间紧张或者安装网络不好可以分成两批装第一批先装标准库能跑的那几个脚本后面再补。3. 文件整理三连重命名、自动归档、Excel合并3.1 脚本1批量重命名给文件加日期前缀场景很常见从各处收集来的照片、截图、合同扫描件文件名都是“微信图片_20240101123456.jpg”这种根本看不出内容。我习惯在文件名前面加上当天日期和序号这样按名称排序就等于按时间排序。from pathlib import Path import datetime folder Path.home() / Downloads / 待整理 folder.mkdir(exist_okTrue) today datetime.date.today().strftime(%Y%m%d) for i, p in enumerate(folder.glob(*.jpg), start1): new_name folder / f{today}_{i:03d}{p.suffix} if not new_name.exists(): p.rename(new_name) print(f重命名: {p.name} - {new_name.name})把扩展名p.suffix保留很重要很多人会顺手写成固定.jpg结果把png文件也改成jpg后缀图片直接打不开。另外enumerate的序号补零是为了让排序按照三位数自然递增不然第10张会排到第2张前面。注意重命名是“破坏性操作”虽然文件还在但名字错了很难找回。第一次跑的时候建议先只print(new_name)确认结果没问题再真正执行rename。3.2 脚本2下载文件夹自动归档按扩展名分类这个脚本是我跑得最频繁的一个。下载文件夹时间一长就变成“电子垃圾桶”我按文件类型建了几个目标目录脚本把对应扩展名的文件移动进去。思路非常简单扫一圈判断后缀建目录移动。from pathlib import Path mapping { 图片: [.jpg, .jpeg, .png, .gif, .webp], 文档: [.pdf, .docx, .doc, .txt, .md], 表格: [.xlsx, .xls, .csv], 压缩包: [.zip, .rar, .7z], 安装包: [.exe, .msi, .dmg], 代码: [.py, .js, .html, .css], } download_dir Path.home() / Downloads for p in download_dir.iterdir(): if not p.is_file(): continue ext p.suffix.lower() target_category 其他 for category, exts in mapping.items(): if ext in exts: target_category category break dest_dir download_dir / target_category dest_dir.mkdir(exist_okTrue) dest_file dest_dir / p.name if dest_file.exists(): print(f跳过目标已存在: {dest_file.name}) else: p.rename(dest_file) print(f移动: {p.name} - {target_category}/)一个小细节一定要先判断目标目录里有没有同名文件否则两个同名文件相撞重名的那个会被覆盖。这个脚本我建议用“先打印再移动”的模式跑第一遍看清楚哪些文件会被归类成“其他”再调整mapping字典。3.3 脚本3批量合并Excel表一个文件汇总所有Sheet如果你经常要收各分公司、各门店的Excel报表合并起来是纯体力活。用pandas可以一次性把某个目录下所有Excel文件的所有Sheet汇总到一张总表里。import pandas as pd from pathlib import Path folder Path.home() / Downloads / 报表 all_data [] for file in folder.glob(*.xlsx): # sheet_nameNone 读取全部Sheet返回一个字典 sheets pd.read_excel(file, sheet_nameNone) for sheet_name, df in sheets.items(): # 加一列来源信息后面出问题好追溯 df[来源] f{file.stem}:{sheet_name} all_data.append(df) merged pd.concat(all_data, ignore_indexTrue) merged.to_excel(folder / 合并总表.xlsx, indexFalse) print(f合并完成共 {len(merged)} 行)这里最常踩的坑是不同Sheet的列名不一致比如一个叫“订单号”一个叫“订单ID”concat之后会出现两列数据同一列的数值反而变成NaN。我的习惯是合并前先打印出每个文件的列名for file in folder.glob(*.xlsx): df pd.read_excel(file, nrows1) print(file.name, list(df.columns))确认列名一致再合并。如果不一致先用df.rename(columns{...})统一列名。另外有的报表第一行是标题不是表头需要加header1或者skiprows1这个一看打印结果就知道。4. 备份与监控两件套数据不出错机器不罢工4.1 脚本4简单增量备份每次只备份新增或改过的文件数据备份的痛点是全量复制太慢增量备份逻辑又怕写复杂。我用的方案是“按日期建目录 按修改时间判断是否复制”每次都复制到当天新的备份文件夹里如果目标已有同名文件并且修改时间比源文件新就跳过。import shutil from pathlib import Path import datetime src Path(/tmp/my_data) backup_root Path(/tmp/backup) today backup_root / datetime.date.today().isoformat() today.mkdir(parentsTrue, exist_okTrue) for p in src.rglob(*): if not p.is_file(): continue rel_path p.relative_to(src) target today / rel_path target.parent.mkdir(parentsTrue, exist_okTrue) need_copy True if target.exists(): if p.stat().st_mtime target.stat().st_mtime: need_copy False if need_copy: shutil.copy2(p, target) print(f已备份: {rel_path})用rglob(*)可以递归遍历所有子目录这样整个项目的源码、素材、文档都能覆盖。copy2会保留文件的修改时间、权限等元信息后续做增量判断更准。我也保留了一个“只保留最近7份备份”的清理函数每天早上用任务计划跑一次备份旧目录超过7天就删除避免备份盘被撑爆。4.2 脚本5磁盘与内存监控超过阈值就告警服务器磁盘飘红、内存打满很多时候不是突然发生的而是用量一点点爬上去的。用psutil写一个监控脚本定时检查磁盘和内存使用率超过阈值就打印告警或调用邮件发送。import psutil def check_disk(path/): disk psutil.disk_usage(path) return disk.percent def check_memory(): return psutil.virtual_memory().percent disk_percent check_disk(/) mem_percent check_memory() print(f磁盘使用率: {disk_percent}%) print(f内存使用率: {mem_percent}%) if disk_percent 85: print(告警磁盘使用率超过85%) if mem_percent 85: print(告警内存使用率超过85%)配合后面的定时任务可以每天早上10点跑一次。如果你监控的是Windows路径要写实际盘符比如check_disk(C:)。我实际用下来85%这个阈值比较合理太低会天天报警太高则等发现时往往已经晚了。日志输出到文本文件里方便排查历史趋势。5. 数据采集与报表三件套抓表、翻日志、生成日报5.1 脚本6网页表格采集一行pandas读表很多网页上的表格其实可以直接用pd.read_html读取不需要手写XPath解析。这个功能适合抓取公开的行情数据、统计报表、竞赛成绩等结构化表格。import pandas as pd url https://example.com/data/table tables pd.read_html(url) df tables[0] # 页面上第一张表 df.to_excel(网页表格.xlsx, indexFalse) print(df.head())read_html返回的是一个DataFrame列表因为一个网页可能有多张表。先打印表格数量再取需要的下标print(len(tables))。它底层依赖lxml或html5lib如果报错就补装一下。遇到动态加载的页面表格是JavaScript渲染出来的时read_html拿到的是空的或只有部分数据。我的备选方案是用requests拿原始HTML再配合BeautifulSoup解析实在不行再考虑浏览器自动化。另外提醒一句抓取数据前看一下目标网站的条款和robots协议访问频率不要太激进只抓公开的非登录数据。5.2 脚本7日志异常扫描只报错不打扰线上服务的日志动辄几万行直接打开搜索效率太低。我写了一个定向扫描脚本只统计ERROR、WARNING的数量并打印最近若干条错误原文。跑起来秒出结果比人工CtrlF翻日志省力太多。import re from collections import Counter from pathlib import Path log_file Path(app.log) counter Counter() error_lines [] patterns { ERROR: re.compile(r\bERROR\b, re.I), WARNING: re.compile(r\bWARNING\b, re.I), } with log_file.open(encodingutf-8, errorsignore) as f: for line in f: for kind, pattern in patterns.items(): if pattern.search(line): counter[kind] 1 if kind ERROR: error_lines.append(line.strip()[:300]) break print(统计结果:, dict(counter)) print(最近20条ERROR:) for line in error_lines[-20:]: print(line)逐行读取而不是一次性read()是为了应对大文件。errorsignore是预防日志里混入非UTF-8编码的乱码不然程序会在某一行直接崩溃。这个脚本可以直接挂在定时任务里每天早上自动把统计结果发到群里或者写到报告里。5.3 脚本8自动生成日报Word模板里填数据日报形式感很强每天都得发但又不想每天手敲。我的做法是维护一个Word模板里面留{{date}}、{{order_count}}、{{error_count}}这类占位符脚本读取数据后替换占位符并另存为新文件。from docx import Document doc Document(日报模板.docx) placeholder_data { {{date}}: 2025-01-07, {{order_count}}: 128, {{error_count}}: 3, } for paragraph in doc.paragraphs: for run in paragraph.runs: for key, value in placeholder_data.items(): if key in run.text: run.text run.text.replace(key, value) doc.save(日报20250107.docx)这里有个非常关键的细节如果直接改paragraph.text会导致整个段落变成纯文本原来设置的加粗、颜色、字体等样式全部丢失。必须先遍历paragraph.runs在每个run对象上替换文本才能保留Word原有格式。我一开始不懂这个生成的日报像大字报后来才发现要操作run。如果你需要插入表格或图片python-docx也能做但代码量会多一些。我一般让日报保持“纯文字少量表格”这样脚本维护成本最低也不容易出错。6. 生活效率两件套图片压缩与定时邮件提醒6.1 脚本9图片批量压缩一张图从5M变500K图片压缩的需求很常见网站上传限制大小、公众号配图太大、手机拍摄的原图发不出去。用Pillow批量处理比一张张用PS打开再另存快得多。from PIL import Image from pathlib import Path source_dir Path(origin_images) output_dir Path(compressed_images) output_dir.mkdir(exist_okTrue) for p in source_dir.glob(*.jpg): img Image.open(p) # 等比缩放最长边不超过1600px img.thumbnail((1600, 1600)) out_path output_dir / p.name img.save(out_path, JPEG, quality80, optimizeTrue) print(f{p.name}: {p.stat().st_size / 1024:.0f}KB - {out_path.stat().st_size / 1024:.0f}KB)thumbnail是等比缩放不会把图压变形quality80是我反复试下来的平衡点肉眼几乎看不出画质损失但体积经常能缩小到原来的1/5。如果你要处理PNG保存时格式参数要改成PNG如果想进一步减小体积可以转成WebP格式同样画质下体积更小但要注意部分老系统不支持WebP。还要记住脚本处理的是“副本”原图保留不动这很重要。6.2 脚本10定时邮件提醒把待办事项送到眼前杂事一多就容易忘。让脚本定时发邮件提醒自己或团队成员比设闹钟更可控而且能同时发给多个人。下面是SMTP发邮件的最小可用版本。import smtplib from email.mime.text import MIMEText sender youexample.com password your_auth_code # 建议使用授权码不是登录密码 receivers [targetexample.com] msg MIMEText(下午5点前记得提交今日数据备份报告, plain, utf-8) msg[Subject] 每日提醒备份报告 msg[From] sender msg[To] , .join(receivers) server smtplib.SMTP_SSL(smtp.example.com, 465) server.login(sender, password) server.sendmail(sender, receivers, msg.as_string()) server.quit() print(邮件已发送)不同邮箱的SMTP服务器地址和端口不一样常见的是SMTP_SSL用465端口或者SMTP先用587端口再starttls()加密。第一次调试时建议先发给自己确认能收到再发给其他人。密码安全性上不要硬编码到脚本里可以用环境变量读取或者单独放在一个不进版本库的配置文件中。7. 把脚本挂上定时任务与排错7.1 让脚本每天自动跑系统自带调度最靠谱脚本写好了如果每次都要手动执行自动化程度就打了一半折扣。我推荐用操作系统自带的任务调度而不是让Python脚本自己常驻循环。原因很朴素系统任务调度挂在操作系统层断了会自动换一个进程重新拉起比Python里跑while True稳定得多。Windows打开“任务计划程序”创建基本任务触发器选“每天”操作里填Python解释器的绝对路径和脚本绝对路径起始目录也填脚本所在目录。Linux / macOS用crontab命令是crontab -e然后加一行0 9 * * * /usr/bin/python3 /path/to/script.py这表示每天早上9点整执行一次。如果你不确定Python解释器路径可以用which python3查看。我强烈建议在任务里加一条“输出日志到文件”的动作例如python script.py run.log 21这样脚本一旦出错你能在日志里看到完整回溯不用对着空屏幕猜问题。7.2 常见问题速查表这几个脚本我踩过的坑、被朋友问过的问题统一整理成一张排查表现象原因解决办法提示ModuleNotFoundError没有安装依赖或装到了别的环境激活虚拟环境后执行pip install -r requirements.txt脚本从其他目录运行时找不到文件相对路径是相对于“当前工作目录”的改用绝对路径或Path(__file__).parent拼出脚本所在目录打开日志/文本文件报编码错误文件不是UTF-8编码open(..., encodingutf-8, errorsignore)文件移动时报权限错误目标文件正在被其他程序占用加try/except跳过该文件先手动确认邮件发送失败SMTP服务器拒绝了普通密码改用邮箱授权码并确认端口是465还是587pd.read_html返回空列表网页是JavaScript动态加载换requests拉源码或考虑浏览器自动化Excel合并后出现大量NaN各Sheet列名不一致合并前打印列名用rename统一定时任务没执行任务计划里没写对解释器路径或工作目录查看任务历史记录把脚本输出重定向到日志文件定位脚本定时执行了但没效果脚本对Excel/文件操作依赖“当前用户桌面”等路径用Path.home()动态定位用户目录排查的核心思路是先看日志。给脚本加打印、加日志把中间结果写出来问题基本都能定位到。我在实际维护这些脚本过程中的体会是先解决一个极小的问题再慢慢扩展不要幻想一口气写出一个230行的全能脚本。先写一个能跑的30行版本连续跑两周不出错再考虑加更多自动化。所有涉及删除、覆盖、移动文件的操作第一次都建议先打印不执行确认无误后再放开真正的执行步骤。备份永远比不备份安全脚本也永远比手工稳定。最后再分享一个小技巧把常用的这些脚本集中放到同一个目录统一维护一个requirements.txt换电脑后五分钟就能把整套“自动化工具箱”复制过去。自动化的核心价值不是让代码看起来很炫而是让你得到一段完全属于自己的、可自由支配的时间。
返回列表