feat: v2.3.0 - 新闻获取准确性优化

核心改进:
1. 新增专用新闻关键词字段(sites.news_keywords)
2. 严格匹配搜索策略(双引号包裹关键词)
3. 前台手动刷新新闻功能

数据库变更:
- Sites表添加news_keywords字段(VARCHAR(200))
- 提供迁移脚本migrate_news_keywords.py

代码变更:
- models.py: Site模型添加news_keywords字段
- app.py: 后台表单配置、API路由、search_site_news调用优化
- utils/news_searcher.py: 支持news_keywords参数优先匹配
- templates/detail_new.html: 添加刷新按钮和JavaScript

新增功能:
- 后台可为每个网站设置专属新闻关键词
- 详情页"获取最新资讯"按钮(前台可用,无需登录)
- 新API端点:POST /api/refresh-site-news/<site_code>

文档:
- DEPLOY_v2.3.0.md: 完整部署指南
- DEPLOY_v2.3_QUICK.md: 快速部署指南

向后兼容:
- 现有网站自动使用网站名称作为默认关键词
- 未设置关键词时降级使用网站名称搜索

🤖 Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Jowe
2025-12-31 11:01:51 +08:00
parent bdf31090ed
commit fdde6990fb
7 changed files with 1009 additions and 8 deletions

85
app.py
View File

@@ -146,6 +146,7 @@ def create_app(config_name='default'):
news_items = searcher.search_site_news(
site_name=site.name,
site_url=site.url,
news_keywords=site.news_keywords, # v2.3新增:使用专用关键词
count=3,
freshness='oneWeek'
)
@@ -547,6 +548,7 @@ def create_app(config_name='default'):
news_items = searcher.search_site_news(
site_name=site.name,
site_url=site.url,
news_keywords=site.news_keywords, # v2.3新增:使用专用关键词
count=count,
freshness=freshness
)
@@ -642,6 +644,7 @@ def create_app(config_name='default'):
news_items = searcher.search_site_news(
site_name=site.name,
site_url=site.url,
news_keywords=site.news_keywords, # v2.3新增:使用专用关键词
count=count_per_site,
freshness=freshness
)
@@ -706,6 +709,85 @@ def create_app(config_name='default'):
'message': f'批量获取失败: {str(e)}'
}), 500
@app.route('/api/refresh-site-news/<site_code>', methods=['POST'])
def refresh_site_news(site_code):
"""手动刷新指定网站的新闻(前台用户可访问)- v2.3新增"""
try:
# 根据code查找网站
site = Site.query.filter_by(code=site_code).first()
if not site:
return jsonify({
'success': False,
'message': '网站不存在'
}), 404
# 检查博查API配置
api_key = app.config.get('BOCHA_API_KEY')
if not api_key:
return jsonify({
'success': False,
'message': '新闻功能未启用'
}), 500
# 创建新闻搜索器
searcher = NewsSearcher(api_key)
# 搜索新闻获取最新5条
news_items = searcher.search_site_news(
site_name=site.name,
site_url=site.url,
news_keywords=site.news_keywords, # 使用专用关键词
count=5,
freshness='oneWeek' # 一周内的新闻
)
if not news_items:
return jsonify({
'success': False,
'message': '未找到相关新闻'
}), 404
# 保存新闻到数据库
saved_count = 0
for item in news_items:
# 检查新闻是否已存在根据URL判断
existing_news = News.query.filter_by(
site_id=site.id,
url=item['url']
).first()
if not existing_news:
news = News(
site_id=site.id,
title=item['title'],
content=item.get('summary') or item.get('snippet', ''),
url=item['url'],
source_name=item.get('site_name', ''),
source_icon=item.get('site_icon', ''),
published_at=item.get('published_at'),
news_type='Search Result',
is_active=True
)
db.session.add(news)
saved_count += 1
# 提交事务
db.session.commit()
return jsonify({
'success': True,
'message': f'成功获取 {saved_count} 条新资讯',
'total_found': len(news_items),
'saved_count': saved_count
})
except Exception as e:
db.session.rollback()
return jsonify({
'success': False,
'message': f'获取失败: {str(e)}'
}), 500
# ========== 批量导入路由 ==========
@app.route('/admin/batch-import', methods=['GET', 'POST'])
@login_required
@@ -1004,6 +1086,7 @@ def create_app(config_name='default'):
'short_desc': '简短描述',
'description': '详细介绍',
'features': '主要功能',
'news_keywords': '新闻关键词',
'is_active': '是否启用',
'view_count': '浏览次数',
'sort_order': '排序权重',
@@ -1011,7 +1094,7 @@ def create_app(config_name='default'):
'created_at': '创建时间',
'updated_at': '更新时间'
}
form_columns = ['name', 'url', 'slug', 'logo', 'short_desc', 'description', 'features', 'tags', 'is_active', 'sort_order']
form_columns = ['name', 'url', 'slug', 'logo', 'short_desc', 'description', 'features', 'news_keywords', 'tags', 'is_active', 'sort_order']
# 自定义编辑/删除文字
column_extra_row_actions = None