Files
kefu/wechat_rpa/tmp/probe_session_fp_drift.py
2026-07-31 11:48:16 +08:00

106 lines
4.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""只读诊断:同一个会话的档案指纹在多次采样之间是否稳定。
档案键 = 头像感知哈希(8B) + 名称哈希(32B),而 store.has_record() 是精确匹配。
只要指纹漂移,同一个联系人就会被当成“首次遇到”,从而丢弃复制到的聊天文字、
只靠截图回复。这里量化漂移幅度。
"""
import os
import sys
import time
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import numpy as np
import wechat_bot as bot_module
def hamming(a: bytes, b: bytes) -> int:
return (int.from_bytes(a, "big") ^ int.from_bytes(b, "big")).bit_count()
def main():
rounds = int(sys.argv[1]) if len(sys.argv) > 1 else 8
bot = bot_module.WeChatBot()
bot.safe_window_mode = True
bot.auto_activate_window = True
if not bot.connect(activate=False, wait_if_missing=False):
print("[-] 未挂载到企业微信窗口")
return
if not bot._ensure_visible():
print("[-] 企业微信未能切到前台")
return
print(
"容差: 头像 %d 位以内算同一人;名称使用模糊匹配"
% bot_module.WeChatBot._FP_HAMMING_TOL
)
samples = []
for index in range(rounds):
img = bot.capture_session_list()
selected_y = bot.detect_selected_row(img)
if selected_y < 0:
print(" 第 %d 次采样:未检测到选中行" % (index + 1))
time.sleep(0.4)
continue
avatar = bot._raw_session_fingerprint(img, selected_y, row_center=True)
name = bot._session_name_fingerprint(img, selected_y, row_center=True)
full = bot._session_fingerprint(img, selected_y, row_center=True)
samples.append((selected_y, avatar, name, full))
print(
" 第 %d 次采样:选中行 y=%-4d 头像=%s 名称=%s 完整键=%s"
% (index + 1, selected_y, avatar.hex(), name.hex()[:16] + "…", full.hex()[:16] + "…")
)
time.sleep(0.4)
if len(samples) < 2:
print("样本不足,无法比较。")
return
print("\n[行中心] y 取值: %s" % sorted({s[0] for s in samples}))
print("[头像哈希] 去重后 %d 种" % len({s[1] for s in samples}))
print("[名称哈希] 去重后 %d 种" % len({s[2] for s in samples}))
print("[完整档案键] 去重后 %d 种 <- 大于 1 就意味着同一会话会被反复当成新会话"
% len({s[3] for s in samples}))
base_y, base_avatar, base_name, _ = samples[0]
worst = 0
for y, avatar, name, _full in samples[1:]:
distance = hamming(base_avatar, avatar)
worst = max(worst, distance)
if distance:
print(
" 头像相对第 1 次漂移 %2d 位(y %d%d%s"
% (distance, base_y, y, " 超出容差!" if distance > bot_module.WeChatBot._FP_HAMMING_TOL else "")
)
print("[结论] 头像最大漂移 %d 位,容差 %d 位" % (worst, bot_module.WeChatBot._FP_HAMMING_TOL))
# 行中心偏移对指纹的影响:模拟 ±1~6 像素的行中心估算误差。
img = bot.capture_session_list()
selected_y = bot.detect_selected_row(img)
if selected_y >= 0:
anchor = bot._raw_session_fingerprint(img, selected_y, row_center=True)
print("\n[敏感度] 同一张图,仅把行中心挪动若干像素:")
for offset in (1, 2, 3, 4, 6, 8):
for sign in (-1, 1):
shifted = bot._raw_session_fingerprint(
img,
selected_y + sign * offset,
row_center=True,
)
print(
" 行中心 %+d px -> 头像漂移 %2d%s"
% (
sign * offset,
hamming(anchor, shifted),
" 超出容差!"
if hamming(anchor, shifted) > bot_module.WeChatBot._FP_HAMMING_TOL
else "",
)
)
if __name__ == "__main__":
main()