Python 实战项目

学了 17 篇基础,是时候把它们串起来做点真东西了。这一章给三个完整、可运行的项目——网页爬虫、数据分析、命令行工具,每个都从需求出发,给出完整代码、运行结果和要点讲解。三个项目覆盖了 Python 最常见的三个应用方向:网络采集、数据处理、自动化脚本。建议你把代码复制到本地亲手跑一遍,再试着改一改需求,这才是真正"上手"的感觉。

实战 1:网页爬虫(requests + BeautifulSoup)

需求:抓取 quotes.toscrape.com(一个专门给爬虫练习用的网站)首页全部名言和作者,保存到 CSV 文件。

涉及知识:HTTP 请求、HTML 解析(CSS 选择器)、异常处理、礼貌爬取(延迟 + User-Agent)、CSV 写入。先装依赖:pip install requests beautifulsoup4。

# spider.py — 网页爬虫:抓取名言网(quotes.toscrape.com)的名言和作者
# 依赖安装:pip install requests beautifulsoup4
import requests
from bs4 import BeautifulSoup
import time
import csv

URL = "https://quotes.toscrape.com/"
HEADERS = {"User-Agent": "Mozilla/5.0 (compatible; MyBot/1.0)"}
DELAY = 1  # 每次请求间隔 1 秒,做个礼貌的爬虫


def fetch(url):
    """发起 HTTP 请求,返回 BeautifulSoup 对象;失败返回 None"""
    try:
        resp = requests.get(url, headers=HEADERS, timeout=10)
        resp.raise_for_status()       # 4xx / 5xx 会抛 HTTPError
        return BeautifulSoup(resp.text, "html.parser")
    except requests.RequestException as e:
        print(f"[错误] 请求失败: {e}")
        return None


def parse(soup):
    """从 HTML 中提取感兴趣的数据(CSS 选择器定位)"""
    items = []
    for q in soup.select(".quote"):
        text = q.select_one(".text").get_text(strip=True)
        author = q.select_one(".author").get_text(strip=True)
        items.append({"text": text, "author": author})
    return items


def save(items, path="quotes.csv"):
    """把结果写入 CSV 文件"""
    with open(path, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=["text", "author"])
        writer.writeheader()
        writer.writerows(items)
    print(f"[完成] 已保存 {len(items)} 条到 {path}")


def main():
    print(f"[开始] 爬取 {URL}")
    time.sleep(DELAY)                 # 礼貌延迟,别给服务器压力
    soup = fetch(URL)
    if not soup:
        return
    items = parse(soup)
    print(f"[预览] 共 {len(items)} 条,前 3 条:")
    for it in items[:3]:
        print(f"  - {it['author']}: {it['text'][:40]}")
    save(items)


if __name__ == "__main__":
    main()
# 输出:
# [开始] 爬取 https://quotes.toscrape.com/
# [预览] 共 10 条,前 3 条:
#   - Albert Einstein: The world as we have created it is a proc
#   - J.K. Rowling: It is our choices, Harry, that show what we
#   - Albert Einstein: There are only two ways to live your life
# [完成] 已保存 10 条到 quotes.csv

要点讲解:

实战 2:销售数据分析(pandas)

需求:给定一份销售流水(日期 / 商品 / 数量 / 单元),算出每种商品的总销量、总销售额,找出销售额 Top 3,把汇总结果导出成新 CSV。

涉及知识:DataFrame 构建 / 读取、列运算、统计描述、布尔筛选、排序、分组聚合 groupby、CSV 导出。先装依赖:pip install pandas。

# analysis.py — 销售数据分析:读 CSV → 统计 → 筛选排序 → 分组聚合 → 导出
# 依赖安装:pip install pandas
import pandas as pd

# 1. 准备数据(实际项目用 df = pd.read_csv("sales.csv"))
data = {
    "日期": ["2024-01-01", "2024-01-01", "2024-01-02", "2024-01-02", "2024-01-03",
             "2024-01-03", "2024-01-03", "2024-01-04", "2024-01-04", "2024-01-05"],
    "商品": ["苹果", "香蕉", "苹果", "橙子", "香蕉",
             "苹果", "橙子", "香蕉", "苹果", "橙子"],
    "数量": [10, 8, 15, 6, 12, 20, 9, 14, 18, 7],
    "单价": [5.0, 3.0, 5.0, 4.0, 3.0, 5.0, 4.0, 3.0, 5.0, 4.0],
}
df = pd.DataFrame(data)
df["金额"] = df["数量"] * df["单价"]      # 新增一列:销售额

print("=== 原始数据(前 5 行)===")
print(df.head())
# 输出:
#           日期  商品  数量  单价    金额
# 0  2024-01-01  苹果   10  5.0   50.0
# 1  2024-01-01  香蕉    8  3.0   24.0
# 2  2024-01-02  苹果   15  5.0   75.0
# 3  2024-01-02  橙子    6  4.0   24.0
# 4  2024-01-03  香蕉   12  3.0   36.0

# 2. 统计描述:一眼看分布(均值、最大最小、标准差)
print("\n=== 数值列统计描述 ===")
print(df[["数量", "金额"]].describe())
# 输出:
#             数量        金额
# count  10.00000  10.000000
# mean   11.90000  55.300000
# std     4.72464  22.541535
# min     6.00000  24.000000
# 25%     8.75000  36.000000
# 50%    11.50000  50.000000
# 75%    15.50000  75.000000
# max    20.00000  90.000000

# 3. 筛选:金额大于 50 的订单
big = df[df["金额"] > 50]
print("\n=== 金额 > 50 的订单 ===")
print(big[["日期", "商品", "金额"]])
# 输出:
#           日期  商品    金额
# 2  2024-01-02  苹果   75.0
# 5  2024-01-03  苹果  100.0
# 8  2024-01-04  苹果   90.0

