更新今日的数据内容以及更新readme的内容
This commit is contained in:
File diff suppressed because it is too large
Load Diff
286
README.md
286
README.md
@@ -1,21 +1,60 @@
|
|||||||
# TopHub数据处理系统
|
# TopHub数据处理与产品分析系统
|
||||||
|
|
||||||
本项目用于处理TopHub网站抓取的临时文件,对数据进行分类并存储到SQLite数据库中。
|
本项目包含两个核心功能模块:
|
||||||
|
1. TopHub网站数据抓取与处理系统
|
||||||
|
2. ProductHunt产品抓取与AI分析系统
|
||||||
|
|
||||||
## 功能特点
|
## 功能特点
|
||||||
|
|
||||||
1. **文件解析**:读取临时文件(格式为"日期+时间.txt"),每5行作为一个数据单元
|
### TopHub数据抓取与处理
|
||||||
2. **数据提取**:从每个数据单元中提取标题和链接
|
- **网站抓取**:从tophub.today网站抓取数据,支持节点ID范围遍历
|
||||||
3. **智能分类**:调用本地API(Ollama)对标题进行自动分类
|
- **智能过滤**:根据过滤列表自动跳过指定栏目内容
|
||||||
4. **去重处理**:检查标题+日期是否已存在于数据库中,避免重复录入
|
- **数据存储**:将抓取数据保存到SQLite数据库
|
||||||
5. **进度显示**:使用进度条显示处理进度
|
- **分类处理**:调用本地API进行智能分类
|
||||||
6. **分类标准化**:将相似分类合并为标准分类
|
- **去重处理**:避免重复数据录入
|
||||||
|
- **分类标准化**:相似分类自动合并
|
||||||
|
|
||||||
|
### ProductHunt产品分析
|
||||||
|
- **产品抓取**:从ProductHunt抓取产品详细信息
|
||||||
|
- **AI分析**:调用Ollama API分析产品开发难度
|
||||||
|
- **数据管理**:完整的产品数据库管理
|
||||||
|
- **关注数转换**:将文本形式的关注数转换为数字
|
||||||
|
- **难度评分**:自动计算产品开发难度分数
|
||||||
|
- **缺失数据补充**:自动补全缺失的产品链接和评分
|
||||||
|
|
||||||
|
### 数据可视化
|
||||||
|
- **GUI查看器**:使用PySide6构建的可视化数据查看器
|
||||||
|
- **搜索筛选**:支持关键词搜索和分类筛选
|
||||||
|
- **分类统计**:实时显示分类统计信息
|
||||||
|
- **数据操作**:支持批量删除、标记感兴趣和评分调整
|
||||||
|
|
||||||
## 文件说明
|
## 文件说明
|
||||||
|
|
||||||
### 核心脚本
|
### 核心脚本
|
||||||
|
|
||||||
1. **process_temp_files.py** - 主处理脚本
|
1. **tophub_scraper.py** - TopHub网站数据抓取脚本
|
||||||
|
- 从tophub.today网站抓取数据
|
||||||
|
- 根据过滤列表过滤内容
|
||||||
|
- 保存数据到临时文件
|
||||||
|
- 调用数据导入脚本
|
||||||
|
|
||||||
|
2. **product/integrated_product_system.py** - 全功能产品抓取与分析系统
|
||||||
|
- 整合产品抓取和AI分析功能
|
||||||
|
- 从tophub数据库查询ProductHunt链接
|
||||||
|
- 使用Playwright抓取产品详细信息
|
||||||
|
- 调用Ollama API分析产品开发难度
|
||||||
|
- 管理产品数据库
|
||||||
|
- 提供完整的工作流程
|
||||||
|
|
||||||
|
3. **db_viewer.py** - TopHub数据查看器
|
||||||
|
- PySide6界面应用程序
|
||||||
|
- 显示SQLite数据库中的抓取数据
|
||||||
|
- 支持搜索、筛选和分类统计
|
||||||
|
- 支持链接点击和数据操作
|
||||||
|
|
||||||
|
### 辅助脚本
|
||||||
|
|
||||||
|
1. **process_temp_files.py** - 临时文件处理脚本
|
||||||
- 解析临时文件
|
- 解析临时文件
|
||||||
- 调用API进行分类
|
- 调用API进行分类
|
||||||
- 存储到数据库
|
- 存储到数据库
|
||||||
@@ -28,30 +67,76 @@
|
|||||||
- 将相似分类合并为标准分类
|
- 将相似分类合并为标准分类
|
||||||
- 提供分类映射规则
|
- 提供分类映射规则
|
||||||
|
|
||||||
### 辅助脚本
|
4. **run_viewer.py** - 数据库查看器启动脚本
|
||||||
|
- 检查依赖包
|
||||||
|
- 启动SQLite数据库查看器
|
||||||
|
|
||||||
1. **check_db.py** - 数据库结构检查脚本
|
5. **check_db.py** - 数据库结构检查脚本
|
||||||
2. **test_api.py** - API测试脚本
|
6. **test_api.py** - API测试脚本
|
||||||
3. **view_categories.py** - 查看分类示例脚本
|
7. **view_categories.py** - 查看分类示例脚本
|
||||||
|
|
||||||
## 使用方法
|
## 使用方法
|
||||||
|
|
||||||
### 1. 处理临时文件
|
### 1. TopHub数据抓取
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python process_temp_files.py
|
python tophub_scraper.py
|
||||||
```
|
```
|
||||||
|
|
||||||
该脚本会:
|
该脚本会:
|
||||||
- 扫描当前目录下的所有临时文件(格式为"日期+时间.txt")
|
- 从tophub.today网站抓取数据
|
||||||
- 解析文件内容,提取标题和链接
|
- 根据过滤列表过滤内容(可配置tophub_ban_column.txt)
|
||||||
- 调用本地API对标题进行分类
|
- 将抓取数据保存为临时文件(格式:YYYY年MM月DD日HHMMSS.txt)
|
||||||
- 检查并避免重复数据
|
- 调用数据导入脚本处理抓取结果
|
||||||
- 存储到tophub_data.db数据库
|
|
||||||
|
|
||||||
### 2. 清理和标准化分类
|
### 2. ProductHunt产品抓取与分析
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# 运行完整工作流程:抓取+分析+数据补充
|
||||||
|
python product/integrated_product_system.py
|
||||||
|
|
||||||
|
# 仅进行分析,不抓取数据
|
||||||
|
python product/integrated_product_system.py --analyze-only
|
||||||
|
|
||||||
|
# 限制最大分析产品数量
|
||||||
|
python product/integrated_product_system.py --max-products 100
|
||||||
|
```
|
||||||
|
|
||||||
|
主要功能:
|
||||||
|
- 从tophub数据库查询ProductHunt链接
|
||||||
|
- 使用Playwright抓取产品详细信息
|
||||||
|
- 调用Ollama API分析产品开发难度
|
||||||
|
- 自动计算难度分数
|
||||||
|
- 转换用户关注数为数字格式
|
||||||
|
- 补全缺失的产品链接
|
||||||
|
- 重新分析无效难度评分
|
||||||
|
|
||||||
|
### 3. 数据可视化查看
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 启动数据库查看器
|
||||||
|
python db_viewer.py
|
||||||
|
```
|
||||||
|
|
||||||
|
或使用启动脚本:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python run_viewer.py
|
||||||
|
```
|
||||||
|
|
||||||
|
查看器功能:
|
||||||
|
- 显示数据库中的抓取数据
|
||||||
|
- 支持关键词搜索和分类筛选
|
||||||
|
- 实时分类统计显示
|
||||||
|
- 支持链接点击在浏览器中打开
|
||||||
|
- 支持批量删除和评分调整
|
||||||
|
|
||||||
|
### 4. 分类处理
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 处理临时文件
|
||||||
|
python process_temp_files.py
|
||||||
|
|
||||||
# 清理分类中的特殊字符
|
# 清理分类中的特殊字符
|
||||||
python cleanup_categories.py
|
python cleanup_categories.py
|
||||||
|
|
||||||
@@ -59,74 +144,118 @@ python cleanup_categories.py
|
|||||||
python standardize_categories.py
|
python standardize_categories.py
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. 查看数据
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 查看分类示例
|
|
||||||
python view_categories.py
|
|
||||||
|
|
||||||
# 检查数据库结构
|
|
||||||
python check_db.py
|
|
||||||
```
|
|
||||||
|
|
||||||
## 数据库结构
|
## 数据库结构
|
||||||
|
|
||||||
数据库文件为`tophub_data.db`,包含以下表:
|
### 1. TopHub数据数据库 (tophub_data.db)
|
||||||
|
|
||||||
1. **tophub_entries** - 主数据表
|
包含TopHub网站抓取的原始数据:
|
||||||
- id: 主键
|
|
||||||
- text_content: 标题内容(非空)
|
|
||||||
- link: 链接
|
|
||||||
- category: 分类
|
|
||||||
- scrape_time: 抓取时间
|
|
||||||
|
|
||||||
2. **classification_progress** - 分类进度表
|
- **articles** - 主数据表
|
||||||
- id: 主键
|
- id: 主键
|
||||||
- total_count: 总数量
|
- title: 标题内容
|
||||||
- processed_count: 已处理数量
|
- url: 链接
|
||||||
- last_updated: 最后更新时间
|
- category: 分类
|
||||||
|
- source_date: 来源日期
|
||||||
|
- score: 评分
|
||||||
|
- is_interested: 是否感兴趣
|
||||||
|
|
||||||
|
- **classification_progress** - 分类进度表
|
||||||
|
- id: 主键
|
||||||
|
- total_count: 总数量
|
||||||
|
- processed_count: 已处理数量
|
||||||
|
- last_updated: 最后更新时间
|
||||||
|
|
||||||
|
### 2. 产品分析数据库 (products.db)
|
||||||
|
|
||||||
|
包含ProductHunt产品的详细信息和分析结果:
|
||||||
|
|
||||||
|
- **products** - 产品信息表
|
||||||
|
- id: 主键
|
||||||
|
- url: 产品链接(唯一)
|
||||||
|
- name: 产品名称
|
||||||
|
- introduction: 产品简介
|
||||||
|
- user_count: 用户数量
|
||||||
|
- maker_link: 制作者链接
|
||||||
|
- maker_statement: 制作者声明
|
||||||
|
- created_at: 创建时间
|
||||||
|
- updated_at: 更新时间
|
||||||
|
|
||||||
|
- **product_analysis** - 产品分析结果表
|
||||||
|
- id: 主键
|
||||||
|
- original_name: 原始产品名称
|
||||||
|
- product_intro: 产品简介
|
||||||
|
- development_difficulty: 开发难度描述
|
||||||
|
- ai_response: AI原始响应
|
||||||
|
- difficulty_score: 难度分数
|
||||||
|
- product_link: 产品链接
|
||||||
|
- follows: 关注数
|
||||||
|
- created_at: 创建时间
|
||||||
|
|
||||||
## API配置
|
## API配置
|
||||||
|
|
||||||
脚本使用本地Ollama API进行分类:
|
项目使用本地Ollama API进行AI相关任务:
|
||||||
- API地址:http://localhost:11434/api/generate
|
- **API地址**:http://localhost:11434/api/generate
|
||||||
- 模型:gemma3:4b
|
- **模型**:qwen3:8b
|
||||||
- 请求格式:JSON
|
- **请求格式**:JSON
|
||||||
|
|
||||||
|
主要用途:
|
||||||
|
1. **TopHub数据分类**:对抓取的标题进行智能分类
|
||||||
|
2. **产品开发难度分析**:分析ProductHunt产品的开发难度
|
||||||
|
3. **用户关注数转换**:将文本形式的关注数转换为数字
|
||||||
|
4. **难度评分计算**:自动计算产品开发难度分数
|
||||||
|
|
||||||
|
## 核心依赖
|
||||||
|
|
||||||
|
### 基础依赖
|
||||||
|
- requests: HTTP请求处理
|
||||||
|
- sqlite3: 数据库操作
|
||||||
|
- loguru: 日志记录
|
||||||
|
- tqdm: 进度条显示
|
||||||
|
|
||||||
|
### 产品分析依赖
|
||||||
|
- asyncio: 异步编程
|
||||||
|
- playwright: 网页抓取
|
||||||
|
- PySide6: GUI界面(仅用于查看器)
|
||||||
|
|
||||||
|
## 日志文件
|
||||||
|
|
||||||
|
系统会生成以下日志文件:
|
||||||
|
- **tophub_scraper.log** - TopHub抓取日志
|
||||||
|
- **integrated_product_system.log** - 产品分析系统日志
|
||||||
|
- **process_temp_files.log** - 临时文件处理日志
|
||||||
|
- **cleanup_categories.log** - 分类清理日志
|
||||||
|
- **standardize_categories.log** - 分类标准化日志
|
||||||
|
|
||||||
## 分类标准
|
## 分类标准
|
||||||
|
|
||||||
系统支持以下标准分类:
|
系统支持以下标准分类:
|
||||||
|
|
||||||
1. 科技 - 新质科技、互联网等
|
1. 科技 - 新质科技、互联网、人工智能等
|
||||||
2. 社会 - 社会新闻、生活服务等
|
2. 社会 - 社会新闻、生活服务、热点事件等
|
||||||
3. 体育 - 体育新闻、足球等
|
3. 体育 - 体育新闻、足球、篮球等
|
||||||
4. 历史 - 历史事件、历史人物等
|
4. 历史 - 历史事件、历史人物、考古发现等
|
||||||
5. 安全 - 安全漏洞、安全科技等
|
5. 安全 - 安全漏洞、网络安全、数据安全等
|
||||||
6. 军事 - 军事新闻、国防等
|
6. 军事 - 军事新闻、国防、武器装备等
|
||||||
7. 金融 - 金融新闻、市场分析等
|
7. 金融 - 金融新闻、市场分析、投资等
|
||||||
8. 购物 - 电商、购物等
|
8. 购物 - 电商、购物、消费等
|
||||||
9. 游戏 - 游戏新闻等
|
9. 游戏 - 游戏新闻、游戏开发、游戏测评等
|
||||||
10. 娱乐 - 娱乐八卦、音乐等
|
10. 娱乐 - 娱乐八卦、音乐、影视等
|
||||||
11. 健康 - 健康医疗、健康生活等
|
11. 健康 - 健康医疗、健康生活、健身等
|
||||||
12. 其他 - 其他未分类内容
|
12. 其他 - 其他未分类内容
|
||||||
|
|
||||||
## 注意事项
|
## 注意事项
|
||||||
|
|
||||||
1. 确保本地Ollama服务已启动并可访问
|
1. **Ollama服务**:确保本地Ollama服务已启动并可访问(默认端口11434)
|
||||||
2. 临时文件格式必须为"日期+时间.txt"
|
2. **Chrome浏览器**:产品抓取功能需要已运行的Chrome浏览器实例(调试端口9222)
|
||||||
3. 每个数据单元包含5行:节点ID、分类、标题、链接和分隔线
|
3. **临时文件格式**:TopHub抓取生成的临时文件格式为"YYYY年MM月DD日HHMMSS.txt"
|
||||||
4. 数据库文件会自动创建,无需手动创建
|
4. **数据单元结构**:每个数据单元包含5行:节点ID、分类、标题、链接和分隔线
|
||||||
|
5. **数据库自动创建**:所有数据库文件会自动创建,无需手动创建
|
||||||
## 日志文件
|
6. **依赖安装**:使用GUI查看器前,请安装依赖:`pip install -r requirements_gui.txt`
|
||||||
|
7. **过滤列表配置**:可通过编辑tophub_ban_column.txt文件配置需要过滤的栏目
|
||||||
系统会生成以下日志文件:
|
|
||||||
- process_temp_files.log - 主处理日志
|
|
||||||
- cleanup_categories.log - 分类清理日志
|
|
||||||
- standardize_categories.log - 分类标准化日志
|
|
||||||
|
|
||||||
## 示例
|
## 示例
|
||||||
|
|
||||||
### 临时文件格式示例
|
### TopHub抓取临时文件示例
|
||||||
|
|
||||||
```
|
```
|
||||||
节点ID: 102
|
节点ID: 102
|
||||||
@@ -141,9 +270,18 @@ python check_db.py
|
|||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
```
|
```
|
||||||
|
|
||||||
### 处理结果示例
|
### 产品分析结果示例
|
||||||
|
|
||||||
```
|
```
|
||||||
标题 '女机器人' 分类为: 科技
|
产品 'AI Assistant' 分析完成
|
||||||
标题 '这个应该属于底盘不行吗' 分类为: 其他
|
- 难度描述: 中等难度,需要一定的AI开发经验
|
||||||
```
|
- 难度分数: 60/100
|
||||||
|
- 关注数: 1500
|
||||||
|
```
|
||||||
|
|
||||||
|
### 数据库查看器界面
|
||||||
|
|
||||||
|
- 显示所有抓取数据,支持实时搜索和筛选
|
||||||
|
- 分类统计显示在顶部
|
||||||
|
- 点击链接可直接在浏览器中打开
|
||||||
|
- 右键菜单支持批量操作和评分调整
|
||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 223 KiB After Width: | Height: | Size: 626 KiB |
@@ -732,7 +732,7 @@ class IntegratedProductSystem:
|
|||||||
logger.info("数据库连接已关闭")
|
logger.info("数据库连接已关闭")
|
||||||
|
|
||||||
def analyze_follower_counts(self):
|
def analyze_follower_counts(self):
|
||||||
"""分析并更新产品的关注数"""
|
"""分析并更新产品的关注数,仅当follows字段为空或不存在时更新"""
|
||||||
logger.info("=== 开始分析产品关注数 ===")
|
logger.info("=== 开始分析产品关注数 ===")
|
||||||
|
|
||||||
conn = None
|
conn = None
|
||||||
@@ -741,12 +741,14 @@ class IntegratedProductSystem:
|
|||||||
conn = self.connect_to_database()
|
conn = self.connect_to_database()
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
|
|
||||||
# 查询所有产品及其对应的分析记录
|
# 查询所有产品及其对应的分析记录,仅包括follows字段为空或不存在的记录
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
SELECT p.id, p.name, p.user_count, pa.id as analysis_id
|
SELECT p.id, p.name, p.user_count, pa.id as analysis_id, pa.follows
|
||||||
FROM products p
|
FROM products p
|
||||||
LEFT JOIN product_analysis pa ON p.name = pa.original_name
|
LEFT JOIN product_analysis pa ON p.name = pa.original_name
|
||||||
WHERE p.user_count IS NOT NULL AND p.user_count != ''
|
WHERE p.user_count IS NOT NULL AND p.user_count != ''
|
||||||
|
AND pa.id IS NOT NULL
|
||||||
|
AND (pa.follows IS NULL OR pa.follows = '')
|
||||||
""")
|
""")
|
||||||
|
|
||||||
products = cursor.fetchall()
|
products = cursor.fetchall()
|
||||||
@@ -758,7 +760,7 @@ class IntegratedProductSystem:
|
|||||||
|
|
||||||
# 为每个产品转换user_count并更新到product_analysis.follows
|
# 为每个产品转换user_count并更新到product_analysis.follows
|
||||||
updated_count = 0
|
updated_count = 0
|
||||||
for i, (product_id, name, user_count, analysis_id) in enumerate(products, 1):
|
for i, (product_id, name, user_count, analysis_id, current_follows) in enumerate(products, 1):
|
||||||
logger.info(f"处理产品关注数 {i}/{len(products)}: {name}, 用户数: {user_count}")
|
logger.info(f"处理产品关注数 {i}/{len(products)}: {name}, 用户数: {user_count}")
|
||||||
|
|
||||||
if not analysis_id:
|
if not analysis_id:
|
||||||
@@ -893,8 +895,90 @@ class IntegratedProductSystem:
|
|||||||
conn.close()
|
conn.close()
|
||||||
logger.info("数据库连接已关闭")
|
logger.info("数据库连接已关闭")
|
||||||
|
|
||||||
|
def fill_missing_product_links(self):
|
||||||
|
"""检查product_analysis表中的product_link字段是否为空,如果为空则从tophub_data.db补全"""
|
||||||
|
logger.info("=== 开始补全缺失的product_link字段 ===")
|
||||||
|
|
||||||
|
# 检查tophub_data.db是否存在
|
||||||
|
tophub_db_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "tophub_data.db")
|
||||||
|
if not os.path.exists(tophub_db_path):
|
||||||
|
logger.error(f"tophub_data.db不存在: {tophub_db_path}")
|
||||||
|
return
|
||||||
|
|
||||||
|
conn_product = None
|
||||||
|
conn_tophub = None
|
||||||
|
try:
|
||||||
|
# 连接两个数据库
|
||||||
|
conn_product = self.connect_to_database()
|
||||||
|
cursor_product = conn_product.cursor()
|
||||||
|
|
||||||
|
conn_tophub = sqlite3.connect(tophub_db_path)
|
||||||
|
cursor_tophub = conn_tophub.cursor()
|
||||||
|
logger.success(f"成功连接到tophub_data.db: {tophub_db_path}")
|
||||||
|
|
||||||
|
# 查询product_link为空的记录
|
||||||
|
cursor_product.execute("""
|
||||||
|
SELECT id, original_name
|
||||||
|
FROM product_analysis
|
||||||
|
WHERE product_link IS NULL OR product_link = ''
|
||||||
|
""")
|
||||||
|
|
||||||
|
missing_link_records = cursor_product.fetchall()
|
||||||
|
logger.info(f"找到 {len(missing_link_records)} 条product_link为空的记录需要补全")
|
||||||
|
|
||||||
|
if not missing_link_records:
|
||||||
|
logger.info("没有发现需要补全product_link的记录")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 获取tophub_data.db中的所有producthunt链接
|
||||||
|
cursor_tophub.execute("SELECT url FROM articles WHERE url LIKE '%producthunt.com%'")
|
||||||
|
tophub_urls = [row[0] for row in cursor_tophub.fetchall()]
|
||||||
|
logger.info(f"从tophub_data.db获取到 {len(tophub_urls)} 个producthunt链接")
|
||||||
|
|
||||||
|
if not tophub_urls:
|
||||||
|
logger.error("从tophub_data.db中没有找到producthunt链接")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 为每个缺失product_link的记录查找匹配的URL
|
||||||
|
updated_count = 0
|
||||||
|
for i, (analysis_id, original_name) in enumerate(missing_link_records, 1):
|
||||||
|
logger.info(f"处理记录 {i}/{len(missing_link_records)}: {original_name}")
|
||||||
|
|
||||||
|
# 查找匹配的URL
|
||||||
|
matched_url = None
|
||||||
|
for url in tophub_urls:
|
||||||
|
# 简单的匹配逻辑:如果产品名称在URL中出现
|
||||||
|
if original_name.lower() in url.lower():
|
||||||
|
matched_url = url
|
||||||
|
break
|
||||||
|
|
||||||
|
if matched_url:
|
||||||
|
# 更新product_link字段
|
||||||
|
cursor_product.execute("""
|
||||||
|
UPDATE product_analysis
|
||||||
|
SET product_link = ?
|
||||||
|
WHERE id = ?
|
||||||
|
""", (matched_url, analysis_id))
|
||||||
|
conn_product.commit()
|
||||||
|
updated_count += 1
|
||||||
|
logger.success(f"成功为产品 '{original_name}' 补全链接: {matched_url}")
|
||||||
|
else:
|
||||||
|
logger.warning(f"无法为产品 '{original_name}' 找到匹配的链接")
|
||||||
|
|
||||||
|
logger.success(f"product_link补全完成! 成功更新 {updated_count} 条记录")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"补全product_link过程中出错: {e}")
|
||||||
|
finally:
|
||||||
|
# 关闭数据库连接
|
||||||
|
if conn_product:
|
||||||
|
conn_product.close()
|
||||||
|
if conn_tophub:
|
||||||
|
conn_tophub.close()
|
||||||
|
logger.info("数据库连接已关闭")
|
||||||
|
|
||||||
async def run_full_workflow_async(self, max_products=None, analyze_only=False):
|
async def run_full_workflow_async(self, max_products=None, analyze_only=False):
|
||||||
"""异步运行完整工作流程:抓取+分析+补充缺失分数+更新关注数+重新分析无效难度评分"""
|
"""异步运行完整工作流程:抓取+分析+补充缺失分数+更新关注数+重新分析无效难度评分+补全product_link"""
|
||||||
logger.info("=== 开始全功能产品系统工作流程 ===")
|
logger.info("=== 开始全功能产品系统工作流程 ===")
|
||||||
|
|
||||||
# 初始化数据库
|
# 初始化数据库
|
||||||
@@ -923,6 +1007,10 @@ class IntegratedProductSystem:
|
|||||||
logger.info("步骤5: 开始重新分析invalid难度评分...")
|
logger.info("步骤5: 开始重新分析invalid难度评分...")
|
||||||
self.reanalyze_invalid_difficulty_scores()
|
self.reanalyze_invalid_difficulty_scores()
|
||||||
|
|
||||||
|
# 步骤6: 补全缺失的product_link字段
|
||||||
|
logger.info("步骤6: 开始补全缺失的product_link字段...")
|
||||||
|
self.fill_missing_product_links()
|
||||||
|
|
||||||
logger.success("=== 全功能产品系统工作流程完成 ===")
|
logger.success("=== 全功能产品系统工作流程完成 ===")
|
||||||
|
|
||||||
def run_full_workflow(self, max_products=None, analyze_only=False):
|
def run_full_workflow(self, max_products=None, analyze_only=False):
|
||||||
|
|||||||
Binary file not shown.
@@ -1,76 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
数据库更新脚本
|
|
||||||
用于更新现有的product_analysis表,添加follows字段
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sqlite3
|
|
||||||
import os
|
|
||||||
from loguru import logger
|
|
||||||
import sys
|
|
||||||
|
|
||||||
# 配置日志
|
|
||||||
logger.remove()
|
|
||||||
logger.add(sys.stderr, level="INFO", format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>")
|
|
||||||
|
|
||||||
def update_product_analysis_table(db_path):
|
|
||||||
"""更新product_analysis表,添加follows字段"""
|
|
||||||
logger.info(f"开始更新数据库: {db_path}")
|
|
||||||
|
|
||||||
try:
|
|
||||||
# 连接数据库
|
|
||||||
conn = sqlite3.connect(db_path)
|
|
||||||
cursor = conn.cursor()
|
|
||||||
|
|
||||||
# 检查product_analysis表是否存在
|
|
||||||
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='product_analysis'")
|
|
||||||
table_exists = cursor.fetchone() is not None
|
|
||||||
|
|
||||||
if not table_exists:
|
|
||||||
logger.error("product_analysis表不存在,无法更新")
|
|
||||||
conn.close()
|
|
||||||
return False
|
|
||||||
|
|
||||||
# 检查follows字段是否已经存在
|
|
||||||
cursor.execute("PRAGMA table_info(product_analysis)")
|
|
||||||
columns = [col[1] for col in cursor.fetchall()]
|
|
||||||
|
|
||||||
if 'follows' in columns:
|
|
||||||
logger.info("follows字段已经存在,无需更新")
|
|
||||||
conn.close()
|
|
||||||
return True
|
|
||||||
|
|
||||||
# 添加follows字段
|
|
||||||
cursor.execute("ALTER TABLE product_analysis ADD COLUMN follows INTEGER")
|
|
||||||
conn.commit()
|
|
||||||
|
|
||||||
logger.success("成功为product_analysis表添加follows字段")
|
|
||||||
conn.close()
|
|
||||||
return True
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"更新数据库失败: {e}")
|
|
||||||
if 'conn' in locals():
|
|
||||||
conn.close()
|
|
||||||
return False
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""主函数"""
|
|
||||||
# 获取默认数据库路径
|
|
||||||
default_db_path = os.path.join(os.path.dirname(__file__), "products.db")
|
|
||||||
|
|
||||||
logger.info("=== 数据库更新脚本开始执行 ===")
|
|
||||||
|
|
||||||
# 更新数据库
|
|
||||||
success = update_product_analysis_table(default_db_path)
|
|
||||||
|
|
||||||
if success:
|
|
||||||
logger.success("=== 数据库更新成功 ===")
|
|
||||||
sys.exit(0)
|
|
||||||
else:
|
|
||||||
logger.error("=== 数据库更新失败 ===")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 374 KiB |
@@ -1,11 +1,11 @@
|
|||||||
=== Product Hunt 产品信息 ===
|
=== Product Hunt 产品信息 ===
|
||||||
|
|
||||||
产品名称: Monifi
|
产品名称: TypMo
|
||||||
|
|
||||||
产品简介: An Excel alternative to manage your personal finances. Track income, expenses, and savings without spreadsheets. Free budgeting app with real-time reports and smart categorization.
|
产品简介: TypMo is where wireframes become prompts. Write UI in simple text syntax, like Markdown, or generate from prompts and sketches. 60+ components, zero learning curve. Iterate freely when changes are cheap, share with stakeholders, gather feedback. Then export detailed implementation specs for AI Coding tools. Clarity before code. Wireframe first, prompt with precision.
|
||||||
|
|
||||||
制作人发言:
|
制作人发言: Winner • Design Tools Product of the Year
|
||||||
|
|
||||||
用户数: 32 followers
|
用户数: 65 followers
|
||||||
|
|
||||||
提取时间: 2025-12-04 21:05:56
|
提取时间: 2025-12-04 21:29:50
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
BIN
tophub_data.db
BIN
tophub_data.db
Binary file not shown.
7695
tophub_scraper.log
7695
tophub_scraper.log
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user