Python能做什么项目?从爬虫到Web应用,从数据分析到自动化办公,Python几乎无所不能。这篇文章整理了9个有趣又实用的小项目,每个都配有完整的项目结构和代码讲解,适合毕业设计或者自学练手。

完整源码链接

https://pan.quark.cn/s/1e54aa2ae950

项目列表

日记本项目


    项目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肖申克的救赎弗兰克·德拉邦特19949.7希望是美好的
    2霸王别姬陈凯歌19939.6不疯魔不成活
    3阿甘正传罗伯特·泽米吉斯19949.5生活就像一盒巧克力
    4泰坦尼克号詹姆斯·卡梅隆19979.4赢得船票是我一生最幸运的事
    5这个杀手不太冷吕克·贝松19949.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:

    1. 首次使用先注册账号
    2. 登录后进入日记列表页,看到所有日记按时间倒序排列
    3. 点击"写新日记"输入标题和内容,选择分类后发布
    4. 日记列表支持按分类筛选和关键词搜索
    5. 每篇日记可以编辑或删除
    6. 统计页面展示总日记数和各分类的数量及占比

    页面使用了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笔记本电脑数码15499974985
    2025-01-08机械键盘数码3039911970
    2025-01-12羽绒服服装2059911980

    样式系统

    定义了统一的样式字典,所有工作表共用一套样式标准。

    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 个工作表: 销售汇总, 产品销售明细, 数据看板
    

    汇总数据:

    品类总销量总销售额平均单价订单数占比
    家居14312,41786.8346.7%
    数码140133,910956.50572.7%
    服装21537,935176.44620.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锦江区绿地锦天府28500120342
    2024高新区金融城8号48000140672

    数据加载与基本统计

    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张专业图表:

    1. 房价走势图 - 折线图展示五年均价变化
    2. 区域房价对比图 - 横向柱状图
    3. 分布分析图 - 箱线图+散点图组合
    4. 各区域走势对比图 - 五条折线对比
    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开发的全部主要方向。每个项目都可以作为毕业设计的基础,加上自己的业务逻辑就能变成完整作品。

    Logo

    这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

    更多推荐