推荐系统
Change-Id: I49b9205568f1ccf88b32b08511aff8b0bea8d1bd
diff --git a/rhj/backend/app/utils/graph_build.py b/rhj/backend/app/utils/graph_build.py
new file mode 100644
index 0000000..a453e4e
--- /dev/null
+++ b/rhj/backend/app/utils/graph_build.py
@@ -0,0 +1,115 @@
+import pymysql
+import datetime
+from collections import defaultdict
+
+SqlURL = "10.126.59.25"
+SqlPort = 3306
+Database = "redbook" # 修改为redbook数据库
+SqlUsername = "root"
+SqlPassword = "123456"
+
+
+def fetch_user_post_data():
+ """
+ 从redbook数据库的behaviors表获取用户-帖子交互数据,只包含已发布的帖子
+ """
+ conn = pymysql.connect(
+ host=SqlURL,
+ port=SqlPort,
+ user=SqlUsername,
+ password=SqlPassword,
+ database=Database,
+ charset="utf8mb4"
+ )
+ cursor = conn.cursor()
+ # 获取用户行为数据,只包含已发布帖子的行为数据
+ cursor.execute("""
+ SELECT b.user_id, b.post_id, b.type, b.value, b.created_at
+ FROM behaviors b
+ INNER JOIN posts p ON b.post_id = p.id
+ WHERE b.type IN ('like', 'favorite', 'comment', 'view', 'share')
+ AND p.status = 'published'
+ ORDER BY b.created_at
+ """)
+ behavior_rows = cursor.fetchall()
+ cursor.close()
+ conn.close()
+ return behavior_rows
+
+
+def process_records(behavior_rows):
+ """
+ 处理用户行为记录,为不同类型的行为分配权重
+ """
+ records = []
+ user_set = set()
+ post_set = set()
+
+ # 为不同行为类型分配权重
+ behavior_weights = {
+ 'view': 1,
+ 'like': 2,
+ 'comment': 3,
+ 'share': 4,
+ 'favorite': 5
+ }
+
+ for row in behavior_rows:
+ user_id, post_id, behavior_type, value, created_at = row
+ user_set.add(user_id)
+ post_set.add(post_id)
+
+ if isinstance(created_at, datetime.datetime):
+ ts = int(created_at.timestamp())
+ else:
+ ts = 0
+
+ # 使用行为权重
+ weight = behavior_weights.get(behavior_type, 1) * (value or 1)
+ records.append((user_id, post_id, ts, weight))
+
+ return records, user_set, post_set
+
+
+def build_id_maps(user_set, post_set):
+ """
+ 构建用户和帖子的ID映射
+ """
+ user2idx = {uid: idx for idx, uid in enumerate(sorted(user_set))}
+ post2idx = {pid: idx for idx, pid in enumerate(sorted(post_set))}
+ return user2idx, post2idx
+
+
+def group_and_write(records, user2idx, post2idx, output_path="./app/user_post_graph.txt"):
+ """
+ 将记录按用户分组并写入文件,支持行为权重
+ """
+ user_items = defaultdict(list)
+ user_times = defaultdict(list)
+ user_weights = defaultdict(list)
+
+ for user_id, post_id, ts, weight in records:
+ uid = user2idx[user_id]
+ pid = post2idx[post_id]
+ user_items[uid].append(pid)
+ user_times[uid].append(ts)
+ user_weights[uid].append(weight)
+
+ with open(output_path, "w", encoding="utf-8") as f:
+ for uid in sorted(user_items.keys()):
+ items = " ".join(str(item) for item in user_items[uid])
+ times = " ".join(str(t) for t in user_times[uid])
+ weights = " ".join(str(w) for w in user_weights[uid])
+ f.write(f"{uid}\t{items}\t{times}\t{weights}\n")
+
+
+def build_user_post_graph(return_mapping=False):
+ """
+ 构建用户-帖子交互图
+ """
+ behavior_rows = fetch_user_post_data()
+ records, user_set, post_set = process_records(behavior_rows)
+ user2idx, post2idx = build_id_maps(user_set, post_set)
+ group_and_write(records, user2idx, post2idx)
+ if return_mapping:
+ return user2idx, post2idx
\ No newline at end of file