Python自动化办公完整指南:告别重复劳动,效率提升10倍

刚开始我也以为Python自动化办公就是网上抄几个脚本跑跑,结果连踩三个坑:第一个是读取Excel时编码问题搞崩数据,第二个是批量重命名文件时没考虑路径分隔符导致程序炸了,第三个是邮件发出去全是乱码被领导骂。今天我就把这套踩坑总结出来的完整指南扔给你,包含文件操作、数据处理、邮件自动化三个核心场景,每段代码都附上为什么这么写。

先看文件批量处理。日常工作里最烦的就是整理一堆乱七八糟的文件,比如从网上下载的报表命名都是“report(1).xlsx”、“report(2).xlsx”,你得手动改成“2023-01销售数据.xlsx”这种格式。用Python的pathlib库就能搞定,注意别用os模块,因为pathlib跨平台更稳。

python
from pathlib import Path
import re

def batch_rename_files(directory: str, pattern: str, replacement: str):
"""
批量重命名文件,支持正则替换
:param directory: 目标文件夹路径
:param pattern: 匹配模式(正则表达式)
:param replacement: 替换后的内容
"""
dir_path = Path(directory)
if not dir_path.exists():
print(f"路径 {directory} 不存在,给我整不会了")
return

for file_path in dir_path.iterdir():
if file_path.is_file():
# 先获取文件名(不含路径)
old_name = file_path.name
# 用正则替换
new_name = re.sub(pattern, replacement, old_name)
if new_name != old_name:
new_path = dir_path / new_name
file_path.rename(new_path)
print(f"重命名: {old_name} -> {new_name}")

实战:把所有"report(数字).xlsx"改成"销售数据_月份.xlsx"

batch_rename_files(
r"C:\Users\yourname\Downloads\reports",
r"report\(\d+\)",
"销售数据_"
)
`

这个设计真的反人类:Windows路径用反斜杠,Linux用正斜杠,用Path对象自动处理。另外注意正则里的转义——括号在正则里是分组符号,必须加反斜杠。我第一次写时没转义,结果匹配了一堆不该匹配的文件。

(开篇:一个码农对着电脑屏幕崩溃的表情包,配文“Python自动化?呵呵,我踩过的坑比你写过的代码还多”)

另一个坑是Excel数据处理。同事发来的表格经常有合并单元格、空行、日期格式乱码,用pandas读取时如果不做预处理,直接报错或者数据错位。官方文档这段文档不够清晰,我研究了一下午才搞明白headerskiprows的参数怎么配合。

`python
import pandas as pd
from pathlib import Path

def clean_excel_data(file_path: str, sheet_name: str = "Sheet1"):
"""
读取并清洗Excel数据,处理常见脏数据
:return: 清洗后的DataFrame
"""
# 先读取原始数据,不设header,避免合并单元格干扰
df_raw = pd.read_excel(file_path, sheet_name=sheet_name, header=None)

# 找到实际表头所在行:跳过空行和合并单元格产生的NaN行
# 实战中发现前3行经常是标题或空行
for i in range(5): # 最多检查前5行
row = df_raw.iloc[i]
if row.notna().sum() > 3: # 如果一行有超过3个非空值,认为是表头
header_row = i
break

# 重新读取,指定表头行
df = pd.read_excel(file_path, sheet_name=sheet_name, header=header_row)

# 删除全空的行和列
df = df.dropna(how='all').dropna(axis=1, how='all')

# 处理日期格式:统一转为字符串,避免Excel日期序列号
for col in df.columns:
if df[col].dtype == 'object':
# 检查是否包含日期格式数据(如"2023/1/1"或"2023-01-01")
if df[col].str.match(r'\d{4}[/-]\d{1,2}[/-]\d{1,2}').any():
df[col] = pd.to_datetime(df[col], errors='coerce').dt.strftime('%Y-%m-%d')

return df

使用示例:读取“销售报表.xlsx”并清洗

