Python 爬虫数据存储:TXT 文本存储指南

爬虫小白练手、临时项目存中间量、不想折腾依赖时,TXT 是你逃不开的「轻量级救星」——但怎么存才既快又清晰不丢数据?这篇给你讲透。

1. 为什么选 TXT?

别小瞧这个上世纪就有的格式,它有三个不可替代的核心优势:

  • 零门槛上手:不需要装任何库(json/csv/pandas 啥的都不用),Python 原生 open() 就能用
  • 全平台通吃:Windows 记事本、Mac 文本编辑、Linux cat 命令,随便打开随便看
  • 绝对轻量无冗余:没有 schema、没有表头、没有编码锁(虽然要强制指定utf-8防乱码)

当然缺点也很明显:

  • 没办法快速按「评分>9」「科幻片」这种条件筛选
  • 很难自动验证数据完整性(比如漏爬了上映时间会不会发现?)
  • 大文件打开卡顿,修改效率极低

适合场景

✅ 爬虫练手验证爬取结果
✅ 短期临时存 JSON/CSV 之前的「过渡数据」
✅ 简单的调试日志记录
❌ 结构化数据检索与统计
❌ 长期数据持久化
❌ 百万级以上数据量处理


2. 实战示例:爬取示例电影网站存 TXT

直接用真实公开的爬虫练习网站 https://ssr1.scrape.center/ 演示,爬首页10部电影的「名称、类型、上映时间、评分」,最后生成易读、带分隔线、UTF-8编码的 TXT。

2.1 完整可运行代码

import requests
from bs4 import BeautifulSoup
from typing import List, Dict
from datetime import datetime  # 后面扩展追加模式会用到

def scrape_movies() -> List[Dict]:
    """爬取练习网站首页10部电影的结构化数据"""
    # 目标URL
    base_url = "https://ssr1.scrape.center/"
    # 伪装浏览器,防止被简单的反爬拦截
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
    }

    try:
        # 发送GET请求,设置10秒超时防卡死
        response = requests.get(base_url, headers=headers, timeout=10)
        # 主动抛出HTTP错误(比如404、500)
        response.raise_for_status()

        # 解析HTML
        soup = BeautifulSoup(response.text, 'html.parser')
        movies = []

        # 遍历每部电影的卡片
        for item in soup.select('.el-card'):
            # 提取数据,用strip()去除首尾空格
            name = item.select_one('h2').text.strip()
            categories = [c.text.strip() for c in item.select('.categories button')]
            published_at = item.select_one('.info:contains("上映")').text.split(':')[-1].strip()
            score = item.select_one('.score').text.strip()

            # 组装成字典存入列表
            movies.append({
                'name': name,
                'categories': categories,
                'published_at': published_at,
                'score': score
            })

        return movies

    except requests.exceptions.RequestException as e:
        print(f"请求失败,原因:{e}")
        return []
    except AttributeError as e:
        print(f"解析HTML失败,检查选择器:{e}")
        return []

def save_to_txt(data: List[Dict], filename: str = 'movies_output.txt'):
    """将结构化电影数据保存为易读的TXT文件"""
    if not data:
        print("没有可保存的数据")
        return

    try:
        # 核心:with语句自动管理文件资源,不用手动f.close()
        # 核心:encoding='utf-8'强制指定,解决Windows中文乱码问题
        with open(filename, 'w', encoding='utf-8') as f:
            # 遍历每部电影,结构化输出
            for idx, movie in enumerate(data, 1):
                f.write(f"【第{idx}部电影】\n")
                f.write(f"电影名称:{movie['name']}\n")
                f.write(f"类型标签:{', '.join(movie['categories'])}\n")
                f.write(f"上映时间:{movie['published_at']}\n")
                f.write(f"豆瓣评分(示例):{movie['score']}\n")
                f.write("=" * 60 + "\n\n")  # 加两行换行,增加可读性

        print(f"✅ 成功保存{len(data)}部电影数据到:{filename}")

    except IOError as e:
        print(f"❌ 文件保存失败,原因:{e}")

