Python项目实例:10个有趣的小项目开发实战(附完整项目结构),详解目录组织与根目录获取方法,Python能做什么项目?含新建项目教程与开源项目源码
Python能做什么项目?从爬虫到Web应用,从数据分析到自动化办公,Python几乎无所不能。这篇文章整理了9个有趣又实用的小项目,每个都配有完整的项目结构和代码讲解,适合毕业设计或者自学练手。
完整源码链接:
https://pan.quark.cn/s/1e54aa2ae950
项目列表
- 项目2:豆瓣电影Top250爬虫
- 项目3:Flask个人日记本
- 项目4:命令行天气查询工具
- 项目5:Excel自动化报表生成
- 项目6:图片批量压缩水印工具
- 项目7:简易数据分析可视化(房价分析)
- 项目8:定时发送邮件提醒
- 项目9:命令行待办事项清单
- 项目10:QR码生成器解码器

日记本项目


项目2:豆瓣电影Top250爬虫
豆瓣电影Top250爬虫是一个非常经典的Python入门项目,它几乎涵盖了爬虫开发的所有核心知识点。通过这个项目,你可以学会怎么用Python从网页上抓取数据、怎么解析HTML、怎么把数据保存到本地文件,还能做简单的数据分析。
项目结构
这个项目的目录组织体现了从单脚本到多模块的演进思路:
项目2_豆瓣电影Top250爬虫/
├── main.py # 主入口
├── crawler.py # 爬虫核心逻辑
├── data_saver.py # 数据存储模块
├── analysis.py # 数据分析模块
├── data.csv # CSV格式数据
├── data.json # JSON格式数据
└── requirements.txt # 依赖库
main.py是启动文件,crawler.py负责爬取,data_saver.py负责保存,analysis.py负责数据分析。这种分模块设计的好处是职责清晰,后期想换数据存储方式或者加新的分析功能,只需要改对应的模块。
爬虫核心代码
爬虫的第一步是准备请求头。豆瓣对爬虫比较敏感,所以要把User-Agent设置成浏览器的样子,模拟真实用户访问。
import requests
from bs4 import BeautifulSoup
import csv
import os
import time
import random
HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
然后是带重试机制的请求函数。网络请求经常会因为各种原因失败,加上重试机制可以让爬虫更稳定。这里用了指数退避策略,第一次失败等2秒,第二次等4秒,第三次等6秒。
def fetch_page(url, params=None, retries=3):
for attempt in range(retries):
try:
resp = requests.get(url, params=params, headers=HEADERS, timeout=10)
resp.raise_for_status()
return resp.text
except requests.exceptions.RequestException as e:
wait = (attempt + 1) * 2
print(f'请求失败(第{attempt+1}次): {e},{wait}秒后重试...')
time.sleep(wait)
return None
解析电影信息时,除了提取电影名和评分,还增加了导演、年份、国家、经典台词、评价人数等字段。
def parse_movie_item(item):
title_tag = item.find('span', class_='title')
title = title_tag.text if title_tag else '未知'
rating_tag = item.find('span', class_='rating_num')
rating = rating_tag.text if rating_tag else '0.0'
quote_tag = item.find('span', class_='inq')
quote = quote_tag.text if quote_tag else ''
bd_tag = item.find('p', class_='')
# 提取导演、年份、国家等更多信息...
return {
'title': title, 'rating': float(rating), 'quote': quote,
'year': year, 'country': country, 'director': director
}
豆瓣Top250一共有10页,每页25部电影。通过循环依次请求每一页,每爬完一页休息1-2秒,防止被封。
def crawl_top250():
all_movies = []
for page in range(10):
url = 'https://movie.douban.com/top250'
params = {'start': page * 25, 'filter': ''}
html = fetch_page(url, params)
if not html:
continue
soup = BeautifulSoup(html, 'html.parser')
items = soup.find_all('div', class_='item')
for item in items:
movie = parse_movie_item(item)
all_movies.append(movie)
print(f'第{page+1}页完成,已累计获取{len(all_movies)}条')
time.sleep(random.uniform(1, 2))
return all_movies
数据存储
数据同时保存为CSV和JSON两种格式。CSV适合用Excel打开查看,JSON适合程序读取。
def save_to_csv(movies, filename='data.csv'):
path = os.path.join(BASE_DIR, filename)
with open(path, 'w', newline='', encoding='utf-8-sig') as f:
writer = csv.writer(f)
writer.writerow(['排名', '电影名', '导演', '年份', '国家', '评分', '评价人数', '经典台词'])
for i, m in enumerate(movies, 1):
writer.writerow([i, m['title'], m['director'], m['year'],
m['country'], m['rating'], m['rating_people'], m['quote']])
保存路径使用os.path.dirname(os.path.abspath(file))获取当前脚本所在目录,这是Python项目获取根目录的经典方法。
数据分析
爬取完数据后可以对数据做多维度的统计分析。
def analyze_ratings(movies):
ratings = [m['rating'] for m in movies]
print(f'平均评分: {sum(ratings)/len(ratings):.2f}')
print(f'9.5分以上: {len([m for m in movies if m["rating"] >= 9.5])}部')
def analyze_country(movies):
country_count = {}
for m in movies:
c = m.get('country', '未知')
country_count[c] = country_count.get(c, 0) + 1
def analyze_year(movies):
# 按年代统计:1990年代、2000年代...
for decade, count in sorted_years:
bar = '█' * (count // 2)
print(f'{decade}年代: {count}部 {bar}')
运行效果
执行python main.py后,控制台逐页显示爬取进度:
开始爬取豆瓣电影Top250...
第1页完成,已累计获取25条
...
第10页完成,已累计获取250条
===== 评分分析 =====
平均评分: 9.23
9.5分以上: 3部
9.0-9.4分: 22部
===== 国家/地区分布 =====
美国: 128部
日本: 45部
中国: 30部
data.csv中的数据(前5条):
| 排名 | 电影名 | 导演 | 年份 | 评分 | 经典台词 |
|---|---|---|---|---|---|
| 1 | 肖申克的救赎 | 弗兰克·德拉邦特 | 1994 | 9.7 | 希望是美好的 |
| 2 | 霸王别姬 | 陈凯歌 | 1993 | 9.6 | 不疯魔不成活 |
| 3 | 阿甘正传 | 罗伯特·泽米吉斯 | 1994 | 9.5 | 生活就像一盒巧克力 |
| 4 | 泰坦尼克号 | 詹姆斯·卡梅隆 | 1997 | 9.4 | 赢得船票是我一生最幸运的事 |
| 5 | 这个杀手不太冷 | 吕克·贝松 | 1994 | 9.4 | 人生总是这么痛苦吗 |
要点总结
一个完整的爬虫项目分为四个步骤:请求网页、解析数据、保存结果、分析数据。多模块组织让代码更清晰,重试机制让爬虫更稳定。项目根目录用os.path.dirname(os.path.abspath(file))获取是通用做法。
扩展思路:加代理IP池防止被封;结合可视化库把评分分布画成图表;改成爬其他网站(知乎热榜、B站排行榜等)。
项目3:Flask个人日记本
Flask个人日记本是一个真正能用的Web应用,从注册登录到写日记、分类管理、搜索、统计,功能一应俱全。这个项目能让你从零开始学习Web开发的核心概念。
项目结构
项目3_Flask个人日记本/
├── app.py # Flask应用主程序
├── init_db.py # 数据库初始化脚本
├── diary.db # SQLite数据库文件
├── requirements.txt # 依赖库
├── templates/ # HTML模板文件夹
│ ├── base.html # 基础模板
│ ├── index.html # 日记列表页
│ ├── edit.html # 新增/编辑日记页
│ ├── login.html # 登录页
│ ├── register.html # 注册页
│ └── stats.html # 统计页
└── static/ # 静态资源文件夹
└── style.css # 样式文件
templates使用模板继承,base.html是基础框架,其他页面继承base.html就自动拥有了导航栏和样式。这种设计避免了重复代码,也是大型Web项目的标准做法。
数据库设计
项目使用SQLite数据库,Python内置的sqlite3模块就可以操作。数据库有三张表:users(用户)、categories(分类)、diaries(日记)。
# init_db.py
import sqlite3
def init_database():
conn = sqlite3.connect(DB_PATH)
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE NOT NULL,
password TEXT NOT NULL
)''')
c.execute('''CREATE TABLE IF NOT EXISTS categories (
id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE NOT NULL
)''')
c.execute('''CREATE TABLE IF NOT EXISTS diaries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
category_id INTEGER,
title TEXT NOT NULL,
content TEXT NOT NULL,
created_at TEXT DEFAULT (datetime('now','localtime')),
FOREIGN KEY (user_id) REFERENCES users(id)
)''')
# 预置默认分类
default_categories = ['日常', '工作', '学习', '旅行', '心情', '其他']
for cat in default_categories:
c.execute('INSERT INTO categories (name) VALUES (?)', (cat,))
conn.commit()
conn.close()
用户认证系统
用户密码使用SHA256加密存储,Flask的session维持登录状态,login_required装饰器保护需要登录才能访问的页面。
from functools import wraps
def hash_password(password):
return hashlib.sha256(password.encode()).hexdigest()
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if 'user_id' not in session:
return redirect(url_for('login'))
return f(*args, **kwargs)
return decorated_function
日记增删改查
日记列表支持按分类筛选和关键词搜索,搜索会同时匹配标题和内容。
@app.route('/')
@login_required
def index():
db = get_db()
category = request.args.get('category')
search = request.args.get('search')
query = 'SELECT d.*, c.name as category_name FROM diaries d LEFT JOIN categories c ON d.category_id = c.id WHERE d.user_id = ?'
params = [session['user_id']]
if category:
query += ' AND d.category_id = ?'
params.append(category)
if search:
query += ' AND (d.title LIKE ? OR d.content LIKE ?)'
params.extend([f'%{search}%', f'%{search}%'])
query += ' ORDER BY d.created_at DESC'
diaries = db.execute(query, params).fetchall()
categories = db.execute('SELECT * FROM categories').fetchall()
return render_template('index.html', diaries=diaries, categories=categories)
新增和编辑共用一个模板,通过mode参数区分模式。
@app.route('/add', methods=['GET', 'POST'])
@login_required
def add():
if request.method == 'POST':
title = request.form['title']
content = request.form['content']
category_id = request.form.get('category_id')
db.execute('INSERT INTO diaries (user_id, category_id, title, content) VALUES (?, ?, ?, ?)',
(session['user_id'], category_id, title, content))
db.commit()
return redirect(url_for('index'))
return render_template('edit.html', diary=None, categories=categories, mode='add')
运行效果
运行python app.py启动服务,访问http://127.0.0.1:5000:
- 首次使用先注册账号
- 登录后进入日记列表页,看到所有日记按时间倒序排列
- 点击"写新日记"输入标题和内容,选择分类后发布
- 日记列表支持按分类筛选和关键词搜索
- 每篇日记可以编辑或删除
- 统计页面展示总日记数和各分类的数量及占比
页面使用了Bootstrap框架,在不同屏幕尺寸下都能正常显示。
要点总结
Flask开发Web应用的核心就是路由、模板、数据库三者配合。SQLite适合小型应用,模板继承避免重复代码,装饰器实现登录校验很优雅。项目根目录用app.root_path获取,这是Flask内置的功能。
扩展思路:加Markdown编辑器支持富文本;添加图片上传功能;部署到服务器上真正用起来。
项目4:命令行天气查询工具
在终端里输入城市名就能看到实时天气,还支持未来多日预报和查询历史记录。这个项目主要锻炼三个技能:调用外部API、用argparse构建命令行工具、模块化组织代码。
项目结构
项目4_命令行天气查询工具/
├── main.py # 主入口
├── weather_api.py # API请求封装
├── formatter.py # 输出格式化(含颜色)
├── history.py # 查询历史记录
├── history.db # SQLite历史数据库
└── requirements.txt # 依赖库
API调用
使用wttr.in这个公共天气API,不需要注册也不需要API Key。format=j1返回JSON,lang=zh用中文显示。
def fetch_weather(city, days=1):
url = f'https://wttr.in/{city}?format=j1&lang=zh'
if days > 1:
url = f'https://wttr.in/{city}?format=j1&lang=zh&days={days}'
resp = requests.get(url, timeout=10)
resp.raise_for_status()
return resp.json()
返回的JSON用parse_current和parse_forecast两个函数分别提取实时数据和预报数据。
def parse_current(data):
current = data['current_condition'][0]
return {
'weather': current['lang_zh'][0]['value'],
'temp': current['temp_C'],
'feels_like': current['FeelsLikeC'],
'humidity': current['humidity'],
'wind_speed': current['windspeedKmph'],
'wind_dir': current['winddir16Point'],
'pressure': current['pressure'],
'visibility': current['visibility'],
'uv_index': current['uvIndex'],
}
彩色终端输出
使用colorama库让输出带上颜色。温度用红色,天气状况用黄色,城市名用绿色。
def format_weather_detail(current):
lines = []
lines.append(f'天气状况: {yellow(current["weather"])}')
lines.append(f'当前温度: {red(current["temp"] + "°C")}')
lines.append(f'体感温度: {current["feels_like"]}°C')
lines.append(f'湿度: {current["humidity"]}%')
lines.append(f'风速: {current["wind_speed"]} km/h ({current["wind_dir"]})')
return '\n'.join(lines)
查询历史
每次查询自动保存到SQLite数据库,通过–history参数查看记录。
def save_query(city, temp='', weather=''):
conn.execute('INSERT INTO queries (city, temp, weather) VALUES (?, ?, ?)',
(city, temp, weather))
运行效果
实时天气查询:
python main.py 成都
====== 成都 天气 ======
天气状况: 多云
当前温度: 28°C
体感温度: 30°C
湿度: 65%
风速: 12 km/h (南)
未来3天预报:
python main.py 北京 --days 3
====== 北京 未来3天预报 ======
7月28日 多云 24°C ~ 35°C
7月29日 晴 26°C ~ 37°C
7月30日 阴转小雨 22°C ~ 31°C
查看历史:
python main.py --history
最近的5次查询记录:
2026-07-28 14:30 | 成都 | 28°C | 多云
要点总结
API调用的核心是requests库的get方法,关键在于理解返回的数据结构。argparse让Python脚本有了专业的命令行界面。colorama给终端输出增加颜色。
扩展思路:接入和风天气等更专业的API;加天气预警功能,极端天气时自动通知。
项目5:Excel自动化报表生成
用Python自动生成Excel报表,可以把几小时的手工操作缩短到几秒钟。这个项目演示了如何用openpyxl库创建专业的Excel报表,包含数据汇总、图表生成、多工作表管理。
项目结构
项目5_Excel自动化报表生成/
├── generate_report.py # 报表生成主程序
├── sample_data.xlsx # 示例源数据
├── 销售报表.xlsx # 生成的完整报表
└── requirements.txt # 依赖库
生成的销售报表包含三个工作表:销售汇总(含柱状图和饼图)、产品销售明细、数据看板。
数据准备
项目内置15条销售数据,涵盖数码、服装、家居三个品类。
| 日期 | 产品 | 品类 | 销量 | 单价 | 销售额 |
|---|---|---|---|---|---|
| 2025-01-05 | 笔记本电脑 | 数码 | 15 | 4999 | 74985 |
| 2025-01-08 | 机械键盘 | 数码 | 30 | 399 | 11970 |
| 2025-01-12 | 羽绒服 | 服装 | 20 | 599 | 11980 |
样式系统
定义了统一的样式字典,所有工作表共用一套样式标准。
STYLE = {
'header_fill': PatternFill(start_color='2F5496', end_color='2F5496', fill_type='solid'),
'header_font': Font(name='SimHei', bold=True, color='FFFFFF'),
'title_font': Font(name='SimHei', bold=True, size=16, color='2F5496'),
'thin_border': Border(
left=Side(style='thin', color='B4B4B4'),
right=Side(style='thin', color='B4B4B4'),
top=Side(style='thin', color='B4B4B4'),
bottom=Side(style='thin', color='B4B4B4')
),
'center': Alignment(horizontal='center', vertical='center'),
'money_format': '#,##0',
}
销售汇总表
按品类分组计算总销量、总销售额、平均单价等,底部显示合计行。
def create_summary_sheet(wb, data):
category_data = {}
for row in data:
cat = row[2]
if cat not in category_data:
category_data[cat] = {'qty': 0, 'amount': 0, 'count': 0}
category_data[cat]['qty'] += row[3]
category_data[cat]['amount'] += row[5]
category_data[cat]['count'] += 1
# 写入汇总数据...
同时插入柱状图和饼图,视觉化展示各品类情况。
chart = BarChart()
chart.title = '各品类销售额对比'
data_ref = Reference(ws, min_col=3, min_row=4, max_row=row_num - 1)
chart.add_data(data_ref, titles_from_data=True)
chart.set_categories(cats_ref)
ws.add_chart(chart, 'A' + str(row_num + 2))
pie = PieChart()
pie.title = '销售额占比分析'
ws.add_chart(pie, 'F' + str(row_num + 2))
运行效果
完整报表已生成: ...\销售报表.xlsx
包含 3 个工作表: 销售汇总, 产品销售明细, 数据看板
汇总数据:
| 品类 | 总销量 | 总销售额 | 平均单价 | 订单数 | 占比 |
|---|---|---|---|---|---|
| 家居 | 143 | 12,417 | 86.83 | 4 | 6.7% |
| 数码 | 140 | 133,910 | 956.50 | 5 | 72.7% |
| 服装 | 215 | 37,935 | 176.44 | 6 | 20.6% |
要点总结
Path(file).parent是处理项目文件路径的推荐方式。openpyxl的样式系统虽然代码多,但能做出很专业的报表。图表支持柱状图、折线图、饼图。
扩展思路:加定时自动生成功能;结合邮件模块自动发送;改成读取数据库生成报表。
项目6:图片批量压缩水印工具
当你有几百张图片需要压缩或加水印时,手动一张张处理效率极低。用Pillow库几行代码就能搞定批量处理。这个工具支持压缩、缩放、水印、格式转换、滤镜等多种功能。
项目结构
项目6_图片批量压缩水印工具/
├── image_tool.py # 主程序
├── input/ # 原始图片目录
├── output/ # 处理后图片目录
└── requirements.txt # 依赖库
input放原始图片,output放处理结果。输入输出分离是批量处理任务的标准模式。
批量压缩
压缩的核心是save方法的quality参数,optimize=True启用优化。
def compress(quality=60):
for img_path in get_images():
img = Image.open(img_path)
out_path = OUTPUT_DIR / f'compressed_{img_path.name}'
img.save(out_path, quality=quality, optimize=True)
批量调整尺寸
支持指定宽度/高度或缩放比例,使用LANCZOS高质量缩放算法。
def resize(width=None, height=None, ratio=None):
if ratio:
new_w, new_h = int(w * ratio), int(h * ratio)
else:
img.thumbnail((rw, rh), Image.LANCZOS)
new_w, new_h = img.size
添加水印
支持五种位置:左上、右上、左下、右下、居中。透明度可调节。
def add_watermark(text='Python', position='br', opacity=128):
font = ImageFont.truetype('C:/Windows/Fonts/simhei.ttf', font_size)
positions = {'tl': (0.05, 0.05), 'tr': (0.75, 0.05),
'bl': (0.05, 0.85), 'br': (0.75, 0.85), 'center': (0.35, 0.45)}
draw.text((x, y), text, fill=(255, 255, 255, opacity), font=font)
格式转换和滤镜
支持jpg/png/bmp/webp互转,滤镜支持模糊、浮雕、锐化、边缘检测等。
运行效果
python image_tool.py compress --quality 50
=== 批量压缩 (quality=50) ===
示例图片1.jpg: 17.6KB -> 5.2KB (-70%)
python image_tool.py watermark --text "我的水印" --pos br
=== 批量添加水印 (pos=br) ===
水印已添加: wm_示例图片1.jpg
要点总结
Pillow的Image.open和Image.save是图像处理的基本操作。输入/输出文件夹分离是标准设计。simhei字体在Windows系统里可直接调用。
扩展思路:加图形界面;生成网站缩略图;集成到Flask做在线处理服务。
项目7:简易数据分析可视化(房价分析)
房价分析是数据分析里最贴近生活的案例。用pandas处理数据、matplotlib画图,分析成都五个区域2020年到2024年的房价变化趋势,最终生成完整的HTML分析报告。
项目结构
项目7_简易数据分析可视化(房价分析)/
├── analysis.py # 分析主程序
├── data/ # 数据文件夹
│ └── housing_data.csv # 25条房价样本数据
├── output/ # 输出文件夹
│ ├── 房价走势图.png
│ ├── 区域房价对比图.png
│ ├── 分布分析图.png
│ ├── 各区域走势对比图.png
│ ├── 相关性热力图.png
│ └── 房价分析报告.html
└── requirements.txt # 依赖库
数据说明
housing_data.csv包含25条模拟数据,覆盖锦江区、武侯区、高新区、天府新区、成华区五个区域。
| 年份 | 区域 | 小区名 | 单价(元/平) | 面积(平) | 总价(万) |
|---|---|---|---|---|---|
| 2020 | 锦江区 | 绿地锦天府 | 28500 | 120 | 342 |
| 2024 | 高新区 | 金融城8号 | 48000 | 140 | 672 |
数据加载与基本统计
import pandas as pd
import matplotlib.pyplot as plt
from pathlib import Path
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
def load_data():
df = pd.read_csv(DATA_PATH, encoding='utf-8')
return df
def basic_statistics(df):
numeric_cols = ['单价(元/平)', '面积(平)', '总价(万)']
stats = df[numeric_cols].describe().round(2)
print(stats)
各区域分析
按区域分组统计,计算均价、最高价、最低价、价格波动情况。
def analyze_by_area(df):
grouped = df.groupby('区域').agg({
'单价(元/平)': ['mean', 'min', 'max', 'std'],
'总价(万)': ['sum', 'mean'],
'面积(平)': 'mean'
}).round(2)
可视化图表
共生成5张专业图表:
- 房价走势图 - 折线图展示五年均价变化
- 区域房价对比图 - 横向柱状图
- 分布分析图 - 箱线图+散点图组合
- 各区域走势对比图 - 五条折线对比
- 相关性热力图 - 单价、面积、总价的相关关系
def plot_price_trend(df):
yearly = df.groupby('年份')['单价(元/平)'].mean()
plt.plot(yearly.index, yearly.values, marker='o', linewidth=2.5, color='#3498db')
plt.fill_between(yearly.index, yearly.values, alpha=0.15, color='#3498db')
plt.savefig(OUTPUT_DIR / '房价走势图.png', dpi=150, bbox_inches='tight')
相关性分析
def correlation_analysis(df):
numeric_df = df[['单价(元/平)', '面积(平)', '总价(万)']]
corr = numeric_df.corr()
# 绘制热力图
plt.matshow(corr, cmap='RdBu_r', vmin=-1, vmax=1)
结果显示:单价与总价强正相关(0.951),面积与总价中正相关(0.727)。
HTML分析报告
所有分析结果和图表自动整合成一份HTML报告,在浏览器中直接打开查看。
运行效果
===== 各区域房价统计 =====
高新区 40000元/平
锦江区 37100元/平
天府新区 30000元/平
武侯区 26800元/平
成华区 23100元/平
===== 年度趋势 =====
2020: 25600元/平
2021: 27900元/平
2022: 31600元/平
2023: 34700元/平
2024: 37200元/平(涨幅约45%)
===== 相关性分析 =====
单价-总价: 0.951 (强相关)
面积-总价: 0.727 (强相关)
要点总结
数据分析标准流程:加载→清洗→分析→可视化。pandas的groupby和agg是分组统计核心,matplotlib的subplots支持多图组合。数据路径用Path(file).parent管理。
扩展思路:接入真实房价API;用scikit-learn做价格预测;做成交互式Web应用。
项目8:定时发送邮件提醒
每天早上发送天气预报、定时提醒、定期发送报表——这个项目涉及smtplib发邮件、schedule定时任务、配置分离、日志记录、HTML模板等多个知识点。
项目结构
项目8_定时发送邮件提醒/
├── main.py # 主程序
├── config.py # 邮箱配置
├── email_templates.py # 邮件模板
├── mail.log # 运行日志
└── requirements.txt # 依赖库
配置说明
需要在config.py里填写真实的邮箱信息。QQ邮箱需要开启SMTP服务并生成16位授权码。
SMTP_CONFIG = {
'server': os.getenv('SMTP_SERVER', 'smtp.qq.com'),
'port': int(os.getenv('SMTP_PORT', 587)),
'sender': os.getenv('SMTP_SENDER', 'your_email@qq.com'),
'password': os.getenv('SMTP_PASSWORD', 'your_auth_code'),
}
发送邮件
smtplib是Python内置库,不需要额外安装。starttls()启动加密传输。
def send_email(subject, body, receiver=None, email_type='plain'):
msg = MIMEText(body, 'plain', 'utf-8')
msg['From'] = Header(sender)
msg['To'] = Header(receiver)
msg['Subject'] = Header(subject, 'utf-8')
with smtplib.SMTP(server, port) as s:
s.starttls()
s.login(sender, password)
s.sendmail(sender, [receiver], msg.as_string())
HTML邮件模板
支持多种模板:通用HTML模板、天气日报模板、待办提醒模板。
def weather_template(city, temp, weather):
return f'''<html><body>
<div style="background:linear-gradient(135deg,#667eea,#764ba2);color:white;padding:30px;text-align:center;">
<h1>{city}</h1><p style="font-size:48px;">{temp}°C</p>
<p>{weather}</p></div></body></html>'''
定时任务
使用schedule库,每天9点自动发送。
schedule.every().day.at('09:00').do(send_daily_reminder)
while True:
schedule.run_pending()
time.sleep(30)
日志系统
使用logging模块,同时输出到控制台和文件。
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s [%(levelname)s] %(message)s',
handlers=[logging.FileHandler('mail.log', encoding='utf-8'), logging.StreamHandler()]
)
运行效果
1. 发送测试邮件
2. 设置每日定时发送(9:00)
3. 查看运行状态
选1立即发送HTML格式测试邮件,选2设置定时任务,选3查看配置和日志。
要点总结
配置分离和日志记录是工程化基础。smtplib内置可用,schedule让定时任务变简单。HTML模板让邮件更美观。
扩展思路:结合天气API自动发送每日天气;结合Excel模块发送报表;做邮件订阅系统。
项目9:命令行待办事项清单
涉及增删改查、数据持久化、命令行交互设计、分层架构。升级版加入了优先级、分类、截止日期、搜索和统计。
项目结构
项目9_命令行待办事项清单/
├── cli.py # 命令行交互层
├── logic.py # 业务逻辑层
├── tasks.json # 数据存储
└── requirements.txt # 依赖库
cli.py负责交互,logic.py负责数据处理。分层设计让代码更清晰,换界面不影响业务逻辑。
数据模型
task = {
'id': 1,
'title': '完成毕业设计',
'priority': 'high', # high/medium/low
'category': '学习', # 自定义分类
'due_date': '2026-08-15', # 截止日期
'done': False,
'created_at': '2026-07-28 14:30'
}
数据存储在tasks.json中,JSON格式方便查看和手动编辑。
业务逻辑
class TaskManager:
def __init__(self):
self.tasks = self._load()
def add(self, title, priority='medium', category='默认', due_date=None):
task = {
'id': self._next_id(), 'title': title,
'priority': priority, 'category': category,
'due_date': due_date or '', 'done': False,
}
self.tasks.append(task)
self._save()
def list_tasks(self, filter_by=None, category=None, priority=None, sort_by='id'):
# 支持多维度筛选和排序
def search(self, keyword):
# 按关键词搜索标题和分类
def stats(self):
# 统计完成率、分类分布、优先级分布
命令行接口
使用argparse的子命令系统,支持add/list/done/delete/search/stats。
p_add = sub.add_parser('add', help='添加任务')
p_add.add_argument('title')
p_add.add_argument('--priority', choices=['high', 'medium', 'low'], default='medium')
p_add.add_argument('--category', default='默认')
p_add.add_argument('--due', help='截止日期 (YYYY-MM-DD)')
p_list = sub.add_parser('list', help='列出任务')
p_list.add_argument('--filter', choices=['all', 'done', 'pending'], default='all')
p_list.add_argument('--category')
p_list.add_argument('--priority', choices=['high', 'medium', 'low'])
p_list.add_argument('--sort', choices=['id', 'priority', 'due_date'], default='id')
运行效果
python cli.py add "写Python项目" --priority high --category 学习 --due 2026-08-01
已添加任务 [#2]: 写Python项目
python cli.py list --filter pending --sort priority
ID 优先级 分类 状态 截止日期 任务
2 高 学习 待办 2026-08-01 写Python项目
1 低 生活 待办 - 买菜
python cli.py stats
====== 任务统计 ======
总任务: 12
已完成: 5 (41.7%)
按分类: 学习: 5, 工作: 4, 生活: 1
要点总结
分层设计(cli+logic)让代码清晰可扩展。JSON持久化适合小规模数据。argparse支持子命令和参数类型检查。数据文件路径用Path(file).parent确定。
扩展思路:加系统通知提醒功能;云端同步;做Web版。
项目10:QR码生成器解码器
用Python生成和解码二维码,支持普通二维码、带Logo的二维码、WiFi配置二维码、电子名片二维码,还能用摄像头实时扫描。
项目结构
项目10_QR码生成器解码器/
├── qr_tool.py # 主程序
├── output/ # 二维码输出目录
└── requirements.txt # 依赖库
生成普通二维码
def generate_qr(data, filename='qr.png', fill_color='black', back_color='white', with_logo=False):
qr = qrcode.QRCode(
version=1, error_correction=qrcode.constants.ERROR_CORRECT_H,
box_size=10, border=4,
)
qr.add_data(data)
qr.make(fit=True)
img = qr.make_image(fill_color=fill_color, back_color=back_color)
if with_logo:
# 在中间添加Logo图案
logo = Image.new('RGB', (logo_size, logo_size), '#3498db')
img.paste(logo, ((img.width - logo_size) // 2, (img.height - logo_size) // 2))
path = OUTPUT_DIR / filename
img.save(path)
error_correction参数设置为H级(最高纠错),允许30%破损,这是加Logo的前提。
生成WiFi二维码
手机扫描后自动连接WiFi。
def generate_wifi_qr(ssid, password, encryption='WPA'):
data = f'WIFI:T:{encryption};S:{ssid};P:{password};;'
return generate_qr(data, 'wifi_qr.png')
生成电子名片
手机扫描后直接保存联系人。
def generate_vcard_qr(name, phone, email=''):
data = f'BEGIN:VCARD\nVERSION:3.0\nFN:{name}\nTEL:{phone}\nEMAIL:{email}\nEND:VCARD'
return generate_qr(data, 'vcard_qr.png')
解码二维码
使用opencv的QRCodeDetector,同时检测和解码。
def decode_qr(image_path):
img = cv2.imread(str(path))
detector = cv2.QRCodeDetector()
data, bbox, _ = detector.detectAndDecode(img)
if data:
print(f'解码成功!内容: {data}')
# 自动识别类型
if data.startswith('WIFI:'): print('类型: WiFi 配置')
elif data.startswith('BEGIN:VCARD'): print('类型: 电子名片')
摄像头实时扫描
调用电脑摄像头实时扫描,在屏幕上绘制二维码边框辅助对准。
def decode_from_camera():
cap = cv2.VideoCapture(0)
detector = cv2.QRCodeDetector()
while True:
ret, frame = cap.read()
data, bbox, _ = detector.detectAndDecode(frame)
if data:
print(f'扫描成功!内容: {data}')
break
if bbox is not None:
# 绘制绿色边框
for i in range(len(bbox)):
cv2.line(frame, tuple(bbox[i][0]), tuple(bbox[(i+1) % len(bbox)][0]),
(0, 255, 0), 3)
cv2.imshow('QR Scanner', frame)
if cv2.waitKey(1) & 0xFF == 27: break
运行效果
生成二维码:
python qr_tool.py generate "https://www.python.org" --logo
二维码已生成: output\qr.png
生成WiFi二维码:
python qr_tool.py wifi "MyWiFi" "password123"
二维码已生成: output\wifi_qr.png
解码二维码:
python qr_tool.py decode output/qr.png
解码成功!内容: https://www.python.org
类型: 网址链接
摄像头扫描:
python qr_tool.py scan
扫描成功!内容: https://www.python.org
要点总结
qrcode库负责生成,opencv负责解码,Pillow负责美化。ERROR_CORRECT_H是加Logo的关键。opencv的QRCodeDetector能同时检测和解码。
扩展思路:批量生成名片二维码;做网页版在线生成器;做成手机App。
总结
这9个项目从爬虫、Web开发、API调用、办公自动化、图像处理、数据分析、邮件服务、命令行工具到二维码应用,几乎涵盖了Python开发的全部主要方向。每个项目都可以作为毕业设计的基础,加上自己的业务逻辑就能变成完整作品。
更多推荐



所有评论(0)