
我一直觉得程序员偷懒的最高级形式就是把自己从重复劳动里捞出来。这几年我的工作流里Python自动化脚本占的比重相当大——从整理下载目录里乱七八糟的文件到定时给团队发周报再到批量巡检交换机配置原本每天至少占用一小时的琐碎操作最后都变成了双击运行或定时触发的脚本。这篇文章我就把日常用得最多、也最经得起折腾的10个Python自动化脚本全部摊开来讲覆盖文件整理、办公数据处理、公开网页采集、UI自动化测试、网络设备运维、系统监控等高频场景。新手可以直接抄作业有基础的可以对照脚本里的细节做优化。看完你会发现自动化脚本并不神秘核心就是两件事拆解手动操作步骤然后用Python一步步把它们翻译成代码。1. 内容整体设计与思路拆解1.1 这10个脚本是怎么挑出来的写自动化脚本最怕两件事一是做得Too Complex一个小功能堆了几百行代码出问题谁都看不懂二是做得Too Narrow只解决自己某一次手头的临时需求换个场景就废掉。我选这10个脚本时用的是四个标准覆盖面广。文件、表格、邮件、网页、系统、网络设备这些日常工作中最常出现的重复劳动场景尽量都能覆盖到不是只盯着某一个方向。输入输出明确。每个脚本的输入是“一堆文件”或者“一个目录”输出是“整理好的文件”或“一份带日期的新文件”边界清晰方便单独使用或组装进更大的流程。改动成本低。全部使用Python标准库加少量第三方库尽量不依赖复杂的框架。像pandas、requests、Pillow这些库都是行业里经过千锤百炼的安装简单踩坑的维度少。可以拼装。脚本之间可以随意组合。比如3.2的Excel汇总结果可以作为3.7邮件的附件3.9的系统监控发现异常后可以调3.7发预警这种“搭积木”的方式才是自动化的正确打开方式。这10个脚本单独拎出来都能解决一个具体问题合在一起基本就能覆盖一个人或者一个小团队日常80%以上的琐碎型重复操作。我不打算展示什么“黑科技”只挑稳定、简单、用了不后悔的方案。1.2 自动化脚本的三个基本套路看别人写的脚本总感觉每一行都认识但轮到自己动手就不知道从哪开始。其实自动化脚本的套路非常固定总结下来就是三步第一步任务分解。把你手动操作的过程写下来越详细越好。比如“整理下载目录”手动操作是打开目录 → 看文件类型 → 移动文件到对应文件夹 → 重名了改名。每一步对应一段代码。第二步数据流设计。想清楚输入是什么、输出是什么、中间需要哪些中间变量。自动化脚本本质上就是“输入→处理→输出”的数据流理清了这条线代码就是顺着水流填进去的事。第三步异常兜底。脚本永远要假设外部环境会出问题——文件被占用、网络超时、磁盘满了。不是每个异常都要处理但关键节点的try/except和日志打印必须有否则半夜定时任务挂了你连它死在哪一步都不知道。这三步想明白写脚本的速度会快很多。后面的每个脚本你都可以按这个思路去拆。2. 环境准备把Python基础打扎实2.1 Python安装与环境变量配置不管你用的是Windows、macOS还是Linux装Python的第一步都是去官网下载对应版本的安装包。下载时有一点容易被忽略Windows安装包打开后第一屏就勾选“Add Python to PATH”这个选项默认不勾漏掉的话后面在命令行里敲python会提示“不是内部或外部命令”。如果不小心漏了补救方法也不难手动把Python安装目录和它的Scripts子目录加到系统环境变量PATH里再重开命令行验证。装完以后在终端执行python --version pip --version能正常输出版本号就说明基础环境没问题。这里再提一个我踩过的坑如果你电脑上同时装了多个Python版本命令行里执行的python到底是谁取决于PATH里的顺序。多人共用电脑或者装过Anaconda的机器尤其容易出现“python不是那个python”的问题。建议这种场景用py -3Windows或者python3Linux/macOS来指定解释器避免程序跑起来后找不到对应版本的库。Linux和macOS用户如果遇到系统自带Python和自装Python冲突的情况推荐用pyenv或者直接通过包管理器安装比手动编译省心得多。2.2 依赖库安装与VS Code调试配置本文涉及第三方库包括pandas、openpyxl、requests、BeautifulSoup4、selenium、webdriver-manager、Pillow、netmiko、psutil。安装命令是一行pip install pandas openpyxl requests beautifulsoup4 selenium webdriver-manager Pillow netmiko psutil国内网络环境下如果下载慢可以临时指定镜像源pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名把镜像源写进pip配置文件里更持久Windows用户在C:/Users/用户名/AppData/Roaming/pip/下建一个pip.iniLinux/macOS用户建~/.pip/pip.conf内容写[global] index-url https://pypi.tuna.tsinghua.edu.cn/simple至于开发环境我用的是VS Code。装完Python插件后按CtrlShiftP打开命令面板输入Python: Select Interpreter选择你刚装的解释器这时候新建.py文件就能直接按右上角的三角图标运行。调试时在行号左侧点一下加红点按F5就会停在断点处可以逐步查看变量的值。很多脚本第一次跑出来结果不对我用调试模式一看就找到问题比到处加print要高效得多。3. 十段实战代码逐个拆解3.1 文件自动整理拯救乱糟糟的下载目录下载目录是所有电脑的重灾区PDF、图片、压缩包、安装包堆在一起想找一个月前的文件要翻半天。手动整理一次容易但养成天天整理的习惯很难这种场景最适合交给脚本。import shutil from pathlib import Path RULES { 图片: [.jpg, .jpeg, .png, .gif, .webp, .bmp], 文档: [.pdf, .docx, .xlsx, .pptx, .txt, .md], 压缩包: [.zip, .rar, .7z, .tar, .gz], 视频: [.mp4, .mkv, .avi, .mov], 安装包: [.exe, .msi, .dmg], } def organize(directory, dry_runTrue): base Path(directory) if not base.exists(): print(f目录不存在: {base}) return for item in base.iterdir(): if item.is_file(): ext item.suffix.lower() for folder, exts in RULES.items(): if ext in exts: target base / folder target.mkdir(exist_okTrue) dest target / item.name # 重名文件自动追加编号 counter 1 while dest.exists(): dest target / f{item.stem}_{counter}{item.suffix} counter 1 if dry_run: print(f[模拟] {item.name} - {dest}) else: shutil.move(str(item), str(dest)) break if __name__ __main__: organize(C:/Users/你的用户名/Downloads, dry_runFalse)几个关键点说一下。第一dry_run参数非常实用第一次跑建议设成True先看一遍模拟结果确认规则没问题再真正移动文件避免误移。第二重名文件不能直接覆盖我的处理是自动加_1、_2这样的编号。第三shutil.move跨盘符移动时会自动执行复制删除速度比同盘慢但安全性没问题。如果想把规则扩展成“按月份归档”可以再加上日期判断。例如用item.stat().st_mtime拿到文件修改时间转成YYYY-MM格式的字符串作为二级子目录名这样每个月一个文件夹再也不会出现“2019年的发票和2024年的混在一起”的尴尬。3.2 Excel批处理多表合并与数据清洗很多人对Excel函数如数家珍但面对几十个同格式的报表文件要合并成一个总表时手工复制粘贴实在是一场灾难。Python里用pandas处理结构化数据是标准做法几行代码就能完成合并和清洗。import pandas as pd from pathlib import Path def merge_excel(folder, output_file): folder_path Path(folder) frames [] for file in folder_path.glob(*.xlsx): df pd.read_excel(file) frames.append(df) if not frames: print(没有找到任何Excel文件) return result pd.concat(frames, ignore_indexTrue) result result.dropna(howall) # 删除全空行 if 日期 in result.columns: result[日期] pd.to_datetime(result[日期], errorscoerce) result result.sort_values(日期) result.to_excel(output_file, indexFalse) print(f合并完成共 {len(result)} 行 - {output_file}) if __name__ __main__: merge_excel(D:/reports, D:/reports/汇总报表.xlsx)这段代码的核心是把每个文件的DataFrame放进列表再统一concat。使用ignore_indexTrue是为了让合并后的行号重新从0开始很多新手漏掉这个参数结果每一份子文件的行号都从0开始排序和筛选都会出问题。需要注意多个Excel表的表头必须一致否则合并后会出现错位。稳妥的做法是在合并前先抽看几个文件的df.columns确认字段完全一致再跑批量合并。pd.read_excel默认依赖openpyxl库如果报错说缺少engine按前面说的pip install openpyxl就能解决。pandas还能干很多类似的事批量把CSV转成Excel、按某个字段拆分大表、统一日期格式、去重等等。只要数据的规律是“重复规则”pandas基本都能高效处理。3.3 定时备份压缩归档并自动清理旧包数据丢了再想找回来那种绝望感谁经历谁知道。手动备份最麻烦的不是拷文件而是坚持每天做。机器擅长坚持所以备份这活儿交给定时脚本再合适不过。import zipfile from datetime import datetime from pathlib import Path def backup(source_dir, backup_dir, keep7): src Path(source_dir) dst Path(backup_dir) if not src.exists(): print(f备份源不存在: {src}) return dst.mkdir(exist_okTrue) stamp datetime.now().strftime(%Y%m%d_%H%M%S) arc_name dst / fbackup_{stamp}.zip with zipfile.ZipFile(arc_name, w, zipfile.ZIP_DEFLATED) as zf: for file in src.rglob(*): # 跳过临时文件和缓存目录节省空间 if any(part.startswith(.) or part __pycache__ for part in file.parts): continue zf.write(file, file.relative_to(src)) # 只保留最近 keep 份 backups sorted(dst.glob(backup_*.zip), keylambda p: p.stat().st_mtime) for old in backups[:-keep]: old.unlink() print(f备份完成: {arc_name}当前共 {len(backups)} 份) if __name__ __main__: backup(D:/project, D:/backups, keep7)这里用zipfile而不是直接复制目录好处是占空间小、方便归档和传输。ZIP_DEFLATED参数表示启用压缩如果源目录里都是已经压缩过的文件比如图片、视频压缩率不大可以把参数改成ZIP_STORED只打包不压缩速度会快很多。保留最近7份这个参数非常关键。如果每天备份一次7份就是一周的备份既保证有历史版本可回滚又不会让磁盘被备份文件堆爆。定时触发部分Windows可以打开“任务计划程序”创建基本任务选择每天/每周触发操作里填python.exe的路径和脚本路径Linux用crontab比如每天凌晨2点执行0 2 * * * /usr/bin/python3 /path/to/backup.py /var/log/backup.log 21有个细节很多人会忽略在Windows任务计划程序里如果勾选了“使用最高权限运行”注意Python解释器路径要写全不要写python三个字母了事否则可能因为环境变量加载不到而失败。3.4 公开网页采集价格监控与信息聚合网页采集这个场景最常见的是两类需求盯着某个商品的价格变化或者持续跟踪某类公开信息的更新。Python里有requests负责请求网页BeautifulSoup负责解析HTML组合起来就能做一个轻量采集器。import time import csv import requests from bs4 import BeautifulSoup HEADERS { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } def fetch_price(url, css_selector): try: resp requests.get(url, headersHEADERS, timeout10) resp.raise_for_status() soup BeautifulSoup(resp.text, html.parser) node soup.select_one(css_selector) return node.text.strip() if node else None except Exception as e: print(f抓取失败: {url}, 错误: {e}) return None def main(): targets [ (商品A, https://example.com/item/1, .price), ] with open(prices.csv, a, newline, encodingutf-8) as f: writer csv.writer(f) for name, url, selector in targets: price fetch_price(url, selector) writer.writerow([name, price, time.strftime(%Y-%m-%d %H:%M:%S)]) time.sleep(3) print(采集完成结果已写入 prices.csv) if __name__ __main__: main()写采集脚本有几个必须守住的规矩。第一只采集公开可访问的数据不搞破解、不绕过登录和访问控制第二请求频率一定要克制目标网站不是你的压力测试机每两次请求之间加个time.sleep(3)是对服务器基本的尊重第三设置超时和异常捕获避免因为某个页面异常导致整个脚本崩掉第四先看目标网站的robots.txt它写明哪些路径不允许采集按规则来。技术上最容易被忽视的是User-Agent。很多网站对没有标识的请求直接拒绝加上一个常见的浏览器UA能解决大部分403问题。解析类库BeautifulSoup有几个解析器可选默认的html.parser足够稳定不需要额外装lxml除非页面格式特别乱。采集到的数据存成CSV最适合“随时间累积”的场景比如价格监控每次追加一行后续用Excel或者pandas分析趋势省心得很。3.5 UI自动化测试表单填充与点击验证自动化测试脚本在互联网行业是刚需。回归测试时反复手点登录、注册、下单流程点得人想睡觉这类重复点击操作交给Selenium最合适。from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC def test_login(): driver webdriver.Chrome() try: driver.get(https://example.com/login) wait WebDriverWait(driver, 10) username wait.until( EC.presence_of_element_located((By.ID, username)) ) username.send_keys(test_user) driver.find_element(By.NAME, password).send_keys(test_pass) driver.find_element(By.XPATH, //button[typesubmit]).click() wait.until(EC.url_contains(dashboard)) print(登录流程测试通过) driver.save_screenshot(login_result.png) finally: driver.quit() if __name__ __main__: test_login()这里最值得说的经验是等待策略。新手最爱用time.sleep(5)等页面加载但这是最脆弱的写法——网速稍微波动5秒可能不够可能又浪费。正确做法是显式等待用WebDriverWait配合presence_of_element_located、element_to_be_clickable这些条件元素没出现就一直等直到超时才报错既稳定又高效。定位元素时我推荐一个优先级idnameCSS选择器XPath。前端开发规范的页面基本都会给关键元素加id或name用这些稳定属性定位脚本就不会因为页面样式微调就挂掉。XPath虽然万能但表达式一长就难维护。还有一个常见坑浏览器驱动和浏览器版本不匹配。手写代码管理chromedriver非常痛苦推荐用webdriver-manager这个库代码里改成from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.chrome.service import Service driver webdriver.Chrome(serviceService(ChromeDriverManager().install()))它会自动检测当前浏览器版本并下载匹配驱动省掉手动更新的活儿。3.6 网络设备自动化运维批量巡检与配置备份如果你管过几台交换机、路由器一定经历过这样的夜宵时刻登录设备 → 敲命令 → 翻着屏幕看状态 → 复制配置 → 退出 → 登录下一台。设备一多这种手工巡检方式效率太低而且容易漏记配置。网络设备自动化运维脚本就是解决这个问题的。from netmiko import ConnectHandler from datetime import datetime def backup_one_device(device): conn ConnectHandler(**device) conn.enable() # 进入特权模式 output conn.send_command(show running-config) conn.disconnect() stamp datetime.now().strftime(%Y%m%d) filename fconfig_{device[host]}_{stamp}.txt with open(filename, w, encodingutf-8) as f: f.write(output) print(f{device[host]} 配置备份完成 - {filename}) if __name__ __main__: devices [ { device_type: cisco_ios, host: 192.168.1.1, username: admin, password: supersecret, secret: enable_password, }, # 继续添加更多设备 ] for dev in devices: try: backup_one_device(dev) except Exception as e: print(f{dev[host]} 备份失败: {e})netmiko库比直接用paramiko底层SSH舒服得多它把不同厂商设备的登录差异封装好了device_type指定为cisco_ios、huawei、h3c等命令处理逻辑基本一致。巡检也不限于备份配置批量执行show interface status、show ip route再存成日志都是同一套代码模板。安全方面多说两句。设备密码千万不能硬编码在脚本里否则脚本文件一旦泄露所有设备等于裸奔。常见的做法是存到环境变量里脚本运行时读取或者用一个独立的、权限收紧的配置文件脚本再解析。另外遍历设备时务必要有超时和异常捕获——机房里的设备不一定每台都在线一台连不上不能让整个巡检流程卡死。备份文件建议按“设备IP_日期”命名这样一个月下来每台设备都有一串历史配置快照出问题需要回滚时直接找到对应日期的文件价值非常大。3.7 邮件自动发送把脚本结果推给需要的人脚本跑完数据算出来了但存在硬盘上没人看那等于没做。让脚本自动把结果发邮件给相关人这才真正形成闭环。邮件自动化最常用的就是smtplib配合email库。import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.header import Header def send_mail(sender, recipients, auth_code, subject, content, attachmentsNone): msg MIMEMultipart() msg[From] sender msg[To] , .join(recipients) msg[Subject] Header(subject, utf-8) msg.attach(MIMEText(content, plain, utf-8)) if attachments: for file_path in attachments: with open(file_path, rb) as f: part MIMEText(f.read(), base64, utf-8) part[Content-Type] application/octet-stream part[Content-Disposition] fattachment; filename{file_path.split(/)[-1]} msg.attach(part) with smtplib.SMTP_SSL(smtp.qq.com, 465) as server: server.login(sender, auth_code) server.sendmail(sender, recipients, msg.as_string()) print(f邮件已发送给 {len(recipients)} 人) if __name__ __main__: send_mail( senderyouqq.com, recipients[colleagueexample.com], auth_code你的邮箱授权码, subject每日数据报表, content请查收附件。, attachments[D:/reports/汇总报表.xlsx], )邮箱授权码是个关键点。现在主流邮箱基本都要求用授权码而不是登录密码来登录SMTP服务QQ邮箱在设置里开启SMTP功能时会生成一串授权码就相当于给脚本单独发了一把钥匙比直接用登录密码安全得多。网易、Gmail等也都类似。不同邮箱的SMTP地址和端口不一样QQ邮箱SSL端口是465163邮箱也支持465Gmail用的是smtp.gmail.com:465。如果公司自建邮件服务器端口和加密方式可能要调成STARTTLS模式with smtplib.SMTP(smtp.example.com, 587) as server: server.starttls() server.login(sender, auth_code)把前面3.2合并出来的Excel、3.3的备份文件丢进附件列表再加上一条简短正文一个“凌晨自动算数据、早上自动发邮件”的全自动流程就有了。3.8 图片批处理压缩、格式转换与加水印给运营或者自己做素材整理时经常要批量处理图片图片太大传不上平台要压缩、产品图要统一尺寸、加个水印防抄袭。手动打开PS一张张弄一张图三分钟几十张图就是一个下午。Pillow是Python图像处理的标准库处理这类需求非常方便。from PIL import Image, ImageDraw, ImageFont from pathlib import Path def process_images(src_dir, dst_dir, target_size(800, 800), quality85, watermarkNone): src, dst Path(src_dir), Path(dst_dir) dst.mkdir(exist_okTrue) for img_file in src.glob(*.jpg): try: im Image.open(img_file) im.thumbnail(target_size) # 等比缩放不裁切 # 加文字水印 if watermark: overlay Image.new(RGBA, im.size, (0, 0, 0, 0)) draw ImageDraw.Draw(overlay) font ImageFont.load_default(size30) draw.text((15, 15), watermark, fill(255, 255, 255, 180), fontfont) im im.convert(RGBA) im Image.alpha_composite(im, overlay) out_name dst / fprocessed_{img_file.name} if im.mode RGBA: im im.convert(RGB) im.save(out_name, JPEG, qualityquality) print(f处理完成: {out_name}) except Exception as e: print(f处理 {img_file.name} 失败: {e}) if __name__ __main__: process_images(D:/photos, D:/photos_out, watermarkyourname)thumbnail方法是最有用的一个API它会在保持原始宽高比的前提下把图片缩小到指定尺寸范围内参数传(800, 800)意思是长边最大800像素不会出现拉伸变形的惨剧。quality参数控制JPEG压缩质量85是个比较平衡的选择肉眼几乎看不出画质损失但文件体积能减小一半以上。如果对体积要求再严可以把保存格式换成WebP用同等质量情况下WebP文件更小适合网页场景。处理大图时要稍微注意内存打开一张16K的超大图Pillow会一次性把完整位图加载进内存内存紧张时容易卡死。稳妥的做法是先读取图片尺寸和模式对于超大图片先缩放到一个合理尺寸再进行处理别让脚本把服务器内存吃满。3.9 系统状态监控资源占用异常及时告警服务器跑着跑着突然“不见了”大部分时候不是服务挂了而是磁盘满了、内存耗尽或者CPU被打到100%导致假死。与其等用户报案不如让脚本盯着资源指标超标就记录日志甚至发告警。import psutil import logging logging.basicConfig( filenamemonitor.log, levellogging.INFO, format%(asctime)s %(levelname)s %(message)s, ) THRESHOLD_CPU 80 THRESHOLD_MEM 85 THRESHOLD_DISK 90 def check_system(): cpu psutil.cpu_percent(interval1) mem psutil.virtual_memory().percent disk psutil.disk_usage(C:/).percent print(fCPU: {cpu}% | 内存: {mem}% | 磁盘: {disk}%) logging.info(fCPU: {cpu}% | 内存: {mem}% | 磁盘: {disk}%) if cpu THRESHOLD_CPU: logging.warning(fCPU超阈值: {cpu}% {THRESHOLD_CPU}%) if mem THRESHOLD_MEM: logging.warning(f内存超阈值: {mem}% {THRESHOLD_MEM}%) if disk THRESHOLD_DISK: logging.warning(f磁盘超阈值: {disk}% {THRESHOLD_DISK}%) if __name__ __main__: check_system()psutil是Python里跨平台获取系统信息的标准库CPU、内存、磁盘、网络、进程全部搞定。cpu_percent(interval1)这段代码会采样1秒的CPU使用率interval参数不加的话直接返回0或者瞬时值非常不准这是一个容易忽略的细节。日志系统我直接用logging标准库写入monitor.log。如果要按天滚动生成日志文件可以用logging.handlers.TimedRotatingFileHandler配置whenmidnight参数每天凌晨自动把昨天的日志归档再新建今天的日志文件避免单个文件无限膨胀。更完整的告警链路是把告警接入3.7的邮件脚本遇到超阈值就发邮件给运维同事。再进一步可以接企业微信或钉钉机器人Webhook这些平台都有现成的群机器人API调到脚本里只有十几行代码的事。有个经验分享阈值一定要留余量比如磁盘90%才告警实际上到85%就要注意了因为日志、临时文件、缓存会在短时间内迅速增长到了90%再处理往往已经出现服务异常了。3.10 文本批处理正则提取与批量替换一堆txt、md、日志文件里要找邮箱、提取手机号、批量替换错误关键词如果文件数量上百手工翻文本根本不现实。正则表达式是文本处理的神器配合Python的re模块就能批量搞定。import re from pathlib import Path def process_texts(folder): folder_path Path(folder) email_pattern re.compile(r[a-zA-Z0-9._%-][a-zA-Z0-9.-]\.[a-zA-Z]{2,}) report {} for file in folder_path.glob(*.txt): text file.read_text(encodingutf-8, errorsreplace) emails email_pattern.findall(text) report[file.name] emails # 批量替换错误关键词 text text.replace(旧版本, 新版本) # 统一清理行尾空白字符 text \n.join(line.rstrip() for line in text.splitlines()) file.write_text(text, encodingutf-8) for name, emails in report.items(): print(f{name}: 找到 {len(emails)} 个邮箱) if __name__ __main__: process_texts(D:/docs)re.compile先编译正则表达式在批量场景下比每次调用re.findall时再传pattern性能更好虽然文件数量少时感觉不出来但这是好习惯。errorsreplace比errorsignore更稳妥遇到无法解码的字节会替换成特殊字符而不是直接丢弃至少不会缺内容。正则表达式的学习曲线陡但常用的就那么几个邮箱、URL、手机号、IP地址、时间日期。网上可以搜到很多现成的pattern但在生产环境用之前建议先拿一小批样本跑一下确认匹配结果符合预期。有些pattern看着能匹配实际边界情况处理得一塌糊涂比如验证码傻傻分不清。批量替换前务必备份源文件。3.3的备份脚本正好派上用场——把整个目录打一个压缩包再跑批量处理出问题还能还原。这种“先备份再操作”的流程所有自动化的批量操作都适用。4. 常见问题与排查技巧实录4.1 pip装包失败与编码报错问题一pip install时报错超时。多半是网络问题按2.2配置国内镜像源基本能解决。如果还是超时可以把默认超时时间调大pip install --default-timeout100 包名。问题二UnicodeDecodeError文件读不出来。这个在高频出现过。比如读取Excel或者txt时文件本身是GBK编码但代码默认用UTF-8去解码必然报错。处理方式明确读取文本时指定encodingutf-8如果确认源文件是GBK就要用encodinggbk。不确定的时候可以先用errorsreplace兜底至少不让脚本崩溃。问题三模块安装了但import时报错ModuleNotFoundError。最常见原因是解释器不对。在VS Code里可以点右下角看当前用的解释器是不是你装了库的那个。命令行运行时确认你执行的是python xxx.py而不是别的版本。还有一种情况是文件名把模块名覆盖了比如你自己创建了requests.py再import requests时Python会优先加载同目录下的同名文件基本必踩改掉文件名就好。4.2 定时任务不执行与浏览器驱动版本不匹配定时任务没跑起来的排查顺序。第一先手动执行一次脚本确认脚本本身没问题第二在任务计划程序或crontab里设置的Python路径写完整了吗Windows里python可能不是你想象的那个路径建议用where python查完整路径然后填进任务第三Windows任务计划程序里的“起始于”目录没设脚本里用相对路径读取文件就可能找不到文件建议一律在脚本里用绝对路径第四权限问题涉及写系统盘或者受保护目录时勾选“使用最高权限运行”。Linux下还要注意脚本文件要有执行权限日志重定向的文件必须有写权限否则cron静默失败一点报错都看不到。浏览器驱动版本不匹配怎么解。Selenium报SessionNotCreatedException十有八九是chromedriver和Chrome版本对不上。最省事的方法是改用webdriver-manager自动匹配。如果还是报错检查一下Chrome浏览器是否开启了自动更新企业内网环境下驱动版本固定但浏览器版本更新了就手动指定驱动版本service Service(ChromeDriverManager(version114.0.5735.90).install())5. 把10个脚本串成一套自动化体系5.1 用统一入口脚本调度脚本单个跑没问题但每次手动去执行一个又一个脚本还是很麻烦。我更推荐的方式是在项目根目录放一个main.py类似于自动化流水线的总控台里面把各功能模块导入进来按预设顺序依次调用。from datetime import datetime from file_organizer import organize from excel_merge import merge_excel from backup import backup def daily_tasks(): print(f 开始执行 {datetime.now()} ) # 1. 整理下载目录 organize(C:/Users/你的用户名/Downloads, dry_runFalse) # 2. 合并报表 merge_excel(D:/reports, D:/reports/汇总报表.xlsx) # 3. 备份项目 backup(D:/project, D:/backups, keep7) print( 全部任务执行完毕 ) if __name__ __main__: daily_tasks()这种统一入口的好处是逻辑清楚每天该干什么看这一个文件就知道新脚本上线在总控台里加一行调用就行。后续如果需求复杂到需要进行条件判断、传递状态也可以用Python的流程控制语法自然实现。目录结构我习惯这样组织D:/scripts main.py file_organizer.py excel_merge.py backup.py send_mail.py logs/ outputs/每个脚本独立成文件函数返回值尽量统一设计成布尔值或者结果字符串方便总控台判断前一步是否成功、要不要继续跑下一步。5.2 日志埋点与异常兜底自动化系统最怕的不是“报错”而是“静默失败”。脚本某一步没跑成功但是没有日志、没有提示你以为备份完成了实际上一周都没备份数据覆盖的时候才追悔莫及。所以每个脚本都应该有日志输出。我自己总结了一个简单的日志规范关键节点必打印异常必须捕获并输出堆栈。print适合手动执行时看输出logging适合落盘长期追踪。生产环境建议两者结合logging同时配置StreamHandler和FileHandler控制台和文件都有。异常处理也有讲究。不是所有Exception都统一捕获就算了应该在关键操作旁边精确捕获可能的问题比如try: shutil.move(src, dst) except FileNotFoundError: logging.error(f源文件不存在: {src}) except PermissionError: logging.error(f文件被占用或没有权限: {src})这样日志里能看到具体原因而不是笼统的一句“出错了”。定时任务挂了之后第二天早上第一件事应该是打开日志文件看最后的错误信息定位问题。最后再说一点体会。我第一次写自动化脚本时也走过弯路总想着代码要写得漂亮、抽象、通用结果一个文件夹整理功能写了200多行自己都看不懂。后来想明白了自动化脚本的第一目标是解决问题第二目标是能维护。先写一个能跑的版本跑通以后再考虑优化。把“手动流程”翻译成“脚本流程”的过程其实也是重新审视自己工作习惯的过程——很多你以为必须人工处理的部分拆开来看都是可以交给机器的重复动作。这个思路通了哪怕这10个脚本不是你的场景你也能自己写出第11个、第12个。另一个实用的小建议所有脚本的常量目录路径、阈值、收件人列表尽量写在文件顶部统一维护比如用CONFIG {}这样的字典集中管理。我踩过最痛的坑就是把路径散落在代码各处改一个目录名要在十几个地方来回找。集中管理后每次调整只需要看一眼文件顶部改起来快也不容易漏。