前言
爬虫开发的核心目标是获取有价值的数据,而数据保存是将爬取结果落地、实现数据复用的关键环节。TXT 文件作为最基础、通用的文本存储格式,具有兼容性强、读写简单、无需额外依赖的特点,是爬虫数据保存的入门首选。本文将系统讲解爬虫数据保存为 TXT 文件的核心方法,从基础文本写入、结构化数据格式化,到批量数据保存、异常处理,结合 **豆瓣电影 Top250** 实战案例,完整演示不同场景下 TXT 文件的保存技巧,帮助开发者掌握数据持久化的核心逻辑。
摘要
本文聚焦爬虫数据保存为 TXT 文件的全流程实战,详细解析 Python 文件操作的核心 API(open ()、write ()、writelines () 等),对比不同写入模式(w/a/x)的适用场景,通过豆瓣电影 Top250 爬取案例,演示 “单行写入、多行批量写入、结构化数据格式化写入、追加写入” 四种 TXT 文件保存方式。文中包含文件操作核心参数表格、完整代码示例及输出结果解析,旨在帮助读者理解 TXT 文件保存的底层逻辑,掌握适配不同爬虫场景的数据持久化方法。
一、TXT 文件保存核心基础
1.1 Python 文件操作核心 API
爬虫数据保存为 TXT 文件的底层依赖 Python 内置的文件操作函数,核心 API 及功能如下:
| API / 参数 | 核心功能 | 常用取值 / 示例 | 注意事项 |
|---|---|---|---|
| open() | 打开文件,返回文件对象 | open("data.txt", "w", encoding="utf-8") | 必须指定编码(utf-8)避免中文乱码 |
| mode(打开模式) | 定义文件操作类型 | w(覆盖写入)、a(追加写入)、x(创建新文件)、r(只读) | w 模式会清空原有文件,a 模式保留原有内容 |
| write() | 写入单行字符串 | f.write("豆瓣电影Top250:肖申克的救赎\n") | 需手动添加换行符(\n)实现换行 |
| writelines() | 写入多行字符串列表 | f.writelines(["第一行\n", "第二行\n"]) | 列表中每个元素需自行包含换行符 |
| close() | 关闭文件对象 | f.close() | 必须关闭文件,否则数据可能未写入磁盘 |
| with 语句 | 自动管理文件上下文(无需手动 close) | with open(...) as f: f.write(...) | 推荐使用,避免忘记关闭文件 |
1.2 核心打开模式对比
不同的文件打开模式适配不同的保存场景,需根据需求选择:
| 模式 | 核心行为 | 适用场景 | 风险点 |
|---|---|---|---|
| w(写入) | 若文件不存在则创建,存在则清空原有内容 | 首次保存数据、覆盖更新数据 | 误操作会清空已有数据 |
| a(追加) | 若文件不存在则创建,存在则在末尾追加内容 | 多页爬虫数据分批保存、增量爬取 | 需注意换行,避免数据粘连 |
| x(创建) | 仅创建新文件,若文件已存在则报错 | 确保文件唯一性(如首次保存) | 重复执行会抛出 FileExistsError |
| r+(读写) | 可读可写,不清空原有内容 | 需同时读取和修改文件 | 写入位置需通过 seek () 控制,易出错 |
二、TXT 文件保存实战案例
2.1 实战准备:爬取豆瓣电影 Top250 基础数据
首先实现豆瓣电影 Top250 数据爬取,提取核心字段(排名、片名、评分、简介),为后续保存做准备:
python
运行
import urllib.request import urllib.error from bs4 import BeautifulSoup # 爬取豆瓣电影Top250基础数据 def crawl_douban_movie(): url = "https://movie.douban.com/top250" 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: request = urllib.request.Request(url=url, headers=headers) response = urllib.request.urlopen(request, timeout=15) html = response.read().decode("utf-8") # 解析数据 soup = BeautifulSoup(html, "lxml") movie_items = soup.find_all("div", class_="item") movie_list = [] for idx, item in enumerate(movie_items): movie = {} # 排名 movie["rank"] = idx + 1 # 片名 title_tag = item.find("span", class_="title") movie["title"] = title_tag.text.strip() if title_tag else "" # 评分 score_tag = item.find("span", class_="rating_num") movie["score"] = score_tag.text.strip() if score_tag else "" # 简介 quote_tag = item.find("span", class_="inq") movie["quote"] = quote_tag.text.strip() if quote_tag else "无简介" movie_list.append(movie) return movie_list except Exception as e: print(f"爬取数据失败:{e}") return [] # 执行爬取,获取数据 movie_data = crawl_douban_movie() print(f"成功爬取 {len(movie_data)} 条电影数据")爬取结果(控制台输出)
plaintext
成功爬取 25 条电影数据2.2 方式 1:基础单行写入(逐行保存数据)
代码实现
python
运行
# 方式1:基础单行写入(w模式,覆盖写入) def save_to_txt_single_line(movie_list): # 打开文件(w模式,utf-8编码) with open("豆瓣电影Top250_单行写入.txt", "w", encoding="utf-8") as f: # 写入文件标题 f.write("豆瓣电影Top250数据\n") f.write("="*50 + "\n") # 逐行写入每条电影数据 for movie in movie_list: line = f"排名:{movie['rank']} | 片名:{movie['title']} | 评分:{movie['score']} | 简介:{movie['quote']}\n" f.write(line) print("单行写入完成,文件保存路径:豆瓣电影Top250_单行写入.txt") # 执行保存 save_to_txt_single_line(movie_data)输出结果(TXT 文件内容节选)
plaintext
豆瓣电影Top250数据 ================================================== 排名:1 | 片名:肖申克的救赎 | 评分:9.7 | 简介:希望让人自由。 排名:2 | 片名:霸王别姬 | 评分:9.6 | 简介:风华绝代。 排名:3 | 片名:阿甘正传 | 评分:9.5 | 简介:一部美国近现代史。 排名:4 | 片名:泰坦尼克号 | 评分:9.5 | 简介:失去的才是永恒的。 ...原理解析
- 使用
with语句自动管理文件上下文,无需手动调用close(),避免文件句柄泄露; w模式为覆盖写入,每次执行会清空原有文件内容,适合首次保存数据;- 每行数据末尾添加
\n实现换行,确保数据分行显示,提升可读性; - 指定
encoding="utf-8"是解决中文乱码的核心,TXT 文件默认编码可能为 GBK,需显式指定 UTF-8。
2.3 方式 2:批量多行写入(提升写入效率)
代码实现
python
运行
# 方式2:批量多行写入(writelines,一次性写入) def save_to_txt_batch(movie_list): # 构造待写入的字符串列表 lines = [] lines.append("豆瓣电影Top250数据(批量写入)\n") lines.append("="*50 + "\n") for movie in movie_list: lines.append(f"排名:{movie['rank']} | 片名:{movie['title']} | 评分:{movie['score']} | 简介:{movie['quote']}\n") # 批量写入 with open("豆瓣电影Top250_批量写入.txt", "w", encoding="utf-8") as f: f.writelines(lines) print("批量写入完成,文件保存路径:豆瓣电影Top250_批量写入.txt") # 执行保存 save_to_txt_batch(movie_data)输出结果
与 “单行写入” 的 TXT 文件内容一致,仅文件名不同。
原理解析
writelines()接收字符串列表作为参数,一次性将所有内容写入文件,减少 I/O 操作次数,相比逐行write()效率更高(尤其数据量较大时);- 列表中每个元素需自行包含换行符
\n,否则所有内容会粘连成一行; - 批量写入适合数据量较大的场景(如爬取数百 / 数千条数据),可显著提升保存速度。
2.4 方式 3:结构化格式化写入(提升可读性)
代码实现
python
运行
# 方式3:结构化格式化写入(分段、对齐,提升可读性) def save_to_txt_structured(movie_list): with open("豆瓣电影Top250_结构化写入.txt", "w", encoding="utf-8") as f: # 写入标题 f.write("【豆瓣电影Top250】\n") f.write("更新时间:2025-12-17\n") f.write("-"*60 + "\n\n") # 结构化写入每条数据 for movie in movie_list: f.write(f"排名:{movie['rank']:>2d}\n") # 右对齐,占2位 f.write(f"片名:{movie['title']}\n") f.write(f"评分:{movie['score']}\n") f.write(f"简介:{movie['quote']}\n") f.write("-"*60 + "\n") # 分隔线 print("结构化写入完成,文件保存路径:豆瓣电影Top250_结构化写入.txt") # 执行保存 save_to_txt_structured(movie_data)输出结果(TXT 文件内容节选)
plaintext
【豆瓣电影Top250】 更新时间:2025-12-17 ------------------------------------------------------------ 排名: 1 片名:肖申克的救赎 评分:9.7 简介:希望让人自由。 ------------------------------------------------------------ 排名: 2 片名:霸王别姬 评分:9.6 简介:风华绝代。 ------------------------------------------------------------ 排名: 3 片名:阿甘正传 评分:9.5 简介:一部美国近现代史。 ...原理解析
- 使用格式化字符串
f"{movie['rank']:>2d}"实现数字右对齐,提升视觉整洁度; - 增加更新时间、分隔线等元信息,让 TXT 文件更具实用性;
- 每条数据分段展示(排名 / 片名 / 评分 / 简介各占一行),相比单行写入更易阅读,适合人工查看。
2.5 方式 4:追加写入(多页爬虫增量保存)
代码实现
python
运行
# 模拟多页爬取,分批追加写入 def save_to_txt_append(): # 模拟第一页数据(前10条) page1_data = movie_data[:10] # 模拟第二页数据(11-20条) page2_data = movie_data[10:20] # 模拟第三页数据(21-25条) page3_data = movie_data[20:] # 第一页:覆盖写入(初始化文件) with open("豆瓣电影Top250_追加写入.txt", "w", encoding="utf-8") as f: f.write("豆瓣电影Top250(多页追加)\n") f.write("="*50 + "\n") for movie in page1_data: f.write(f"排名:{movie['rank']} | 片名:{movie['title']} | 评分:{movie['score']}\n") print("第一页数据写入完成") # 第二页:追加写入(a模式) with open("豆瓣电影Top250_追加写入.txt", "a", encoding="utf-8") as f: f.write("\n--- 第二页数据 ---\n") for movie in page2_data: f.write(f"排名:{movie['rank']} | 片名:{movie['title']} | 评分:{movie['score']}\n") print("第二页数据追加完成") # 第三页:追加写入 with open("豆瓣电影Top250_追加写入.txt", "a", encoding="utf-8") as f: f.write("\n--- 第三页数据 ---\n") for movie in page3_data: f.write(f"排名:{movie['rank']} | 片名:{movie['title']} | 评分:{movie['score']}\n") print("第三页数据追加完成,文件保存路径:豆瓣电影Top250_追加写入.txt") # 执行追加写入 save_to_txt_append()输出结果(TXT 文件内容节选)
plaintext
豆瓣电影Top250(多页追加) ================================================== 排名:1 | 片名:肖申克的救赎 | 评分:9.7 排名:2 | 片名:霸王别姬 | 评分:9.6 ... 排名:10 | 片名:楚门的世界 | 评分:9.4 --- 第二页数据 --- 排名:11 | 片名:教父 | 评分:9.3 排名:12 | 片名:星际穿越 | 评分:9.4 ... 排名:20 | 片名:禁闭岛 | 评分:9.1 --- 第三页数据 --- 排名:21 | 片名:盗梦空间 | 评分:9.4 ... 排名:25 | 片名:蝙蝠侠:黑暗骑士 | 评分:9.2原理解析
a模式为追加写入,不会清空原有内容,仅在文件末尾添加新数据,适合多页爬虫、增量爬取场景;- 追加时建议添加分页标识(如 “--- 第二页数据 ---”),便于区分不同批次的数据;
- 若需实现 “断点续爬”,可先读取文件中已保存的最大排名,再从下一页开始爬取并追加。
三、异常处理与数据安全
3.1 核心异常处理(避免程序崩溃)
python
运行
# 带异常处理的TXT保存函数 def save_to_txt_with_exception(movie_list): try: with open("豆瓣电影Top250_异常处理.txt", "w", encoding="utf-8") as f: # 校验数据是否为空 if not movie_list: f.write("爬取的数据为空!") print("数据为空,已写入提示信息") return # 批量写入数据 lines = ["豆瓣电影Top250(异常处理版)\n", "="*50 + "\n"] for movie in movie_list: # 校验字段是否存在,避免KeyError rank = movie.get("rank", "未知") title = movie.get("title", "未知") score = movie.get("score", "未知") quote = movie.get("quote", "无简介") lines.append(f"排名:{rank} | 片名:{title} | 评分:{score} | 简介:{quote}\n") f.writelines(lines) print("带异常处理的保存完成") except FileNotFoundError: print("错误:文件路径不存在,请检查保存路径是否正确") except PermissionError: print("错误:无文件写入权限,请检查文件是否被占用或路径权限") except UnicodeEncodeError: print("错误:数据包含无法编码的字符,请清洗数据后重试") except Exception as e: print(f"未知错误:{e}") # 执行保存 save_to_txt_with_exception(movie_data)原理解析
- 捕获
FileNotFoundError:处理保存路径不存在的问题(如指定了不存在的文件夹); - 捕获
PermissionError:处理文件被占用、权限不足的问题; - 捕获
UnicodeEncodeError:处理数据中包含特殊字符无法编码的问题; - 使用
movie.get("rank", "未知")替代movie["rank"],避免字段缺失导致的KeyError; - 先校验数据是否为空,避免生成空文件。
3.2 数据安全技巧
- 备份原有文件:覆盖写入(w 模式)前,可先复制原有文件为备份(如
data_bak.txt); - 分批保存:爬取大量数据时(如 1000 条 +),每爬取 100 条就保存一次,避免程序崩溃导致数据丢失;
- 编码校验:保存前清洗数据,去除无法编码的特殊字符(如
\x00、\r等); - 路径校验:保存前检查目标文件夹是否存在,不存在则创建(使用
os.makedirs())。
四、TXT 文件保存的局限性与拓展方向
4.1 局限性
| 局限性 | 具体表现 | 适用场景 |
|---|---|---|
| 无结构化 | 数据以纯文本存储,无法直接按字段查询 / 筛选 | 简单数据展示、临时保存 |
| 读写效率低 | 数据量超大时(10 万条 +),读写速度慢 | 小数据量(万级以内) |
| 易篡改 | 纯文本可直接编辑,数据安全性低 | 非核心数据保存 |
4.2 拓展方向
- CSV 文件:适合结构化数据,可直接用 Excel 打开,使用
csv库实现; - JSON 文件:适合嵌套数据,便于跨语言解析,使用
json库实现; - 数据库:适合大量数据、高频查询,如 SQLite/MySQL/MongoDB;
- 压缩保存:数据量较大时,可将 TXT 文件压缩为 zip/gz 格式,减少存储空间。
拓展示例:TXT 文件压缩保存
python
运行
import zipfile # 将TXT文件压缩为ZIP def compress_txt_file(): # 压缩文件 with zipfile.ZipFile("豆瓣电影Top250_压缩包.zip", "w", zipfile.ZIP_DEFLATED) as zf: # 添加TXT文件到压缩包 zf.write("豆瓣电影Top250_结构化写入.txt", arcname="豆瓣电影Top250.txt") # 读取压缩包中的文件 with zipfile.ZipFile("豆瓣电影Top250_压缩包.zip", "r") as zf: # 列出压缩包内的文件 print("压缩包内文件:", zf.namelist()) # 读取文件内容 with zf.open("豆瓣电影Top250.txt") as f: content = f.read().decode("utf-8") print("压缩包内文件内容(前200字符):\n", content[:200]) # 执行压缩 compress_txt_file()五、总结
TXT 文件保存是爬虫数据持久化的基础方法,其核心在于掌握 Python 文件操作的核心 API、不同打开模式的适用场景,以及数据格式化、异常处理的技巧。本文通过豆瓣电影 Top250 实战案例,演示了单行写入、批量写入、结构化写入、追加写入四种核心保存方式,覆盖了从基础保存到异常处理、数据安全的全流程。
在实际爬虫开发中,需根据数据量、使用场景选择合适的保存方式:
- 小数据量、临时查看:选择结构化写入,提升可读性;
- 大数据量、追求效率:选择批量写入,减少 I/O 操作;
- 多页爬取、增量更新:选择追加写入,实现断点续爬;
- 生产环境:必须添加异常处理,确保程序稳定性。
同时,需认识到 TXT 文件的局限性,对于结构化数据、大量数据,应拓展到 CSV、JSON、数据库等保存方式。掌握 TXT 文件保存的核心逻辑,能为后续更复杂的数据持久化操作奠定基础。