df_cleaned = clean_excel_data("销售报表.xlsx")
print(f"清洗后数据量: {df_cleaned.shape[0]} 行, {df_cleaned.shape[1]} 列")
`

为什么要这么写?因为Excel的合并单元格在pandas里会变成多个NaN值,直接读会导致数据偏移。先手动找表头行再重新读取,虽然多了一步,但稳定得像老黄牛。另一个技巧是errors=’coerce’——碰到无法解析的日期直接变成NaT,比抛异常强。

还有个技巧是邮件自动发送。以前我都是手动抄送几十个人,每次粘贴附件还得检查格式。用smtplib配合email库,可以做成一个函数,传入收件人列表和附件路径就行。

`python
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
from pathlib import Path

def send_email_with_attachments(smtp_server: str, port: int, sender: str, password: str,
recipients: list, subject: str, body: str,
attachments: list = None):
"""
发送带附件的邮件
:param attachments: 附件文件路径列表,支持多个
"""
# 构建邮件对象
msg = MIMEMultipart()
msg['From'] = sender
msg['To'] = ', '.join(recipients) # 多个收件人用逗号分隔
msg['Subject'] = subject

# 添加正文,指定编码防止乱码
msg.attach(MIMEText(body, 'plain', 'utf-8'))

# 添加附件
if attachments:
for file_path in attachments:
file_path = Path(file_path)
if not file_path.exists():
print(f"附件 {file_path} 不存在,跳过")
continue
with open(file_path, 'rb') as f:
part = MIMEBase('application', 'octet-stream')
part.set_payload(f.read())
encoders.encode_base64(part)
# 附件的文件名带扩展名
part.add_header(
'Content-Disposition',
f'attachment; filename="{file_path.name}"'
)
msg.attach(part)

# 发送邮件
try:
with smtplib.SMTP(smtp_server, port) as server:
server.starttls() # 启用TLS加密
server.login(sender, password)
server.send_message(msg)
print(f"邮件发送成功,收件人: {recipients}")
except Exception as e:
print(f"发送失败: {e}")

实战:发送周报给3个同事,附上Excel报表

send_email_with_attachments(
smtp_server="smtp.qq.com", # QQ邮箱用这个,其他邮箱自己查
port=587,
sender="yourname@qq.com",
password="你的授权码", # 不是密码,是QQ邮箱的授权码!这个坑我踩过
recipients=["colleague1@company.com", "colleague2@company.com"],
subject="周报 - 销售数据",
body="各位好,本周销售数据见附件,请查收。",
attachments=[r"C:\reports\销售数据_2023-01.xlsx"]
)
`

第一次写邮件脚本时,我直接用QQ邮箱密码登录,结果报错“SMTPAuthenticationError”,查了半天发现QQ邮箱要求用授权码。去设置里开启SMTP服务,生成一串16位授权码,搞定。另一个坑是附件中文文件名——不加utf-8编码,收件人收到后文件名全是乱码。还有starttls()必须在login()之前调用,否则连接不安全。

(核心:一张流程图,展示文件批量处理→Excel清洗→邮件发送的自动化流水线,标注各环节耗时对比:手工2小时→自动化5分钟)

总结一下,你可以立刻用的三个点:

  • 文件批量处理用pathlib代替os:跨平台兼容,路径拼接用/操作符就行,再也不用担心os.path.join写错。正则替换时一定要转义括号、点号这些特殊字符。
  • Excel清洗先找表头行再读:用header=None读原始数据,遍历前几行找非空值超过3个的行作为表头,能避开合并单元格的坑。日期格式统一用pd.to_datetime转字符串,避免Excel序列号。
  • 邮件发送用授权码代替密码:去邮箱设置里生成16位授权码,starttls()必须在登录前调用。附件中文名用utf-8`编码,多个收件人用逗号隔开。
  • 我写这篇时,正在帮同事跑一个自动化脚本:每天8点自动下载邮件附件、整理成报表、再发回给领导。以前她花2小时干的事,现在5分钟搞定,还能摸鱼喝咖啡。你还在手动复制粘贴?赶紧试试这些代码,有问题评论区见。

    (总结前:一个程序员翘着二郎腿喝咖啡的卡通图,旁边电脑屏幕显示“脚本运行成功”,配文“自动化之后,每天多出2小时”)

    滚动至顶部