工作这十年,我写得最多的其实不是业务代码,而是一堆不起眼的自动化小脚本。它们没有闪光的技术亮点,却实打实把我从“复制粘贴、重复点击”的泥潭里捞了出来。平时听到同事抱怨“又要在几百个文件里挑出带关键字的”、“这个月报表合了一下午”,我心里都会默默想:这活儿十分钟就能搞定。这篇文章我就把平时最常用的10个Python自动化脚本整理出来,逐个说清楚它们能解决什么问题、核心逻辑长什么样、实操时有哪些容易踩的坑。不管你基础如何,看完至少能照葫芦画瓢改出自己那版。
1. 为什么选择用Python写自动化脚本
1.1 自动化脚本的价值在于“挤出时间”
很多人一听“自动化脚本”就觉得这是程序员炫技的东西,其实恰恰相反,脚本最大的价值不是代码写得漂亮,而是把那些“规则明确、重复度高、不出成绩”的工作一次性接管过来。
我见过最典型的一个场景:某公司运营同学,每周一早上要手动打开五个Excel文件,筛选出上上周的订单数据,然后填到一张汇总表里。这套流程他干了两年,每次大约四十分钟。后来我用Python给他写了个脚本,数据一放进去,双击运行,三十秒出结果。他省下的时间拿去做了真正需要人判断的事情:分析为什么某个地区的退货率突然升高。这才是自动化的本质,不是替代人,而是把人从低价值劳动中释放出来。
1.2 什么样的任务值得写成脚本
不是所有事情都值得自动化。我判断一个任务能不能写成脚本,通常看三个条件:
第一,规则是否清晰。如果一件事连你都说不清楚“什么情况怎么处理”,那脚本更没办法替你判断。比如“把文件按类型整理”,类型是明确的;但“把重要的文件挑出来”,重要是个模糊概念,得先把它变成具体条件。
第二,频率是否够高。一次性任务也值得写,但投入产出比不划算,除非这个任务特别复杂,光靠人做容易出错。高频任务才是脚本的主场,每天、每周、每月固定重复的事情,写一次脚本能用上一年甚至更久。
第三,出错成本是否够高。手工操作最容易在重复劳动中出错,漏一个字段、错一个格式、忘记保存,这些低级错误在数据量大时几乎无法避免。脚本只要逻辑正确,每次执行的结果都是一致的,不会因为“今天状态不好”而出错。
1.3 脚本选型的几个原则
真正写得多之后,我就总结出了几条属于自己的铁律。
宁可简单,不要花哨。我见过有人用Python写了个带图形界面的文件整理工具,界面做得挺漂亮,但代码量翻了好几倍。如果你的脚本只是自己用,或者给身边几个同事用,命令行交互就够了,加图形界面纯属给自己找事。
善用现成库,不要什么都自己造。Python在自动化领域之所以好用,就是因为生态太全了。处理Excel有openpyxl和pandas,处理图片有Pillow,抓网页有requests加BeautifulSoup,定时任务有schedule。这些库都是经过了大量生产环境检验的,比你自己手搓的轮子稳妥得多。
先跑通,再优化。很多初学者一上来就想写一个“完美”的脚本,各种异常处理、配置化、日志输出一应俱全。我的习惯是先写一个能跑的版本,确认核心逻辑没问题,再根据实际使用中的问题慢慢迭代。脚本这种东西,能用比好看重要一百倍。
2. 十个高频自动化场景拆解
2.1 按扩展名自动整理文件夹
这是一个最入门的脚本,却也是身边朋友好评率最高的一个。它的工作是把一个杂乱无章的文件夹里的文件,按扩展名归类到不同子目录里,比如图片归到“图片”、文档归到“文档”、压缩包归到“压缩包”。
核心逻辑其实很简单:遍历目标文件夹下所有文件,用os.path.splitext取出扩展名,再根据扩展名映射到不同的目标文件夹,最后os.rename或shutil.move移动过去。
这里有个细节值得注意,移动之前一定要先判断目标文件夹是否存在,不存在就先创建,否则会直接报错。另外我习惯把配置文件单独放在一个列表里做映射,这样以后想新增一个分类,改一行列表就够了,不用动核心代码。
2.2 批量重命名文件
批量重命名的需求比想象中多得多。有人要批量给图片加日期前缀,有人要把“项目A_最终版_v3.docx”这种乱七八糟的名字统一成“20240512_项目A_报告.docx”,还有人要把几百个文件里的空格全部替换成下划线。
实现思路主要分三步:用os.listdir或glob拿到文件列表,然后通过字符串处理生成新文件名,最后用os.rename改名。字符串处理是核心,我的建议是先用print把新旧名字对照打出来,确认没问题再真正改名。干过这事的都知道,几百个文件改错名想恢复,那才是真正的灾难。
2.3 图片压缩与格式转换
图片处理是我用得最频繁的脚本之一。无论是做PPT配图、上传网站,还是发邮件,图片太大都是痛点。一个几十兆的图片文件夹压缩之后可能只有两三兆,速度还特别快。
核心工具是Pillow库。打开图片后用thumbnail方法按比例缩放,再用save方法重新保存,quality参数控制压缩质量,85到90是个甜点区间,肉眼看不出差别,体积却能减小一大半。
格式转换更简单,Pillow打开图片后直接另存成目标格式就行。需要注意一点:如果图片有透明度通道,比如PNG转JPEG,直接转换会丢透明背景,必须先用convert('RGB')处理,否则存出来的JPEG背景是黑色的。我第一次转的时候没注意这个,做了十几张图全废了。
2.4 Excel数据清洗与合并
有些所谓的“数据分析”,本质就是体力活。比如一个月度销售数据分散在30张工作表里,需要把它们合并成一张总表,然后做一些简单的汇总统计。用Python做这件事,熟练之后也就是一百行代码的事。
pandas是处理这种任务的主力。read_excel可以批量读取,concat负责纵向合并,groupby做分类统计,最后一行to_excel把结果写出去。这套组合拳对付常见的Excel操作基本够用。
有个实操经验:读取Excel时最好加上dtype=str参数,强制所有列以文本形式读入,否则某些列的数字会被自动识别成浮点数,导致“00123”变成“123”,“工号”“编号”这类列就容易出问题。这种数据污染在合并数据时特别坑,还特别难排查。
2.5 网页信息批量抓取
很多人问:“爬虫是不是很复杂?”其实对于自己日常用的小需求,一点也不复杂。比如我经常要批量查询某个网站的公开信息,几十个链接一个个打开复制粘贴,效率太低了。用requests请求页面,再用BeautifulSoup定位元素,写个循环就完了。
选选择器的时候有个小技巧,尽量不要用那种又长又容易变的CSS路径,优先用带有明确语义的选择器,比如find('h2', class_='title'),这样就算网站的样式稍微调整一下,脚本也不容易挂。
另一个必须提醒的点:要尊重网站的robots协议,控制请求频率,别给人家服务器造成压力。我在脚本里习惯加个sleep(1),每请求一次就歇一秒。数据少时的确慢点,但换来的是稳定和友好,划算。
2.6 定时自动备份
备份这件事,道理谁都懂,但能做到的人真不多。不是懒,是总忘。解决遗忘问题的最好办法不是靠记性,而是靠定时任务。
Windows上的计划任务、macOS上的launchd、Linux上的crontab,都能做到定时执行。但Python自己也有个schedule库,用几行代码就能实现“每天下午六点执行备份函数”。这属于躺平式自动化:写一次,忘掉它,它在后台替你干活。
备份时要考虑两个细节:一是备份文件最好带时间戳,比如backup_20240512.zip,方便以后按时间找回;二是备份方式先拷贝到临时目录再打包,避免文件正在被占用时打包出损坏的压缩包。
2.7 邮件报表自动发送
自动发邮件最典型的应用场景是定时报表。数据脚本把统计结果算完之后,用smtplib和email库把Excel或PDF附件发到指定邮箱,整个流程就能完全跑通,不用人工干预。
这里比较容易踩坑的是邮箱服务的授权密码问题。现在主流邮箱基本都要求用“授权码”而不是登录密码来登录SMTP服务,很多人第一次配置失败,原因就在这里。
另外,邮件正文我建议用HTML格式,不要用纯文本。HTML邮件可以做一些简单的排版,比如把重点数据标红加粗,对方打开邮件一眼就能看到关键信息,体验完全不一样。
2.8 日志关键词监控与报警
服务器日志动辄几十兆,人眼根本看不过来。我的做法是写一个脚本定时读取日志文件的新增部分,用正则匹配关键词,比如“ERROR”“Exception”“连接超时”,一旦命中就把相关行发到即时通讯工具或者邮件里。
实现上要注意一个细节:日志文件一般很大,不能每次从头读一遍。要记住上一次读取到的位置,用seek跳过去,只读新增内容。不然日志一大,脚本效率会越来越低,最终变成自己都不愿意跑的废物脚本。
2.9 磁盘空间预警
磁盘满了这件事,对开发者和设计师来说是家常便饭,但对普通用户来说,往往是电脑突然卡到没法用才发现。与其等到那天,不如提前写个监控脚本。
脚本的逻辑很直接:用shutil.disk_usage获取磁盘总空间、已用空间和剩余空间,算出使用率,超过阈值就发提醒。把这个脚本挂在定时任务里,每天跑一次,基本就能避免“磁盘满了才发现”的窘境。
2.10 文本批量提取与格式转换
这算是一个万金油脚本,主要解决两类问题:一是从一堆文档中批量提取某些字段,比如从一个TXT文件中提取所有手机号;二是把一种格式批量转成另一种,比如多张Word文档统一转成PDF或者纯文本。
提取字段用正则表达式最方便。格式转换的工具看情况,转PDF我用docx2pdf,转纯文本用python-docx,转换前最好先检查源文件是否损坏,否则中途报错会很麻烦。
3. 实操:三个核心脚本的完整实现
3.1 文件自动归类脚本
这个脚本可以作为你的第一个自动化项目,代码量不大,效果立竿见影。我这里给出一个相对完整的版本:
import os import shutil from pathlib import Path # 分类规则:扩展名 -> 目标文件夹 RULES = { '图片': ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp'], '文档': ['.doc', '.docx', '.pdf', '.txt', '.md', '.xls', '.xlsx'], '压缩包': ['.zip', '.rar', '.7z', '.tar', '.gz'], '视频': ['.mp4', '.avi', '.mkv', '.mov'], '音频': ['.mp3', '.wav', '.flac', '.aac'], '代码': ['.py', '.js', '.html', '.css', '.java', '.c', '.cpp'], '其他': [], } def classify(file: Path) -> str: ext = file.suffix.lower() for category, extensions in RULES.items(): if not extensions: continue if ext in extensions: return category return '其他' def organize_folder(folder: str): folder = Path(folder) if not folder.exists(): print(f'文件夹不存在: {folder}') return for item in folder.iterdir(): if item.is_dir(): continue # 不处理子文件夹本身 category = classify(item) target_dir = folder / category target_dir.mkdir(exist_ok=True) target_path = target_dir / item.name if target_path.exists(): # 重名文件加时间戳,避免覆盖 new_name = f'{item.stem}_{item.stat().st_mtime:.0f}{item.suffix}' target_path = target_dir / new_name shutil.move(str(item), str(target_path)) print(f'已移动: {item.name} -> {category}/') if __name__ == '__main__': organize_folder(r'D:\下载文件')运行前建议先注释掉shutil.move那行,换成print预览一遍处理结果。确认分类规则符合预期后再真正执行移动。别人踩过的坑你就别踩了,尤其是“把某个文件夹误判成文件”这种低级错误,一旦大量移动错了,恢复起来非常麻烦。
这个脚本还可以进一步扩展,比如按文件的修改时间归类到“2024年1月”“2024年2月”这样的子目录,改成按年度分层的文件夹结构。原理都一样,只是分类函数的逻辑不同。
3.2 图片批量压缩脚本
图片压缩脚本在线办公场景里太常见了,也是我日常工作使用频率最高的脚本之一。直接上代码:
import os from pathlib import Path from PIL import Image def compress_images(source_folder: str, target_folder: str, max_width=1920, quality=85): source = Path(source_folder) target = Path(target_folder) target.mkdir(exist_ok=True) supported = {'.jpg', '.jpeg', '.png', '.bmp', '.webp'} for img_path in source.iterdir(): if img_path.suffix.lower() not in supported: continue try: with Image.open(img_path) as img: # 转换色彩模式,避免PNG透明背景转JPEG出现黑色底 if img_path.suffix.lower() == '.png': img = img.convert('RGB') # 等比缩放,控制最大宽度 if img.width > max_width: ratio = max_width / img.width new_height = int(img.height * ratio) img = img.resize((max_width, new_height), Image.LANCZOS) # 统一输出为JPEG output_path = target / f'{img_path.stem}.jpg' # 保存:quality控制压缩质量,optimize减小体积,progressive让图片边下边显示 img.save(output_path, 'JPEG', quality=quality, optimize=True, progressive=True) original_size = img_path.stat().st_size / 1024 compressed_size = output_path.stat().st_size / 1024 print(f'{img_path.name}: {original_size:.1f}KB -> {compressed_size:.1f}KB') except Exception as e: print(f'处理失败: {img_path.name}, 原因: {e}') if __name__ == '__main__': compress_images(r'D:\照片原图', r'D:\照片压缩')几个参数的选择我解释一下:quality=85是我试过最稳的区间,再低画质会有可见损失,再高体积降不下来多少;max_width=1920适合大多数网站和文档配图场景,如果你只是发微信,1280就够。Image.LANCZOS是做高质量缩放的经典算法,处理出来的图片在缩小后依然能保持清晰。
还有一个生产环境的小经验:压缩时如果遇到“不支持这种模式”的错误,十有八九是图片色彩模式的问题。先用img.convert('RGB')转一下基本都能解决。
3.3 Excel报表自动合并
报表合并脚本是办公室场景里使用最广的,也是最能体现pandas优势的地方。这里给一个实际的参考案例:
import pandas as pd from pathlib import Path def merge_excel(folder: str, output_file: str, sheet_index=0): folder = Path(folder) all_data = [] errors = [] # 找出所有Excel文件 excel_files = list(folder.glob('*.xlsx')) + list(folder.glob('*.xls')) if not excel_files: print('没有找到Excel文件') return print(f'共找到 {len(excel_files)} 个Excel文件') for file in excel_files: try: # 强制读成字符串,防止工号/编号变成科学计数法 df = pd.read_excel(file, sheet_name=sheet_index, dtype=str) # 加一列标记数据来源 df['数据来源'] = file.stem all_data.append(df) print(f'读取成功: {file.name}, 共 {len(df)} 行') except Exception as e: errors.append((file.name, str(e))) print(f'读取失败: {file.name}, 原因: {e}') if not all_data: print('没有成功读取任何文件') return # 纵向合并所有数据 result = pd.concat(all_data, ignore_index=True) # 去重:保留第一次出现的记录 result = result.drop_duplicates() # 简单统计:按某一列分组计数,这里以“地区”列示例 if '地区' in result.columns: summary = result.groupby('地区').size().reset_index(name='数量') print(summary) # 写入结果 with pd.ExcelWriter(output_file, engine='openpyxl') as writer: result.to_excel(writer, sheet_name='合并数据', index=False) print(f'合并完成,共 {len(result)} 行,输出到: {output_file}') if errors: print(f'共有 {len(errors)} 个文件读取失败,请检查') if __name__ == '__main__': merge_excel(r'D:\分店报表', r'D:\月度汇总.xlsx')这里有一个容易被忽略的细节:用dtype=str读入Excel,表面上看只是把类型统一成了字符串,实际上能躲过一大类数据精度问题。比如Excel里输入“0012”默认会保存成数字12,但你读进来变成字符串后,“0012”才能保留原样。如果你的编号本身就带前导零,这一步绝对不能省。
drop_duplicates()默认保留第一条记录,如果你的业务规则是“保留最新一条”,那就需要先按时间排序,再用keep='last'。我做过的一次需求就是这类,当时没有注意排序规则,结果保留的数据全是旧版本,好在及时发现。
4. 常见问题与排查技巧实录
4.1 中文路径和编码问题
这是Windows用户最常见的坑。Python在Windows下处理中文路径,偶尔会遇到编码异常的报错,尤其是早期版本的Python。现在的Python 3基本解决得不错,但如果你用的还是老版本,建议升级到3.8以上。另外,文件读写时尽量显式指定编码,比如open('file.txt', 'r', encoding='utf-8'),不然遇到GBK编码的文件,默认读取方式会直接报错。
还有一种情况是脚本本身保存为UTF-8,但在Windows的记事本打开时会带BOM头,可能导致Python报SyntaxError: unexpected byte。解决办法是别用记事本写代码,用VS Code或PyCharm这类专业编辑器,保存时选择UTF-8无BOM即可。
4.2 依赖库版本冲突
Python的第三方库更新特别快,有些库的大版本之间API差异巨大,最典型的就是pandas。网上很多教程是老版本写的,你拿着新版本代码去跑,很可能直接报错。解决这类问题,我强烈建议给关键项目建一个虚拟环境,每个项目独立装一套依赖,互不干扰。命令就几个:
python -m venv venv venv\Scripts\activate # Windows source venv/bin/activate # macOS/Linux pip install pandas openpyxl pillow requests beautifulsoup4如果实在不想折腾虚拟环境,那就在脚本里锁定版本号,pip install pandas==2.0.3,至少保证今天能跑,明天升级了也不会突然崩。
4.3 定时任务为什么不执行
定时任务脚本写好了,放在计划任务里却死活不跑,这是很多人都遇到过的问题。我排查这类问题一般按三个方向来找:
第一,看Python解释器路径对不对。计划任务里填的python如果不是绝对路径,系统可能找不到。在Windows上,常见的Python路径是C:\Python312\python.exe,一定要写绝对路径。
第二,看工作目录对不对。脚本里如果有相对路径,比如读取data.xlsx,这个文件相对于哪里?计划任务执行时的默认工作目录往往不是你想象的那个位置。要么把脚本里的路径全部写成绝对路径,要么在计划任务里把“起始于”目录设置成脚本所在目录。
第三,看权限够不够。有些操作需要管理员权限,比如写入系统目录、修改环境变量。如果计划任务是普通用户身份运行,权限不足就静默失败。排查时可以先用命令行手动执行一次,能跑成功再丢到计划任务里。
4.4 脚本运行速度太慢怎么办
自动化脚本如果跑得比人还慢,那就失去意义了。我踩过几次性能的坑,分享几条最有效的优化手段。
处理大量文件时,能用pathlib.Path.iterdir()就不要用os.listdir加字符串拼接,前者在内部处理路径时更高效。处理大数据量时,能用pandas的向量化操作就不要用for循环一行行遍历,相差可能几十倍。
另外一个非常实用的技巧:如果脚本要处理几千个文件,加上multiprocessing或者concurrent.futures的多线程,分分钟跑完。但要注意,多线程处理文件时,输出文件不要重名,每个线程负责的子任务要划分清楚。
最后一条可能反直觉:在脚本里减少print。很多人习惯每处理一个文件就print一行,几千个文件就要刷几千行屏幕,打印本身也占时间。真要确认进度,就print关键节点,比如每处理100个打一行。
5. 脚本落地之后,我的一些习惯
写了几年自动化脚本,踩过的坑少说也有几十个了。有些教训是教训,有些习惯则成了肌肉记忆。比如我养成了一个习惯:所有脚本运行之前,先让脚本打印将要执行的操作,确认无误再用--run参数真正执行。这种“预演模式”虽然多了一道工序,却帮我避免了好几次批量误操作的灾难。
还有一个习惯是给脚本加日志输出。我给每个脚本都准备了一个简单的logs目录,运行结果和错误信息写进日志文件里,方便出问题时回溯。脚本刚开始看不觉得有什么,等你哪天发现数据异常想倒查原因,就明白日志有多重要了。
如果你看完也想动手写自己的自动化脚本,我的建议是不要贪多,从每天最烦的一件小事开始。文件太乱了,就先整理文件;Excel处理得烦,就先合并Excel。把一件小事自动化掉,你就能感受到那种“省下来的时间”的快感,然后自然会有动力去做下一个。自动化这件事,门槛低到不像是技术活,但做久了你会发现,它真正改变的是你对“重复劳动”这件事的敏感度——以后再遇到任何重复的事情,你的第一反应都会是:这能不能写个脚本?