Phase1: 效果数据真实化
- 替换scheduler.py中假随机数metrics_sync为知乎API自动获取 - 新增 POST /api/metrics/zhihu-fetch 知乎公开数据API端点 - metrics.html新增「数据录入」tab:手动录入表单+已有数据列表+知乎自动获取 - gitignore清理已跟踪的生成文件(outlines/research/images/cache)
This commit is contained in:
@@ -165,12 +165,12 @@ class TaskScheduler:
|
||||
logger.exception("[Scheduled] Source AI optimization failed: %s", e)
|
||||
|
||||
def _run_metrics_sync(self):
|
||||
"""定时从各平台公开API获取发布文章的效果数据(当前仅支持知乎)"""
|
||||
try:
|
||||
logger.info("[Scheduled] Starting metrics sync...")
|
||||
logger.info("[Scheduled] Starting metrics sync (zhihu auto-fetch)...")
|
||||
from ..database import SessionLocal
|
||||
from ..models import Topic, ContentMetrics, PublishRecord
|
||||
import random, math
|
||||
from datetime import date
|
||||
from ..models import Topic, ContentMetrics
|
||||
import re, requests as http_requests
|
||||
|
||||
db = SessionLocal()
|
||||
try:
|
||||
@@ -182,58 +182,51 @@ class TaskScheduler:
|
||||
db.close()
|
||||
return
|
||||
|
||||
random.seed(42)
|
||||
multipliers = {
|
||||
"zhihu": {"v": 1.0, "l": 1.2, "f": 0.6, "c": 1.5, "s": 0.3},
|
||||
"wechat": {"v": 1.8, "l": 0.6, "f": 0.4, "c": 0.3, "s": 2.0},
|
||||
"xiaohongshu": {"v": 2.5, "l": 1.5, "f": 1.8, "c": 1.0, "s": 1.5},
|
||||
}
|
||||
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
|
||||
count = 0
|
||||
for topic in topics:
|
||||
platforms = set()
|
||||
records = db.query(PublishRecord).filter(
|
||||
PublishRecord.topic_id == topic.id,
|
||||
PublishRecord.action == "publish",
|
||||
PublishRecord.status == "success"
|
||||
).all()
|
||||
for rec in records:
|
||||
platforms.add(rec.platform)
|
||||
if not platforms:
|
||||
platforms = {"zhihu", "wechat", "xiaohongshu"}
|
||||
days = max(1, (date.today() - (topic.published_at or date.today())).days)
|
||||
quality = (topic.compliance_score or 70) / 100.0
|
||||
for plat in platforms:
|
||||
if plat not in multipliers:
|
||||
platform_urls = topic.platform_urls or {}
|
||||
zhihu_url = platform_urls.get("zhihu", "")
|
||||
if not zhihu_url:
|
||||
continue
|
||||
m = re.search(r'zhuanlan\.zhihu\.com/p/(\d+)', zhihu_url)
|
||||
if not m:
|
||||
continue
|
||||
post_id = m.group(1)
|
||||
api_url = f"https://zhuanlan.zhihu.com/api/posts/{post_id}"
|
||||
try:
|
||||
resp = http_requests.get(api_url, headers={"User-Agent": ua}, timeout=10)
|
||||
if resp.status_code != 200:
|
||||
continue
|
||||
m = multipliers[plat]
|
||||
base = random.randint(30, 200)
|
||||
growth = 1 + math.log(days + 1, 2) * 0.5
|
||||
views = int(base * m["v"] * growth)
|
||||
likes = int(views * quality * 0.08 * m["l"])
|
||||
favs = int(likes * 0.5 * m["f"])
|
||||
comm = int(views * quality * 0.02 * m["c"])
|
||||
shar = int(views * quality * 0.03 * m["s"])
|
||||
raw = resp.json()
|
||||
existing = db.query(ContentMetrics).filter(
|
||||
ContentMetrics.topic_id == topic.id,
|
||||
ContentMetrics.platform == plat
|
||||
ContentMetrics.platform == "zhihu"
|
||||
).first()
|
||||
metric_data = {
|
||||
"views": raw.get("voteup_count", raw.get("views_count", 0)),
|
||||
"likes": raw.get("voteup_count", 0),
|
||||
"favorites": raw.get("favorite_count", 0),
|
||||
"comments": raw.get("comment_count", raw.get("comments_count", 0)),
|
||||
"shares": raw.get("share_count", 0),
|
||||
"last_fetched": datetime.now(),
|
||||
"publish_url": zhihu_url,
|
||||
"data_snapshot": raw,
|
||||
}
|
||||
if existing:
|
||||
existing.views = views
|
||||
existing.likes = likes
|
||||
existing.favorites = favs
|
||||
existing.comments = comm
|
||||
existing.shares = shar
|
||||
existing.last_fetched = datetime.now()
|
||||
for k, v in metric_data.items():
|
||||
setattr(existing, k, v)
|
||||
else:
|
||||
db.add(ContentMetrics(
|
||||
topic_id=topic.id, platform=plat,
|
||||
views=views, likes=likes, favorites=favs,
|
||||
comments=comm, shares=shar, last_fetched=datetime.now()
|
||||
))
|
||||
db.add(ContentMetrics(topic_id=topic.id, platform="zhihu", **metric_data))
|
||||
count += 1
|
||||
db.commit()
|
||||
except Exception:
|
||||
continue
|
||||
if count:
|
||||
db.commit()
|
||||
logger.info("[Scheduled] Metrics sync completed: synced %d zhihu articles", count)
|
||||
else:
|
||||
logger.info("[Scheduled] Metrics sync: no zhihu articles to sync")
|
||||
db.close()
|
||||
logger.info("[Scheduled] Metrics sync completed: %d entries for %d topics", count, len(topics))
|
||||
except Exception as e:
|
||||
logger.exception("[Scheduled] Metrics sync failed: %s", e)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user