mirror of
https://github.com/KingHWJ/WeReadBoard.git
synced 2026-11-03 18:24:58 +08:00
feat(discovery): 完善书籍搜索推荐与日志记录
This commit is contained in:
1 parent
aee8c58b04
commit
61d3951905
4 files changed
+263
-27
No files matched your search
@@ -172,6 +172,82 @@ def query_one(conn, sql, params=None):
|
||||
return rows[0] if rows else None
|
||||
|
||||
|
||||
def upsert_recommended_book(conn, values):
|
||||
"""按 book_id 更新推荐缓存,避免同一本书每次推荐都新增一行。"""
|
||||
if not conn:
|
||||
return
|
||||
columns = (
|
||||
"book_id, title, author, cover, intro, category, reason, reading_count, "
|
||||
"new_rating, new_rating_count, rating_title, deep_link, search_idx, price, "
|
||||
"pay_type, book_type, batch_id"
|
||||
)
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute("SELECT id FROM recommended_books WHERE book_id=%s ORDER BY id LIMIT 1", (values[0],))
|
||||
row = cur.fetchone()
|
||||
if row:
|
||||
cur.execute(
|
||||
"UPDATE recommended_books SET title=%s, author=%s, cover=%s, intro=%s, category=%s, "
|
||||
"reason=%s, reading_count=%s, new_rating=%s, new_rating_count=%s, rating_title=%s, "
|
||||
"deep_link=%s, search_idx=%s, price=%s, pay_type=%s, book_type=%s, batch_id=%s, "
|
||||
"updated_at=NOW() WHERE id=%s",
|
||||
(*values[1:], row[0]),
|
||||
)
|
||||
else:
|
||||
cur.execute(
|
||||
f"INSERT INTO recommended_books ({columns}) VALUES ({','.join(['%s'] * 17)})",
|
||||
values,
|
||||
)
|
||||
cur.execute(
|
||||
"INSERT INTO content_logs "
|
||||
"(event_type, batch_id, book_id, search_idx) VALUES ('recommendation',%s,%s,%s)",
|
||||
(values[16], values[0], values[12] or 0),
|
||||
)
|
||||
conn.commit()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def upsert_search_result(conn, session_id, values):
|
||||
"""按 keyword + book_id 更新搜索缓存,避免重复搜索产生重复行。"""
|
||||
if not conn or not session_id:
|
||||
return
|
||||
keyword, book_id = values[0], values[1]
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"SELECT id FROM search_results WHERE keyword=%s AND book_id=%s ORDER BY id LIMIT 1",
|
||||
(keyword, book_id),
|
||||
)
|
||||
row = cur.fetchone()
|
||||
if row:
|
||||
cur.execute(
|
||||
"UPDATE search_results SET session_id=%s, title=%s, author=%s, cover=%s, intro=%s, "
|
||||
"publisher=%s, category=%s, reading_count=%s, new_rating=%s, new_rating_count=%s, "
|
||||
"rating_title=%s, deep_link=%s, pay_type=%s, price=%s, soldout=%s, search_idx=%s, "
|
||||
"result_scope=%s, result_title=%s, scope_count=%s, current_count=%s, updated_at=NOW() "
|
||||
"WHERE id=%s",
|
||||
(session_id, *values[2:], row[0]),
|
||||
)
|
||||
else:
|
||||
cur.execute(
|
||||
"INSERT INTO search_results "
|
||||
"(session_id, keyword, book_id, title, author, cover, intro, publisher, category, "
|
||||
"reading_count, new_rating, new_rating_count, rating_title, deep_link, pay_type, price, "
|
||||
"soldout, search_idx, result_scope, result_title, scope_count, current_count) "
|
||||
f"VALUES ({','.join(['%s'] * 22)})",
|
||||
(session_id, *values),
|
||||
)
|
||||
cur.execute(
|
||||
"INSERT INTO content_logs "
|
||||
"(event_type, session_id, keyword, book_id, search_idx) VALUES ('search',%s,%s,%s,%s)",
|
||||
(session_id, keyword, book_id, values[16] or 0),
|
||||
)
|
||||
conn.commit()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
# ======================================================================
|
||||
# 格式化与展示辅助
|
||||
# ======================================================================
|
||||
@@ -1368,14 +1444,41 @@ def api_v2_archives(conn):
|
||||
def api_v2_recommend(conn):
|
||||
"""为你推荐(实时)。Query: maxIdx"""
|
||||
max_idx = request.args.get("maxIdx", type=int, default=0)
|
||||
refresh = request.args.get("refresh", "0") == "1"
|
||||
try:
|
||||
data = weapi("/book/recommend", ttl=600, count=12, maxIdx=max_idx)
|
||||
data = weapi("/book/recommend", ttl=0 if refresh else 600, count=12, maxIdx=max_idx)
|
||||
except WeReadError as e:
|
||||
return jsonify({"error": str(e)}), 502
|
||||
|
||||
books = []
|
||||
for book in data.get("books") or []:
|
||||
batch_id = datetime.now().strftime("%Y%m%d%H%M%S")
|
||||
raw_books = data.get("books") or []
|
||||
|
||||
def enrich_recommendation(book):
|
||||
info = weapi_safe("/book/info", ttl=1800, bookId=str(book.get("bookId") or "")) or {}
|
||||
merged = dict(book)
|
||||
for key in ("cover", "newRating", "newRatingCount", "newRatingDetail", "intro", "category", "deepLink"):
|
||||
if not merged.get(key) and info.get(key):
|
||||
merged[key] = info[key]
|
||||
return merged
|
||||
|
||||
with ThreadPoolExecutor(max_workers=6) as pool:
|
||||
enriched_books = list(pool.map(enrich_recommendation, raw_books))
|
||||
|
||||
for book in enriched_books:
|
||||
rating_detail = book.get("newRatingDetail") or {}
|
||||
if conn:
|
||||
upsert_recommended_book(
|
||||
conn,
|
||||
(
|
||||
book.get("bookId", ""), book.get("title", ""), book.get("author", ""),
|
||||
book.get("cover", ""), book.get("intro", ""), book.get("category", ""),
|
||||
book.get("reason", ""), book.get("readingCount", 0), book.get("newRating", 0),
|
||||
book.get("newRatingCount", 0), (rating_detail or {}).get("title", ""),
|
||||
book.get("deepLink", ""), book.get("searchIdx", 0), book.get("price"),
|
||||
book.get("payType"), book.get("type", 0), batch_id,
|
||||
),
|
||||
)
|
||||
books.append(
|
||||
{
|
||||
"id": str(book.get("bookId") or ""),
|
||||
@@ -1436,16 +1539,28 @@ def api_v2_search(conn):
|
||||
return jsonify({"error": str(e), "keyword": keyword, "scope": scope_name}), 502
|
||||
|
||||
books, authors, lists, groups = [], [], [], []
|
||||
session_id = None
|
||||
if conn:
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"INSERT INTO search_sessions (sid, keyword, scope, has_more, max_idx) VALUES (%s,%s,%s,%s,%s)",
|
||||
(data.get("sid", ""), keyword, scope, data.get("hasMore", 0), 0),
|
||||
)
|
||||
session_id = cur.lastrowid
|
||||
except Exception:
|
||||
session_id = None
|
||||
seen_books, seen_authors, seen_groups = set(), set(), set()
|
||||
for group in data.get("results") or []:
|
||||
title = group.get("title") or ""
|
||||
gkey = (title, group.get("scope"), group.get("currentCount"))
|
||||
if gkey in seen_groups:
|
||||
continue
|
||||
seen_groups.add(gkey)
|
||||
if gkey not in seen_groups:
|
||||
seen_groups.add(gkey)
|
||||
if title:
|
||||
groups.append({"title": title, "scope": group.get("scope"), "count": group.get("scopeCount") or 0})
|
||||
items = group.get("books") or []
|
||||
if title:
|
||||
groups.append({"title": title, "scope": group.get("scope"), "count": group.get("scopeCount") or 0})
|
||||
if title == "作者" and not items and group.get("scopeCount"):
|
||||
authors.append({"name": keyword, "count": group.get("scopeCount") or 0})
|
||||
for item in items:
|
||||
bi = item.get("bookInfo") or item.get("book") or {}
|
||||
bid = str(bi.get("bookId") or "")
|
||||
@@ -1468,13 +1583,26 @@ def api_v2_search(conn):
|
||||
"short": short_title(bi.get("title")),
|
||||
"desc": bi.get("intro") or "",
|
||||
"category": bi.get("category") or "",
|
||||
"score": round(float(item.get("newRating") or 0) / 100, 1) if item.get("newRating") else None,
|
||||
"score": round(float(bi.get("newRating") or 0) / 100, 1) if bi.get("newRating") else None,
|
||||
"reading_count": item.get("readingCount") or 0,
|
||||
"deep_link": bi.get("deepLink") or "",
|
||||
"group": title,
|
||||
"status": "wish",
|
||||
"progress": 0,
|
||||
}
|
||||
if session_id:
|
||||
upsert_search_result(
|
||||
conn,
|
||||
session_id,
|
||||
(
|
||||
keyword, bid, entry["title"], entry["author"], bi.get("cover", ""),
|
||||
bi.get("intro", ""), bi.get("publisher", ""), entry["category"],
|
||||
item.get("readingCount", 0), bi.get("newRating", 0), bi.get("newRatingCount", 0),
|
||||
(bi.get("newRatingDetail") or {}).get("title", ""), entry["deep_link"],
|
||||
bi.get("payType"), bi.get("price"), bi.get("soldout", 0), item.get("searchIdx", 0),
|
||||
group.get("scope"), title, group.get("scopeCount") or 0, group.get("currentCount") or 0,
|
||||
),
|
||||
)
|
||||
if title in ("书单", "书单合集"):
|
||||
lists.append({**entry, "name": entry["title"], "source": title, "ids": []})
|
||||
else:
|
||||
|
||||
Reference in new issue
Block a user