|
|
@@ -37,24 +37,21 @@ class ArticleFetchDetail(DemandSearchArticleConst):
|
|
|
"""串行处理待拉详情项
|
|
|
|
|
|
Returns:
|
|
|
- {"pending": int, "success": int, "failed": int, "skipped": int}
|
|
|
+ {"pending": int, "success": int, "failed": int}
|
|
|
"""
|
|
|
items = await self.relation_mapper.fetch_pending(limit=limit)
|
|
|
if not items:
|
|
|
logger.info("无待拉详情项")
|
|
|
- return {"pending": 0, "success": 0, "failed": 0, "skipped": 0}
|
|
|
-
|
|
|
- ids = [it["id"] for it in items]
|
|
|
- await self.relation_mapper.mark_processing(ids)
|
|
|
+ return {"pending": 0, "success": 0, "failed": 0}
|
|
|
|
|
|
success = 0
|
|
|
failed = 0
|
|
|
- skipped = 0
|
|
|
for item in items:
|
|
|
+ await self.relation_mapper.mark_processing([item["id"]])
|
|
|
if success + failed > 0: # 非首条,等待后执行
|
|
|
await asyncio.sleep(self.DETAIL_INTERVAL_SEC)
|
|
|
try:
|
|
|
- outcome, _ = await self._fetch_detail_and_save(item)
|
|
|
+ outcome = await self._fetch_detail_and_save(item)
|
|
|
except Exception:
|
|
|
logger.exception(
|
|
|
"详情拉取异常: relation_id=%s", item["id"],
|
|
|
@@ -65,37 +62,34 @@ class ArticleFetchDetail(DemandSearchArticleConst):
|
|
|
|
|
|
if outcome == "success":
|
|
|
success += 1
|
|
|
- elif outcome == "failed":
|
|
|
- failed += 1
|
|
|
else:
|
|
|
- skipped += 1
|
|
|
+ failed += 1
|
|
|
|
|
|
logger.info(
|
|
|
- "详情拉取完成: total=%d, success=%d, failed=%d, skipped=%d",
|
|
|
- len(items), success, failed, skipped,
|
|
|
+ "详情拉取完成: total=%d, success=%d, failed=%d",
|
|
|
+ len(items), success, failed,
|
|
|
)
|
|
|
return {
|
|
|
"pending": len(items),
|
|
|
"success": success,
|
|
|
"failed": failed,
|
|
|
- "skipped": skipped,
|
|
|
}
|
|
|
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
# 单条处理
|
|
|
# ═══════════════════════════════════════════════════════════════
|
|
|
|
|
|
- async def _fetch_detail_and_save(self, item: Dict) -> tuple[str, int | None]:
|
|
|
+ async def _fetch_detail_and_save(self, item: Dict) -> str:
|
|
|
"""拉取详情 → 写 detail 表 → 更新 relation 状态
|
|
|
|
|
|
Returns:
|
|
|
- ("success"/"failed"/"skipped", relation_id)
|
|
|
+ "success" 或 "failed"
|
|
|
"""
|
|
|
url = item.get("url", "")
|
|
|
if not url:
|
|
|
logger.warning("空 URL, 跳过 relation_id=%s", item["id"])
|
|
|
await self.relation_mapper.mark_failed([item["id"]])
|
|
|
- return ("failed", item["id"])
|
|
|
+ return "failed"
|
|
|
|
|
|
try:
|
|
|
resp = await get_article_detail(url)
|
|
|
@@ -104,7 +98,7 @@ class ArticleFetchDetail(DemandSearchArticleConst):
|
|
|
"get_article_detail 调用异常: url=%s, relation_id=%s", url, item["id"],
|
|
|
)
|
|
|
await self.relation_mapper.mark_failed([item["id"]])
|
|
|
- return ("failed", item["id"])
|
|
|
+ return "failed"
|
|
|
|
|
|
if not resp or resp.get("code") != 0:
|
|
|
logger.warning(
|
|
|
@@ -112,7 +106,7 @@ class ArticleFetchDetail(DemandSearchArticleConst):
|
|
|
url, item["id"], resp.get("code") if resp else "None",
|
|
|
)
|
|
|
await self.relation_mapper.mark_failed([item["id"]])
|
|
|
- return ("failed", item["id"])
|
|
|
+ return "failed"
|
|
|
|
|
|
detail_data = (resp.get("data") or {}).get("data")
|
|
|
if not detail_data:
|
|
|
@@ -120,7 +114,7 @@ class ArticleFetchDetail(DemandSearchArticleConst):
|
|
|
"详情数据为空: url=%s, relation_id=%s", url, item["id"],
|
|
|
)
|
|
|
await self.relation_mapper.mark_failed([item["id"]])
|
|
|
- return ("failed", item["id"])
|
|
|
+ return "failed"
|
|
|
|
|
|
channel_content_id = detail_data.get("channel_content_id", "")
|
|
|
if not channel_content_id:
|
|
|
@@ -128,7 +122,7 @@ class ArticleFetchDetail(DemandSearchArticleConst):
|
|
|
"channel_content_id 为空: url=%s, relation_id=%s", url, item["id"],
|
|
|
)
|
|
|
await self.relation_mapper.mark_failed([item["id"]])
|
|
|
- return ("failed", item["id"])
|
|
|
+ return "failed"
|
|
|
|
|
|
detail_row = parse_detail(detail_data)
|
|
|
await self.detail_mapper.insert_one(detail_row)
|
|
|
@@ -140,7 +134,7 @@ class ArticleFetchDetail(DemandSearchArticleConst):
|
|
|
"详情拉取成功: relation_id=%s, channel_content_id=%s, title=%s",
|
|
|
item["id"], channel_content_id, detail_row.get("title", "")[:40],
|
|
|
)
|
|
|
- return ("success", item["id"])
|
|
|
+ return "success"
|
|
|
|
|
|
|
|
|
__all__ = ["ArticleFetchDetail"]
|