Browse Source

feat(database): 添加 SQLite 支持作为默认数据库

支持 SQLite 和 MySQL 两种数据库配置,默认使用 SQLite 简化部署
更新环境变量配置、数据库连接逻辑和文档说明
liuyuqi-cnb 4 days ago
parent
commit
fd1eb2edbd
4 changed files with 90 additions and 23 deletions
  1. 12 6
      .env.example
  2. 39 4
      README.md
  3. 14 6
      config/settings.py
  4. 25 7
      models/product.py

+ 12 - 6
.env.example

@@ -1,9 +1,15 @@
-# 数据库配置
-DB_HOST=127.0.0.1
-DB_PORT=3306
-DB_NAME=price_crawler
-DB_USER=root
-DB_PASSWORD=your_password
+# 数据库类型: sqlite (默认) 或 mysql
+DB_TYPE=sqlite
+
+# SQLite 配置 (当 DB_TYPE=sqlite 时使用)
+SQLITE_PATH=data/price_crawler.db
+
+# MySQL 配置 (当 DB_TYPE=mysql 时使用)
+# DB_HOST=127.0.0.1
+# DB_PORT=3306
+# DB_NAME=price_crawler
+# DB_USER=root
+# DB_PASSWORD=your_password
 
 # 可选:代理配置
 # HTTP_PROXY=http://127.0.0.1:7890

+ 39 - 4
README.md

@@ -8,7 +8,7 @@
 - 支持批发价格获取(1688平台)
 - 支持并发爬取
 - 支持 Cookie 和代理配置
-- 数据持久化到 MySQL 数据库
+- 支持多种数据库:**SQLite(默认)**、MySQL
 - 价格历史记录追踪
 
 ## 项目结构
@@ -54,10 +54,27 @@ pip install -r requirements.txt
 cp .env.example .env
 ```
 
-编辑 `.env` 文件:
+#### 使用 SQLite(默认,无需额外配置)
+
+默认使用 SQLite 数据库,无需额外配置。数据库文件默认保存在 `data/price_crawler.db`。
 
 ```env
-# 数据库配置
+# 数据库类型: sqlite (默认) 或 mysql
+DB_TYPE=sqlite
+
+# SQLite 配置
+SQLITE_PATH=data/price_crawler.db
+```
+
+#### 使用 MySQL
+
+如果需要使用 MySQL 数据库,修改配置如下:
+
+```env
+# 数据库类型: sqlite (默认) 或 mysql
+DB_TYPE=mysql
+
+# MySQL 配置
 DB_HOST=127.0.0.1
 DB_PORT=3306
 DB_NAME=price_crawler
@@ -69,12 +86,30 @@ DB_PASSWORD=your_password
 # HTTPS_PROXY=http://127.0.0.1:7890
 ```
 
-### 3. 创建数据库
+### 3. 初始化数据库
+
+#### SQLite
+
+无需手动创建数据库,运行初始化命令会自动创建:
+
+```bash
+python main.py --mode init
+```
+
+#### MySQL
+
+需要先创建数据库:
 
 ```sql
 CREATE DATABASE price_crawler CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
 ```
 
+然后运行初始化命令:
+
+```bash
+python main.py --mode init
+```
+
 ## 使用方法
 
 ### 查看帮助

+ 14 - 6
config/settings.py

@@ -3,13 +3,21 @@ from dotenv import load_dotenv
 
 load_dotenv()
 
+DATABASE_TYPE = os.getenv('DB_TYPE', 'sqlite').lower()
+
 DATABASE_CONFIG = {
-    'host': os.getenv('DB_HOST', 'localhost'),
-    'port': int(os.getenv('DB_PORT', 3306)),
-    'user': os.getenv('DB_USER', 'root'),
-    'password': os.getenv('DB_PASSWORD', ''),
-    'database': os.getenv('DB_NAME', 'price_crawler'),
-    'charset': 'utf8mb4'
+    'type': DATABASE_TYPE,
+    'sqlite': {
+        'path': os.getenv('SQLITE_PATH', 'data/price_crawler.db'),
+    },
+    'mysql': {
+        'host': os.getenv('DB_HOST', 'localhost'),
+        'port': int(os.getenv('DB_PORT', 3306)),
+        'user': os.getenv('DB_USER', 'root'),
+        'password': os.getenv('DB_PASSWORD', ''),
+        'database': os.getenv('DB_NAME', 'price_crawler'),
+        'charset': 'utf8mb4'
+    }
 }
 
 CRAWLER_CONFIG = {

+ 25 - 7
models/product.py

@@ -1,3 +1,4 @@
+import os
 from sqlalchemy import Column, Integer, String, Text, DateTime, Float, create_engine
 from sqlalchemy.ext.declarative import declarative_base
 from sqlalchemy.orm import sessionmaker
@@ -101,13 +102,30 @@ class PriceHistory(Base):
 
 
 def get_engine():
-    db_config = DATABASE_CONFIG
-    connection_string = (
-        f"mysql+pymysql://{db_config['user']}:{db_config['password']}"
-        f"@{db_config['host']}:{db_config['port']}/{db_config['database']}"
-        f"?charset={db_config['charset']}"
-    )
-    return create_engine(connection_string, echo=False)
+    db_type = DATABASE_CONFIG.get('type', 'sqlite')
+    
+    if db_type == 'sqlite':
+        sqlite_config = DATABASE_CONFIG.get('sqlite', {})
+        db_path = sqlite_config.get('path', 'data/price_crawler.db')
+        
+        db_dir = os.path.dirname(db_path)
+        if db_dir and not os.path.exists(db_dir):
+            os.makedirs(db_dir, exist_ok=True)
+        
+        connection_string = f"sqlite:///{db_path}"
+        return create_engine(connection_string, echo=False, connect_args={'check_same_thread': False})
+    
+    elif db_type == 'mysql':
+        mysql_config = DATABASE_CONFIG.get('mysql', {})
+        connection_string = (
+            f"mysql+pymysql://{mysql_config.get('user', 'root')}:{mysql_config.get('password', '')}"
+            f"@{mysql_config.get('host', 'localhost')}:{mysql_config.get('port', 3306)}/{mysql_config.get('database', 'price_crawler')}"
+            f"?charset={mysql_config.get('charset', 'utf8mb4')}"
+        )
+        return create_engine(connection_string, echo=False)
+    
+    else:
+        raise ValueError(f"不支持的数据库类型: {db_type}")
 
 
 def init_db():