# 4. 排序:按金额降序,取 Top 3
top3 = df.sort_values("金额", ascending=False).head(3)
print("\n=== 销售额 Top 3 ===")
print(top3[["商品", "数量", "金额"]])
# 输出:
#   商品  数量    金额
# 5  苹果   20  100.0
# 8  苹果   18   90.0
# 2  苹果   15   75.0

# 5. 分组聚合:按商品统计总销量、总销售额、订单数
summary = df.groupby("商品").agg(
    总数量=("数量", "sum"),
    总销售额=("金额", "sum"),
    订单数=("金额", "count"),
).reset_index()
print("\n=== 按商品汇总 ===")
print(summary)
# 输出:
#   商品  总数量  总销售额  订单数
# 0  橙子     22    88.0      3
# 1  苹果     63   315.0      4
# 2  香蕉     34   102.0      3

# 6. 导出结果到 CSV(utf-8-sig 让 Excel 打开不乱码)
summary.to_csv("sales_summary.csv", index=False, encoding="utf-8-sig")
print("\n已导出到 sales_summary.csv")
# 输出:
# 已导出到 sales_summary.csv

要点讲解:

实战 3:命令行工具 todo(argparse)

需求:做一个待办管理 CLI,支持三个子命令——add 添加、list 列出、done 标记完成,数据存 JSON 文件。能脱离 Python 解释器,像真实工具那样在终端用。

涉及知识:标准库 argparse(子命令、参数解析、自动帮助)、JSON 读写、文件路径、datetime 格式化。无需第三方依赖。

# todo.py — 简易待办管理 CLI(支持 add / list / done 三个子命令)
# 无需第三方依赖,纯标准库
import argparse
import json
import os
from datetime import datetime

TODO_FILE = "todos.json"


def load_todos():
    """从文件读取待办列表;文件不存在返回空列表"""
    if os.path.exists(TODO_FILE):
        with open(TODO_FILE, "r", encoding="utf-8") as f:
            return json.load(f)
    return []


def save_todos(todos):
    """保存待办列表到文件"""
    with open(TODO_FILE, "w", encoding="utf-8") as f:
        json.dump(todos, f, ensure_ascii=False, indent=2)


def cmd_add(args):
    todos = load_todos()
    todo = {
        "id": len(todos) + 1,
        "title": args.title,
        "done": False,
        "created": datetime.now().strftime("%Y-%m-%d %H:%M"),
    }
    todos.append(todo)
    save_todos(todos)
    print(f"已添加: [{todo['id']}] {todo['title']}")


def fmt(t):
    """格式化一条待办为字符串"""
    mark = "x" if t["done"] else " "
    return f"[{mark}] {t['id']}. {t['title']}  ({t['created']})"


def cmd_list(args):
    todos = load_todos()
    items = todos if args.all else [t for t in todos if not t["done"]]
    if not items:
        print("(空空如也)")
        return
    for t in items:
        print(fmt(t))


def cmd_done(args):
    todos = load_todos()
    for t in todos:
        if t["id"] == args.id:
            t["done"] = True
            save_todos(todos)
            print(f"已完成: {t['title']}")
            return
    print(f"未找到 id={args.id} 的待办")


def main():
    parser = argparse.ArgumentParser(
        description="简易待办管理 CLI",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="示例:\n"
               "  python todo.py add 买牛奶\n"
               "  python todo.py list\n"
               "  python todo.py list --all\n"
               "  python todo.py done 1\n",
    )
    sub = parser.add_subparsers(dest="command", required=True, help="子命令")

    p_add = sub.add_parser("add", help="添加一条待办")
    p_add.add_argument("title", help="待办内容")

    p_list = sub.add_parser("list", help="列出未完成待办")
    p_list.add_argument("--all", action="store_true", help="显示全部(含已完成)")

    p_done = sub.add_parser("done", help="标记某条为已完成")
    p_done.add_argument("id", type=int, help="待办 id")

    args = parser.parse_args()
    if args.command == "add":
        cmd_add(args)
    elif args.command == "list":
        cmd_list(args)
    elif args.command == "done":
        cmd_done(args)


if __name__ == "__main__":
    main()

# === 用法示例(在终端依次运行)===
# $ python todo.py add 买牛奶
# 已添加: [1] 买牛奶
# $ python todo.py add 写季度报告
# 已添加: [2] 写季度报告
# $ python todo.py list
# [ ] 1. 买牛奶  (2024-06-01 10:30)
# [ ] 2. 写季度报告  (2024-06-01 10:31)
# $ python todo.py done 1
# 已完成: 买牛奶
# $ python todo.py list
# [ ] 2. 写季度报告  (2024-06-01 10:31)
# $ python todo.py list --all
# [x] 1. 买牛奶  (2024-06-01 10:30)
# [ ] 2. 写季度报告  (2024-06-01 10:31)
# $ python todo.py -h
# usage: todo.py [-h] {add,list,done} ...
# 简易待办管理 CLI

要点讲解:

小结

三个项目分别对应 Python 三大主力场景:爬虫(采集数据)、数据分析(理解数据)、CLI 工具(自动化日常)。它们都用到了前面学的基础——函数、字典、文件读写、异常处理、模块——只是组合起来解决真实问题。建议你至少把其中一个改造成自己的版本(换爬取目标、换数据集、给 todo 加新子命令),做过一遍比读十遍更扎实。

恭喜!到这里 Python 系列就真正完结了。接下来挑一个方向深入——Web 后端(Django / FastAPI)、数据分析深入(pandas + 可视化)、AI(llama-index / transformers)、自动化(把日常重复工作交给脚本)——边做边学,进步最快。

← 上一篇 Python 日期时间

返回 Python 教程目录

✈️💬