1. 为什么SQLite是爬虫新手的首选数据库
作为一个从零开始学习爬虫的新手,第一次面对数据存储问题时往往会感到迷茫。MySQL需要配置服务端,MongoDB的文档结构对初学者不够直观,而SQLite就像它的名字一样轻量——不需要任何服务器配置,直接一个.db文件就能开始工作。
我至今记得2016年第一次用SQLite存储爬取数据的场景。当时需要保存某论坛的10万条帖子数据,原本打算用MySQL,但光安装配置就花了大半天。后来改用SQLite,只用了三行Python代码就创建好了数据库文件:
python复制import sqlite3
conn = sqlite3.connect('forum.db')
print("数据库已创建!")
SQLite的独特优势在于:
- 零配置:不需要安装服务端,Python标准库自带支持
- 单文件存储:整个数据库就是一个.db文件,方便迁移和备份
- 完整的SQL支持:虽然轻量但支持大多数标准SQL语法
- 跨平台:数据库文件可以在Windows/Linux/macOS间自由转移
注意:虽然SQLite适合入门和小型项目,但当数据量超过GB级别或需要高并发写入时,建议考虑MySQL等专业数据库。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. SQLite环境准备与基础操作
2.1 快速搭建SQLite环境
令人惊喜的是,Python标准库已经内置了sqlite3模块,这意味着你不需要额外安装任何包。我建议新手使用DB Browser for SQLite这个图形化工具来辅助学习,它能直观地展示数据库结构。
安装DB Browser的步骤:
- 官网下载对应操作系统的安装包
- 安装后打开软件,点击"新建数据库"
- 选择保存路径并命名(如crawler_data.db)
python复制# 检查Python是否支持SQLite
import sqlite3
print(sqlite3.sqlite_version) # 应输出版本号如"3.37.2"
2.2 创建你的第一个爬虫数据表
假设我们要爬取豆瓣图书信息,表结构设计很关键。经过多次实践,我总结出适合新手的字段设计原则:
- 必带自增主键id
- 文本字段合理设置长度
- 添加爬取时间戳
python复制def create_book_table():
conn = sqlite3.connect('douban_books.db')
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS books(
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
author TEXT,
rating REAL,
price REAL,
publish_date TEXT,
crawl_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
conn.commit()
conn.close()
实际项目中我总会添加status字段标记数据状态(0=原始,1=已清洗),这个技巧能大幅降低后期数据处理的复杂度。
3. 爬虫数据入库实战技巧
3.1 基础插入操作的三种方式
根据不同的爬取场景,我通常使用这三种插入方式:
- 单条插入 - 适合调试阶段
python复制def insert_single(book):
conn = sqlite3.connect('douban_books.db')
cursor = conn.cursor()
cursor.execute('''
INSERT INTO books(title, author, rating, price, publish_date)
VALUES(?,?,?,?,?)
''', (book['title'], book['author'], book['rating'],
book['price'], book['publish_date']))
conn.commit()
conn.close()
- 批量插入 - 生产环境首选
python复制def insert_batch(book_list):
conn = sqlite3.connect('douban_books.db')
cursor = conn.cursor()
cursor.executemany('''
INSERT INTO books(title, author, rating, price, publish_date)
VALUES(?,?,?,?,?)
''', [(b['title'], b['author'], b['rating'],
b['price'], b['publish_date']) for b in book_list])
conn.commit()
conn.close()
- UPSERT操作 - 防止重复数据
python复制def upsert_book(book):
conn = sqlite3.connect('douban_books.db')
cursor = conn.cursor()
cursor.execute('''
INSERT INTO books(title, author, rating, price, publish_date)
VALUES(?,?,?,?,?)
ON CONFLICT(title) DO UPDATE SET
author=excluded.author,
rating=excluded.rating,
price=excluded.price,
publish_date=excluded.publish_date
''', (book['title'], book['author'], book['rating'],
book['price'], book['publish_date']))
conn.commit()
conn.close()
3.2 性能优化实战心得
当处理10万级以上数据时,这些技巧能显著提升性能:
- 事务批量提交:不要每条数据都commit
python复制conn = sqlite3.connect('large_data.db')
cursor = conn.cursor()
cursor.execute("BEGIN TRANSACTION") # 显式开启事务
for i in range(100000):
cursor.execute("INSERT INTO data VALUES(?)", (i,))
if i % 1000 == 0: # 每1000条提交一次
conn.commit()
cursor.execute("BEGIN TRANSACTION")
conn.commit()
- PRAGMA调优:调整SQLite运行参数
python复制conn = sqlite3.connect('optimized.db')
conn.execute("PRAGMA journal_mode = WAL") # 写前日志
conn.execute("PRAGMA synchronous = NORMAL")
conn.execute("PRAGMA cache_size = -10000") # 10MB缓存
- 内存数据库加速:适合中间处理环节
python复制mem_conn = sqlite3.connect(":memory:")
# 处理完成后可导出到文件
mem_conn.backup(sqlite3.connect('final.db'))
4. 常见问题排查与进阶技巧
4.1 新手最常遇到的5个坑
- 编码问题:SQLite默认使用UTF-8,但Windows下Python可能有编码问题
python复制# 解决方案:连接时指定编码
conn = sqlite3.connect('data.db', isolation_level=None,
detect_types=sqlite3.PARSE_DECLTYPES,
check_same_thread=False,
uri=True)
- 并发写入冲突:多线程同时写入会报错
python复制# 解决方案1:使用队列单线程写入
# 解决方案2:设置超时重试
conn = sqlite3.connect('data.db', timeout=10)
- 字段类型混淆:SQLite的动态类型系统可能导致意外
python复制# 明确指定类型
cursor.execute("CREATE TABLE test(id INTEGER, name TEXT, value REAL)")
- 忘记关闭连接:会导致文件锁定
python复制# 使用with语句自动关闭
with sqlite3.connect('data.db') as conn:
cursor = conn.cursor()
cursor.execute("SELECT * FROM table")
- 备份问题:直接复制.db文件可能损坏数据库
python复制# 正确备份方法
src = sqlite3.connect('source.db')
dst = sqlite3.connect('backup.db')
src.backup(dst)
4.2 数据导出与可视化准备
当需要分析爬取的数据时,我常用这些方法导出:
- 导出为CSV
python复制import csv
def export_to_csv(table_name, output_file):
conn = sqlite3.connect('data.db')
cursor = conn.cursor()
cursor.execute(f"SELECT * FROM {table_name}")
with open(output_file, 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow([i[0] for i in cursor.description]) # 写列名
writer.writerows(cursor)
conn.close()
- 使用Pandas分析
python复制import pandas as pd
def analyze_with_pandas():
conn = sqlite3.connect('data.db')
df = pd.read_sql("SELECT * FROM books WHERE rating > 8.0", conn)
print(df.describe())
# 绘制评分分布直方图
df['rating'].hist(bins=20)
conn.close()
- 生成JSON API
python复制from flask import Flask, jsonify
import sqlite3
app = Flask(__name__)
@app.route('/api/books')
def get_books():
conn = sqlite3.connect('douban_books.db')
conn.row_factory = sqlite3.Row # 使返回字典形式
cursor = conn.cursor()
cursor.execute("SELECT * FROM books LIMIT 100")
books = [dict(row) for row in cursor.fetchall()]
conn.close()
return jsonify(books)
在真实项目中,我通常会结合爬虫进度将关键指标(如已爬取数量、重复率等)实时写入SQLite,然后用上述方法定期导出报告。这种工作流既简单又高效,特别适合个人和小团队的数据采集项目。
