一、回顾与本篇目标
前面九篇,你从零开始学了 Python 的语法、容器、函数、模块、文件读写、爬虫、数据分析。这些技能单独拿出来都能用,但更常见的场景是——把它们组合起来,写一个能自动完成某项任务的脚本。
比如:下载了一个文件夹的图片,文件名全是乱的,想批量重命名;每周要发一份同样的邮件给不同的人;每个月要把 Excel 表格里的数据整理成固定格式。这些事情手动做很烦,写个小脚本却能几十秒搞定。
这一篇,我们不引入新概念,而是用你已经学过的知识,写出几个真正实用的自动化脚本。每个脚本你改几个参数就能用到自己的实际场景中。
本篇的目标:
- 学会用 Python 批量操作文件
- 学会用 Python 自动发送邮件
- 学会用 Python 读写 Excel 文件
二、批量文件操作
这是日常工作中最常见的自动化需求——文件太多,手动处理太累。Python 处理文件的优势在于:一次写好脚本,反复使用。
2.1 批量重命名文件
假设你有一个文件夹,里面全是图片,文件名格式很乱:IMG_20230101.jpg、IMG_20230102.jpg……你想把它们统一改成 旅行照片_001.jpg、旅行照片_002.jpg……
import os
# 目标文件夹路径(改成你自己的)
folder = './photos'
# 新文件名的前缀
prefix = '旅行照片'
# 获取文件夹里所有文件
files = os.listdir(folder)
# 只处理图片文件
image_extensions = ('.jpg', '.jpeg', '.png', '.gif', '.bmp')
image_files = [f for f in files if f.lower().endswith(image_extensions)]
# 按文件名排序(保证顺序一致)
image_files.sort()
# 逐个重命名
for index, old_name in enumerate(image_files, start=1):
# 获取文件扩展名
ext = os.path.splitext(old_name)[1]
# 新文件名:前缀_编号.扩展名
new_name = f'{prefix}_{index:03d}{ext}'
old_path = os.path.join(folder, old_name)
new_path = os.path.join(folder, new_name)
os.rename(old_path, new_path)
print(f'{old_name} → {new_name}')
print(f'完成!共重命名 {len(image_files)} 个文件')
代码解释:
os.listdir(folder):获取文件夹下所有文件的文件名列表。f.lower().endswith(image_extensions):判断文件扩展名是不是图片格式。.lower()转小写保证大小写不敏感。enumerate(image_files, start=1):同时获取索引和文件名,start=1让编号从 1 开始。os.path.splitext(old_name):把文件名拆成“主名”和“扩展名”两部分。{index:03d}:把数字格式化为三位数(001、002、……、099、100)。os.rename(old_path, new_path):重命名文件。
使用前先测试:在正式重命名之前,可以先把 os.rename 那行注释掉,只打印新旧文件名,确认无误后再真正执行。
2.2 按文件类型分类整理
下载文件夹里什么都有——图片、文档、压缩包、安装程序,全混在一起。写个脚本自动分类:
import os
import shutil
folder = './downloads'
# 文件类型与对应的文件夹名
type_mapping = {
'图片': ('.jpg', '.jpeg', '.png', '.gif', '.bmp', '.svg'),
'文档': ('.pdf', '.doc', '.docx', '.txt', '.xlsx', '.pptx'),
'压缩包': ('.zip', '.rar', '.7z', '.tar', '.gz'),
'视频': ('.mp4', '.avi', '.mkv', '.mov'),
'音乐': ('.mp3', '.wav', '.flac'),
}
# 先创建分类文件夹
for folder_name in type_mapping.keys():
os.makedirs(os.path.join(folder, folder_name), exist_ok=True)
# 创建“其他”文件夹
os.makedirs(os.path.join(folder, '其他'), exist_ok=True)
# 遍历文件并归类
for filename in os.listdir(folder):
filepath = os.path.join(folder, filename)
# 跳过文件夹
if os.path.isdir(filepath):
continue
# 获取扩展名
ext = os.path.splitext(filename)[1].lower()
# 查找匹配的类型
moved = False
for category, extensions in type_mapping.items():
if ext in extensions:
shutil.move(filepath, os.path.join(folder, category, filename))
print(f'{filename} → {category}/')
moved = True
break
# 没匹配到的移到“其他”
if not moved:
shutil.move(filepath, os.path.join(folder, '其他', filename))
print(f'{filename} → 其他/')
print('整理完成!')
新出现的 shutil.move():它用来移动文件(或文件夹)。和 os.rename() 类似,但 shutil.move() 可以跨磁盘分区移动,更通用。
2.3 查找并删除重复文件
有时候文件夹里存了多个相同内容的文件,白白占空间。可以通过比较文件的 MD5 哈希值来判断是否重复:
import os
import hashlib
def get_file_md5(filepath):
"""计算文件的 MD5 哈希值"""
with open(filepath, 'rb') as file:
content = file.read()
return hashlib.md5(content).hexdigest()
def find_duplicates(folder):
"""查找重复文件"""
hash_map = {} # 哈希值 → 文件路径列表
for root, dirs, files in os.walk(folder):
for filename in files:
filepath = os.path.join(root, filename)
file_hash = get_file_md5(filepath)
if file_hash in hash_map:
hash_map[file_hash].append(filepath)
else:
hash_map[file_hash] = [filepath]
# 找出所有重复组
duplicates = {h: paths for h, paths in hash_map.items() if len(paths) > 1}
return duplicates
# 使用
folder = './my_files'
duplicates = find_duplicates(folder)
if duplicates:
print(f'找到 {len(duplicates)} 组重复文件:')
for file_hash, paths in duplicates.items():
print(f'\n 哈希值:{file_hash[:16]}...')
print(f' 原始文件:{paths[0]}')
for path in paths[1:]:
print(f' 重复文件:{path}')
else:
print('没有找到重复文件')
代码解释:
hashlib.md5(content).hexdigest():计算文件的 MD5 哈希值。相同内容的文件哈希值相同。os.walk(folder):递归遍历文件夹下所有子文件夹和文件。root是当前目录路径,dirs是当前目录的子目录列表,files是当前目录的文件列表。
三、自动发送邮件
Python 内置了 smtplib 和 email 模块,可以自动发送邮件——发送测试报告、定时提醒、批量通知。
3.1 发送简单文本邮件
import smtplib
from email.mime.text import MIMEText
from email.header import Header
# === 配置信息(改成你自己的) ===
smtp_server = 'smtp.qq.com' # SMTP 服务器地址
smtp_port = 587 # QQ邮箱用587,163邮箱用25
sender_email = '你的邮箱@qq.com'
sender_password = '你的授权码' # 不是邮箱密码,是 SMTP 授权码
receiver_email = '收件人@example.com'
# =============================
# 构建邮件内容
subject = '测试邮件——来自 Python'
content = '''
你好!
这是一封由 Python 脚本自动发送的测试邮件。
如果你收到了,说明脚本运行成功。
致礼
Python 自动化脚本
'''
# 创建邮件对象
message = MIMEText(content, 'plain', 'utf-8')
message['From'] = Header(sender_email)
message['To'] = Header(receiver_email)
message['Subject'] = Header(subject)
# 发送邮件
try:
server = smtplib.SMTP(smtp_server, smtp_port)
server.starttls() # 开启 TLS 加密
server.login(sender_email, sender_password)
server.sendmail(sender_email, receiver_email, message.as_string())
print('邮件发送成功!')
except smtplib.SMTPException as e:
print(f'邮件发送失败:{e}')
finally:
server.quit()
关键配置说明:
- SMTP 服务器地址:QQ邮箱是
smtp.qq.com,163邮箱是smtp.163.com,Gmail 是smtp.gmail.com。 - 授权码:不是你的邮箱登录密码。需要在邮箱设置里开启 SMTP 服务后获取。QQ邮箱:设置 → 账户 → POP3/SMTP 服务 → 开启 → 获取授权码。163邮箱:设置 → POP3/SMTP/IMAP → 开启 → 新增授权码。
server.starttls():开启 TLS 加密,保护邮件内容在传输过程中不被窃听。server.quit()放在finally块中,确保无论是否发送成功都会关闭连接。
3.2 发送带附件的邮件
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 email.header import Header
def send_email_with_attachment(sender, password, receiver, subject, body, filepath):
"""发送带附件的邮件"""
# 创建带附件的邮件对象
message = MIMEMultipart()
message['From'] = Header(sender)
message['To'] = Header(receiver)
message['Subject'] = Header(subject)
# 添加邮件正文
message.attach(MIMEText(body, 'plain', 'utf-8'))
# 添加附件
with open(filepath, 'rb') as file:
attachment = MIMEBase('application', 'octet-stream')
attachment.set_payload(file.read())
encoders.encode_base64(attachment)
filename = os.path.basename(filepath)
attachment.add_header(
'Content-Disposition',
'attachment',
filename=('utf-8', '', filename)
)
message.attach(attachment)
# 发送
server = smtplib.SMTP('smtp.qq.com', 587)
server.starttls()
server.login(sender, password)
server.sendmail(sender, receiver, message.as_string())
server.quit()
print('邮件发送成功!')
四、操作 Excel 文件
上一篇文章讲了用 Pandas 处理表格数据。但有时候需要的不只是分析数据,而是在现有 Excel 模板的基础上自动填写内容,或者设置格式、添加图表。这时候需要 openpyxl 库。
4.1 安装 openpyxl
pip install openpyxl
4.2 创建 Excel 文件并写入数据
from openpyxl import Workbook
# 创建一个工作簿
wb = Workbook()
# 选择默认的工作表
ws = wb.active
ws.title = '学生成绩'
# 写入表头
ws['A1'] = '姓名'
ws['B1'] = '班级'
ws['C1'] = '成绩'
# 写入数据
students = [
('张三', '一班', 85),
('李四', '二班', 92),
('王五', '一班', 78),
('赵六', '三班', 95),
('孙七', '二班', 88),
]
for row_index, (name, class_name, score) in enumerate(students, start=2):
ws.cell(row=row_index, column=1, value=name)
ws.cell(row=row_index, column=2, value=class_name)
ws.cell(row=row_index, column=3, value=score)
# 保存
wb.save('学生成绩.xlsx')
print('Excel 文件已创建')
两种写入方式:
ws['A1'] = '姓名':像字典一样用单元格地址写入。ws.cell(row=2, column=1, value='张三'):用行号和列号写入,循环填充时更方便。
4.3 读取 Excel 文件并修改
from openpyxl import load_workbook
# 打开已有的 Excel 文件
wb = load_workbook('学生成绩.xlsx')
ws = wb.active
# 读取所有数据
print('当前数据:')
for row in ws.iter_rows(values_only=True):
print(row)
# 新增一列:等级
ws['D1'] = '等级'
# 根据成绩填充等级
for row in range(2, ws.max_row + 1):
score = ws.cell(row=row, column=3).value
if score >= 90:
grade = '优秀'
elif score >= 80:
grade = '良好'
elif score >= 60:
grade = '及格'
else:
grade = '不及格'
ws.cell(row=row, column=4, value=grade)
# 保存
wb.save('学生成绩_带等级.xlsx')
print('等级已添加,保存为新文件')
代码解释:
load_workbook():打开已有 Excel 文件。ws.iter_rows(values_only=True):遍历所有行,values_only=True表示只返回单元格的值而不是单元格对象。ws.max_row:获取工作表中有数据的最大行号。
4.4 设置单元格样式
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
wb = Workbook()
ws = wb.active
# 写入数据
ws['A1'] = '产品'
ws['B1'] = '销量'
ws['C1'] = '销售额'
products = [
('手机', 120, 359880),
('电脑', 45, 269955),
('平板', 80, 159920),
]
for row_index, (name, count, total) in enumerate(products, start=2):
ws.cell(row=row_index, column=1, value=name)
ws.cell(row=row_index, column=2, value=count)
ws.cell(row=row_index, column=3, value=total)
# 设置表头样式
header_font = Font(name='微软雅黑', bold=True, size=12, color='FFFFFF')
header_fill = PatternFill(start_color='4A90D9', end_color='4A90D9', fill_type='solid')
header_alignment = Alignment(horizontal='center', vertical='center')
for cell in ws[1]: # 第一行所有单元格
cell.font = header_font
cell.fill = header_fill
cell.alignment = header_alignment
# 设置边框
thin_border = Border(
left=Side(style='thin'),
right=Side(style='thin'),
top=Side(style='thin'),
bottom=Side(style='thin')
)
for row in ws.iter_rows(min_row=1, max_row=ws.max_row, max_col=ws.max_column):
for cell in row:
cell.border = thin_border
# 设置列宽
ws.column_dimensions['A'].width = 15
ws.column_dimensions['B'].width = 10
ws.column_dimensions['C'].width = 15
wb.save('销售报告_带格式.xlsx')
print('带格式的 Excel 文件已创建')
样式说明:
Font():设置字体、大小、加粗、颜色。PatternFill():设置单元格背景色。Alignment():设置水平和垂直对齐方式。Border()+Side():设置单元格边框。ws.column_dimensions['A'].width:设置列宽。
五、综合演示:周报自动生成器
下面这个脚本综合运用了文件读写、Pandas 数据处理、openpyxl 操作 Excel,模拟一个实用的场景——把 CSV 格式的销售数据自动汇总成带格式的 Excel 周报:
import pandas as pd
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from datetime import datetime
def generate_weekly_report(csv_file, output_file):
"""从 CSV 数据生成 Excel 周报"""
# 1. 读取数据
df = pd.read_csv(csv_file)
# 2. 数据处理:分组汇总
summary = df.groupby('产品').agg(
总销量=('销量', 'sum'),
总销售额=('销售额', 'sum'),
平均单价=('单价', 'mean')
).sort_values('总销售额', ascending=False).reset_index()
# 3. 创建 Excel
wb = Workbook()
ws = wb.active
ws.title = '周报'
# 4. 标题
ws.merge_cells('A1:D1')
title_cell = ws['A1']
title_cell.value = f'销售周报 - {datetime.now().strftime("%Y年%m月%d日")}'
title_cell.font = Font(name='微软雅黑', bold=True, size=16, color='333333')
title_cell.alignment = Alignment(horizontal='center', vertical='center')
ws.row_dimensions[1].height = 40
# 5. 表头
headers = ['产品', '总销量', '总销售额', '平均单价']
for col, header in enumerate(headers, start=1):
cell = ws.cell(row=3, column=col, value=header)
cell.font = Font(name='微软雅黑', bold=True, size=11, color='FFFFFF')
cell.fill = PatternFill(start_color='4A90D9', end_color='4A90D9', fill_type='solid')
cell.alignment = Alignment(horizontal='center', vertical='center')
# 6. 数据
for row_index, (_, row) in enumerate(summary.iterrows(), start=4):
ws.cell(row=row_index, column=1, value=row['产品'])
ws.cell(row=row_index, column=2, value=int(row['总销量']))
ws.cell(row=row_index, column=3, value=f"¥{row['总销售额']:,.0f}")
ws.cell(row=row_index, column=4, value=f"¥{row['平均单价']:,.0f}")
# 7. 汇总行
total_row = len(summary) + 5
ws.cell(row=total_row, column=1, value='合计').font = Font(bold=True)
ws.cell(row=total_row, column=2, value=int(summary['总销量'].sum()))
ws.cell(row=total_row, column=3, value=f"¥{summary['总销售额'].sum():,.0f}")
# 8. 边框和列宽
thin_border = Border(
left=Side(style='thin'), right=Side(style='thin'),
top=Side(style='thin'), bottom=Side(style='thin')
)
for row in ws.iter_rows(min_row=3, max_row=total_row, max_col=4):
for cell in row:
cell.border = thin_border
ws.column_dimensions['A'].width = 12
ws.column_dimensions['B'].width = 12
ws.column_dimensions['C'].width = 16
ws.column_dimensions['D'].width = 14
# 9. 保存
wb.save(output_file)
print(f'周报已生成:{output_file}')
# 先创建一个示例 CSV
sample_data = '''日期,产品,地区,销量,单价,销售额
2024-01-05,手机,华东,120,2999,359880
2024-01-12,电脑,华北,45,5999,269955
2024-01-18,手机,华东,150,2999,449850
2024-02-03,平板,华南,80,1999,159920
2024-02-15,电脑,华北,55,5999,329945
'''
with open('sample_data.csv', 'w', encoding='utf-8') as f:
f.write(sample_data)
# 生成周报
generate_weekly_report('sample_data.csv', '销售周报.xlsx')
代码逻辑:
- 第一步:用 Pandas 读取 CSV 数据并进行分组汇总。
- 第二步:用 openpyxl 创建 Excel 文件,填入汇总结果。
- 第三步:设置标题、表头、边框、列宽等格式。
- 第四步:保存文件。
这个脚本在实际工作中稍作修改就能用——把 CSV 路径换成你实际的数据源,调整汇总字段,周报就生成了。
六、定时执行脚本
脚本写好了,但你不想每次手动运行它。让操作系统帮你定时执行:
- Windows:用“任务计划程序”。创建一个基本任务,设置触发器(如每天上午 9 点),操作为“启动程序”,程序填
python,参数填脚本路径。 - Mac / Linux:用 crontab。终端执行
crontab -e,添加一行:0 9 * * * /usr/bin/python3 /path/to/your/script.py,表示每天上午 9 点运行脚本。
七、本篇动手练习
练习 1:文件批量重命名
新建一个文件夹,放一些测试文件。写一个脚本,把所有 .txt 文件统一命名格式为 笔记_001.txt、笔记_002.txt……
练习 2:给自己发一封邮件
配置邮箱的 SMTP 授权码,写一个脚本给自己发一封测试邮件。成功后,改写成可以批量发送不同内容的邮件(收件人列表 + 模板)。
练习 3:Excel 成绩单
用 openpyxl 创建一个学生成绩表,包含:表头、10 名学生的数据、根据成绩自动填充“优秀/良好/及格/不及格”等级、带格式(边框、表头颜色、居中)。
八、本篇小结
这一篇你把前面九篇学到的知识用在了解决实际问题上:
- 批量文件操作:
os.listdir()遍历文件,os.rename()重命名,shutil.move()移动文件,os.walk()递归遍历子文件夹。 - 自动发送邮件:用
smtplib和email模块构建并发送邮件。需要邮箱开启 SMTP 服务并获取授权码。 - 操作 Excel:
openpyxl创建和读取 Excel 文件、写入数据、设置样式、保存。和 Pandas 分工:Pandas 做数据分析,openpyxl 做格式美化。 - 定时执行:Windows 用任务计划程序,Mac/Linux 用 crontab。
自动化的核心思想很简单:把重复的、有规律的操作,用代码描述出来,交给计算机去执行。越是烦琐的工作,越值得花时间写个脚本把它自动化——你可能花半小时写脚本,但以后每次省下五分钟,一个月就赚回来了。
下一篇预告
下一篇——《用 Flask 写后端——Python 版的 Express》:用 Python 写后端 API。如果你之前跟着《后端零基础入门》学过 Express,这一篇会让你发现——Python 写后端和 Node.js 写后端的思路完全一样,只是语法不同。你会用 Flask 把之前的留言板项目用 Python 重写一遍。
Python 零基础入门,每周更新。











暂无评论内容