一篇搞定爬虫存储:MySQL/MongoDB/Excel 方案对比 + 代码实战

张开发
2026/4/18 0:13:36 15 分钟阅读

分享文章

一篇搞定爬虫存储:MySQL/MongoDB/Excel 方案对比 + 代码实战
一、引言为什么爬虫数据存储如此重要在分布式爬虫、高并发采集、AI 辅助抓取全面普及的 2026 年数据采集环节的反爬绕过、渲染抓取、IP 代理、验证码识别等技术已经高度工程化。但在真实项目落地中超过 65% 的爬虫故障、数据丢失、效率瓶颈都来源于存储选型不当。小爬虫用 Excel 撑不住十万条数据卡死结构化商品数据塞进 MongoDB 导致后期无法联表统计不规则 JSON 强行存入 MySQL 造成字段爆炸、维护灾难高并发写入因存储瓶颈导致队列阻塞、任务中断。数据存储是爬虫链路最后一公里也是价值落地的核心环节。一套合理的存储方案直接决定数据是否不丢、写入是否高效、查询是否顺畅、扩展是否平滑、维护成本是否可控。反之错误选型会让前面所有采集工作大打折扣甚至让整个爬虫项目失效。本章结构概览plaintext概念解析 → 技术原理 → 方案对比 → 实战代码 → 最佳实践 → 常见问题 → 趋势展望二、核心概念解析2.1 基本定义概念一爬虫数据的三大类型表格数据类型特点典型来源存储难度强结构化数据字段固定、长度可控、格式规整电商商品、房产、企业信息、榜单低半结构化数据JSON/XML、嵌套深、字段可变评论、动态、接口返回、文章中非结构化数据长文本、HTML、富文本、图片链接新闻正文、帖子内容、源码高概念二三种主流存储方案MySQL关系型数据库强规范、SQL 强查询、适合结构化数据MongoDB文档型数据库BSON 存储、无固定结构、适合 JSON 爬虫数据Excel/CSV表格文件零部署、适合小批量、临时交付数据2.2 关键术语解释写入吞吐量单位时间可写入的数据条数决定高并发爬虫是否阻塞事务安全批量写入失败时是否能回滚避免脏数据与数据丢失水平扩展数据量爆炸后能否通过加机器实现容量线性提升索引优化通过建立索引加速查询避免全表扫描导致卡顿优雅降级存储异常时爬虫仍能保证不崩溃、不丢数据2.3 爬虫存储架构概览plaintext┌─────────────────────────────────────────┐ │ 采集层 │ │ 请求 → 解析 → 清洗 → 结构化 │ ├─────────────────────────────────────────┤ │ 调度层 │ │ 队列、限速、重试、代理切换 │ ├─────────────────────────────────────────┤ │ 存储层 │ │ MySQL / MongoDB / Excel/CSV │ ├─────────────────────────────────────────┤ │ 应用层 │ │ 查询、统计、导出、可视化、业务对接 │ └─────────────────────────────────────────┘三、技术原理深入3.1 核心存储原理技术一MySQL 关系型存储原理以表 行 列结构存储强 Schema 约束支持主键、外键、唯一索引、联合索引支持 ACID 事务保证批量写入一致性适合固定字段、需要统计分析、联表查询的场景技术二MongoDB 文档型存储原理以BSON二进制 JSON为存储单元无固定表结构单条文档可自由增删字段内置分片、副本集天然支持分布式高并发爬虫返回 JSON 可直接入库零映射成本技术三Excel/CSV 文件存储原理纯二维表格行式存储无服务、无进程写入时追加行不支持并发、不支持事务打开时全量加载到内存超量即卡顿适合一次性、小批量、非技术人员直接查看3.2 数据写入与读取机制1MySQL 写入流程建立连接 → 开启事务 → 拼装 SQL → 执行写入 → 提交 / 回滚 → 关闭连接特点稳定可靠、支持批量、适合高规范数据2MongoDB 写入流程连接集合 → 构造字典 → insert_one /insert_many → 自动序列化特点极快、无结构约束、高并发友好3Excel/CSV 写入流程打开文件 → 追加行 → 关闭文件特点简单、低效、不支持多线程同时写3.3 性能与瓶颈原理表格方案写入瓶颈查询瓶颈扩容瓶颈MySQL事务开销、锁竞争无索引、大表全表扫分库分表成本MongoDB内存不足、磁盘 IO复杂联表分片配置Excel/CSV文件大小、单线程大数据量筛选无法扩容四、三大存储方案全方位对比2026 最新4.1 整体对比表表格对比维度MySQLMongoDBExcel/CSV数据结构强结构化、固定表文档型、支持嵌套二维表格、纯结构化写入性能中高事务保证极高无锁优化低单线程、易阻塞查询能力最强SQL、联表、聚合强嵌套查询、索引极弱仅基础筛选并发支持高极高极低并发写必损坏支持数据量千万亿级分库分表亿十亿级分片万级内超 10 万卡顿开发成本中需建表、写 SQL低直接存 JSON极低开箱即用部署成本中需安装配置中可 Docker 一键跑极低零服务数据安全高备份、主从、事务高副本集、持久化低易删、易乱码嵌套 JSON 支持差需拆表或 JSON 字段极佳原生支持不支持必须扁平化2026 爬虫适用度⭐⭐⭐⭐⭐结构化首选⭐⭐⭐⭐⭐通用首选⭐⭐仅小数据4.2 适用爬虫场景精准匹配MySQL电商商品、房产、工商、订单、库存等强结构化爬虫MongoDB新闻、评论、动态、公众号、接口 JSON、不规则字段爬虫Excel/CSV单次小批量、临时导出、给运营 / 客户直接交付报表五、Python 实战代码可直接运行5.1 MySQL 存储实战爬虫标准写法python运行import pymysql from pymysql.err import OperationalError, ProgrammingError class MySQLStorage: def __init__(self, hostlocalhost, userroot, password123456, dbspider_data): self.host host self.user user self.password password self.db db self.conn None self.cursor None self.connect() def connect(self): try: self.conn pymysql.connect( hostself.host, userself.user, passwordself.password, databaseself.db, charsetutf8mb4, connect_timeout5 ) self.cursor self.conn.cursor() except (OperationalError, ProgrammingError) as e: raise Exception(fMySQL连接失败{str(e)}) def create_table(self): sql CREATE TABLE IF NOT EXISTS goods ( id BIGINT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(1000) NOT NULL, price DECIMAL(12,2) DEFAULT 0.00, url VARCHAR(1500), source VARCHAR(255), create_time DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX idx_title (title), INDEX idx_create_time (create_time) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; self.cursor.execute(sql) self.conn.commit() def save_one(self, data): sql INSERT INTO goods(title, price, url, source) VALUES(%s, %s, %s, %s) try: self.cursor.execute(sql, ( data.get(title), data.get(price, 0.00), data.get(url), data.get(source) )) self.conn.commit() return True except Exception as e: self.conn.rollback() print(f写入失败{e}) return False def save_batch(self, data_list, batch_size100): sql INSERT INTO goods(title, price, url, source) VALUES(%s, %s, %s, %s) success 0 for i in range(0, len(data_list), batch_size): batch data[i:ibatch_size] try: self.cursor.executemany(sql, [( item.get(title), item.get(price, 0.00), item.get(url), item.get(source) ) for item in batch]) self.conn.commit() success len(batch) except Exception as e: self.conn.rollback() print(f批量写入失败{e}) return success def close(self): if self.cursor: self.cursor.close() if self.conn: self.conn.close() # 使用示例 if __name__ __main__: storage MySQLStorage() storage.create_table() test_data { title: 2026新款智能手机, price: 3999.00, url: https://example.com/item/123, source: 电商平台 } storage.save_one(test_data) storage.close()5.2 MongoDB 存储实战爬虫首选python运行from pymongo import MongoClient from pymongo.errors import ConnectionFailure, BulkWriteError class MongoDBStorage: def __init__(self, hostlocalhost, port27017, dbspider_db, collectiongoods): self.host host self.port port self.db_name db self.coll_name collection self.client None self.db None self.coll None self.connect() def connect(self): try: self.client MongoClient(self.host, self.port, serverSelectionTimeoutMS5000) self.db self.client[self.db_name] self.coll self.db[self.coll_name] # 自动创建索引 self.coll.create_index(url, uniqueTrue, sparseTrue) self.coll.create_index(create_time) except ConnectionFailure as e: raise Exception(fMongoDB连接失败{str(e)}) def save_one(self, data): try: data[create_time] self.get_current_time() self.coll.insert_one(data) return True except Exception as e: print(f写入失败{e}) return False def save_batch(self, data_list): if not data_list: return 0 try: for item in data_list: item[create_time] self.get_current_time() self.coll.insert_many(data_list, orderedFalse) return len(data_list) except BulkWriteError: return 部分写入失败可能重复 except Exception as e: print(f批量写入异常{e}) return 0 def get_current_time(self): from datetime import datetime return datetime.now().strftime(%Y-%m-%d %H:%M:%S) def close(self): if self.client: self.client.close() # 使用示例 if __name__ __main__: storage MongoDBStorage() test_data { title: 2026新款智能手机, price: 3999.00, url: https://example.com/item/123, source: 电商平台, info: {brand: 品牌A, color: 黑色} # 嵌套JSON直接存 } storage.save_one(test_data) storage.close()5.3 Excel / CSV 存储实战轻量场景python运行import csv import openpyxl import os from datetime import datetime class ExcelCSVStorage: def __init__(self, filenamespider_data): self.csv_path f{filename}.csv self.xlsx_path f{filename}.xlsx self.init_csv() self.init_excel() def init_csv(self): if not os.path.exists(self.csv_path): with open(self.csv_path, w, newline, encodingutf-8-sig) as f: writer csv.DictWriter(f, fieldnames[title, price, url, source, create_time]) writer.writeheader() def init_excel(self): if not os.path.exists(self.xlsx_path): wb openpyxl.Workbook() ws wb.active ws.title 爬虫数据 ws.append([标题, 价格, 链接, 来源, 采集时间]) wb.save(self.xlsx_path) def save_to_csv(self, data): data[create_time] datetime.now().strftime(%Y-%m-%d %H:%M:%S) with open(self.csv_path, a, newline, encodingutf-8-sig) as f: writer csv.DictWriter(f, fieldnamesdata.keys()) writer.writerow(data) def save_to_excel(self, data): data[create_time] datetime.now().strftime(%Y-%m-%d %H:%M:%S) wb openpyxl.load_workbook(self.xlsx_path) ws wb.active ws.append([ data.get(title), data.get(price), data.get(url), data.get(source), data.get(create_time) ]) wb.save(self.xlsx_path) wb.close() # 使用示例 if __name__ __main__: storage ExcelCSVStorage() test_data { title: 2026新款智能手机, price: 3999.00, url: https://example.com/item/123, source: 电商平台 } storage.save_to_csv(test_data) storage.save_to_excel(test_data)六、实践应用指南6.1 场景选型清单场景一电商商品爬虫推荐MySQL字段固定标题、价格、销量、品牌、规格需要统计价格区间、销量排行、品牌汇总需对接后台、报表、数据分析系统场景二新闻 / 评论 / 公众号爬虫推荐MongoDB字段不固定嵌套深高并发写入单秒几十条JSON 直接入库无需映射场景三小批量一次性采集推荐Excel/CSV数据量 5 万条给运营、客户直接交付无需部署数据库6.2 实施步骤通用爬虫存储流程步骤 1根据数据类型选择存储方案步骤 2设计表结构 / 文档结构 / 表头步骤 3建立索引避免后期查询卡顿步骤 4实现单条 / 批量写入函数步骤 5加入异常捕获、重试、降级逻辑步骤 6压测写入性能调整批量大小步骤 7上线运行定期备份数据6.3 最佳实践分享最佳实践一批量写入优先禁止逐条写入批量 50~200 条一次提交大幅提升性能降低连接消耗最佳实践二去重必须做MySQL唯一索引 / 主键判断MongoDB唯一索引 upsertExcel记录已存 url内存去重最佳实践三异常捕获与重试连接失败自动重连写入失败存入本地日志后续补采避免爬虫因存储崩溃退出最佳实践四定时备份MySQLmysqldump 定时任务MongoDBmongodump / 云备份Excel按天分割文件避免单文件过大七、案例分析7.1 成功案例电商分布式爬虫背景某电商爬虫日均采集 200 万条商品数据字段固定需实时统计价格波动。方案存储MySQL 分表按天写入批量 100 条 / 次索引商品 ID、店铺 ID、时间效果写入稳定无丢失统计查询秒级响应支撑 6 个月累计 3.6 亿条数据7.2 失败案例小爬虫滥用 Excel问题个人爬虫一次性爬取 20 万条文章存入单 Excel导致文件打开 5 分钟写入频繁卡顿、丢失数据无法筛选、无法排序改进切换为 MongoDB10 分钟迁移完成性能提升 50 倍以上。八、常见问题解答8.1 技术问题Q1爬虫数据量超过 1000 万怎么存A优先 MongoDB 分片结构化数据用 MySQL 分库分表。Q2多线程爬虫写入文件乱码 / 损坏怎么办A禁止多线程写同一个 Excel/CSV加文件锁改用数据库。Q3MySQL 写入太慢如何优化A关闭自动提交、批量写入、建立合理索引、使用连接池。Q4MongoDB 占用空间太大怎么办A启用压缩、删除无用字段、建立 TTL 自动过期、按时间归档。8.2 应用问题Q1个人新手最推荐用哪个A直接用 MongoDB最简单、最强、最适配爬虫。Q2客户只要 Excel 怎么办A先存数据库再定时导出 Excel 分片文件。Q3如何保证绝对不丢数据A写入失败 → 写本地日志 → 后台定时重试 → 告警机制。九、未来发展趋势2026–20289.1 技术趋势表格趋势描述时间时序型存储普及爬虫高频数据用时序库InfluxDB/Prometheus1 年内AI 自动选型根据数据结构自动推荐存储1–2 年混合存储架构MySQLMongoDBRedis 一体化已流行存储与采集一体化爬虫框架内置存储引擎已实现9.2 职业发展建议初级掌握 CSV MySQL 基础中级精通 MongoDB 批量、索引、优化高级混合存储、分库分表、分片、备份、高可用十、本章小结10.1 核心要点回顾爬虫存储选型直接决定项目稳定性与效率强结构化 → MySQL半结构化 / JSON → MongoDB小数据 → Excel批量写入、去重、异常捕获、备份是四大关键2026 年主流爬虫默认技术栈MongoDB 为主MySQL 为辅10.2 学习建议先跑通本文三种代码理解差异根据自己的爬虫数据类型做选型上线前必做压测与异常模拟定期归档避免单表 / 单库过大课后练习使用三种存储分别写入 1000 条测试数据对比速度为自己的爬虫项目设计一套存储方案实现写入失败重试 本地日志降级功能

更多文章