if __name__ == '__main__':
    # 执行爬取和保存
    movies = scrape_movies()
    save_to_txt(movies)

2.2 代码亮点拆解

相比网上随便搜的「入门TXT爬虫代码」,这版做了几个实用改进:

  1. 类型注解清晰-> List[Dict] 这种标注,写的时候不容易传参错,看的时候也一眼懂返回值
  2. 完善的错误分支:分成「请求失败」和「解析失败」,调试的时候不用瞎猜
  3. 强制指定UTF-8编码:彻底解决Windows记事本默认GBK打开乱码的问题
  4. 带序号、标签、强分隔线的输出:肉眼扫一遍就能快速找到想看的电影
  5. 先检查数据再保存:避免生成空文件

3. 必懂的Python TXT文件操作

前面实战用了 w 写入模式,但TXT还有很多其他玩法,核心是掌握打开模式、with语句、编码规范这三点。

3.1 核心打开模式对照表

模式全称核心行为必知细节适用场景
rread只读打开现有文件文件不存在会报错读取爬虫生成的TXT数据
wwrite覆盖式写入文件不存在会创建,存在会清空原内容重写第一次生成完整的结构化TXT
aappend追加式写入文件不存在会创建,存在会在文件末尾加内容爬虫增量爬取、日志记录
r+read+write读写打开现有文件覆盖是从当前指针位置开始(默认开头)小范围修改已有TXT

⚠️ 新手踩坑提醒:不要用 w 模式去「修改已有文件的某一行」——直接用 r+ 或者「读取全部→修改→覆盖写入」更安全。

3.2 高级常用操作

3.2.1 增量追加模式(爬虫爬多页时最常用)

def append_to_txt(movie: Dict, filename: str = 'movies_append.txt'):
    """单条追加电影数据到TXT"""
    try:
        with open(filename, 'a', encoding='utf-8') as f:
            # 加当前时间戳,方便知道是哪次爬取的
            f.write(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] ")
            f.write(f"电影:{movie['name']} | 类型:{', '.join(movie['categories'])} | 评分:{movie['score']}\n")
    except IOError as e:
        print(f"追加失败:{e}")

# 调用示例
if movies:
    append_to_txt(movies[0])

3.2.2 批量写入提升性能

如果要写10000条以上的数据,别用 for 循环一条一条 f.write()——用 f.writelines() 更省时间:

# 先生成所有要写的字符串列表
lines_to_write = []
for idx, movie in enumerate(movies, 1):
    lines_to_write.append(f"【第{idx}部】{movie['name']}\n")
    lines_to_write.append(f"类型:{', '.join(movie['categories'])}\n")
    lines_to_write.append("-"*30 + "\n")

# 一次性写入
with open('bulk_movies.txt', 'w', encoding='utf-8') as f:
    f.writelines(lines_to_write)

4. 安全避坑指南

虽然TXT很简单,但也有几个容易踩的「小雷」:

  1. 乱码雷:不管什么平台,只要是文本文件就必须加 encoding='utf-8'
  2. 路径雷:Windows用 \ 分隔路径,Mac/Linux用 /——用 pathlib.Path 自动适配所有平台:
    from pathlib import Path
    
    # 创建输出文件夹(如果不存在的话)
    output_dir = Path("output")
    output_dir.mkdir(exist_ok=True)  # exist_ok=True避免文件夹已存在时报错
    
    # 生成安全的文件路径
    safe_file = output_dir / "safe_movies.txt"
  3. 权限雷:如果存的是敏感数据,给文件加个权限:
    import os
    
    if os.name == "posix":  # 仅Mac/Linux生效
        os.chmod(safe_file, 0o600)  # 仅文件所有者可读可写

5. 总结

TXT 不是万能的,但在「快速验证、临时过渡、轻量日志」这三个场景下,它绝对是性价比最高的选择。如果后续需要结构化检索,可以很容易把TXT转成JSON/CSV或者存入SQLite数据库——这也是我们下一篇要讲的内容~

你平时用TXT存过什么爬虫数据?欢迎在评论区交流😉