- NavClick 加 anon_id 字段(已为历史表自动迁移) - 后端静默下发 wk_anon cookie(uuid4,1 年,HttpOnly) - 点击埋点写入 anon_id;新增 GET /site/api/my-top 与 POST /site/api/my-clear - 首页服务端渲染「我常访问」区(时间衰减加权分),与「热门网址」共显 - 前端 localStorage 累计 + 与服务端榜取 max 合并;冷启动阈值 2 个网址 - 一键清除:清 localStorage + 服务端删该匿名 ID 的全部记录 - 移动端抽屉、顶部导航同步加「我常访问」入口 - 底部隐私说明更新
64 lines
2.7 KiB
Python
64 lines
2.7 KiB
Python
"""验证「我常访问」:服务端匿名榜 + localStorage 合并 + 清除按钮。
|
||
|
||
用法:先启动 Flask(python app.py),再 PYTHONPATH=. python scripts/verify_mine_section.py
|
||
"""
|
||
from playwright.sync_api import sync_playwright
|
||
|
||
BASE = 'http://127.0.0.1:5000'
|
||
LS_KEY = 'wk_mine_clicks'
|
||
|
||
with sync_playwright() as p:
|
||
browser = p.chromium.launch()
|
||
ctx = browser.new_context(viewport={'width': 1280, 'height': 900})
|
||
page = ctx.new_page()
|
||
|
||
# ---- 1) 全新访客:没有点击记录,不该出现个人区 ----
|
||
page.goto(BASE + '/site/', wait_until='networkidle')
|
||
print('1) 新访客 #cat-mine 存在:', page.locator('#cat-mine').count())
|
||
anon = [c for c in ctx.cookies() if c['name'] == 'wk_anon']
|
||
print(' 匿名 cookie:', (anon[0]['value'][:8] + '...') if anon else '无')
|
||
|
||
# 取页面上真实存在的几个 nav id
|
||
ids = page.eval_on_selector_all(
|
||
'.section:not(#cat-mine) .card[data-nav-id]',
|
||
'els => els.slice(0, 5).map(e => e.getAttribute("data-nav-id"))'
|
||
)
|
||
print(' 可用 nav id:', ids)
|
||
|
||
# ---- 2) 只写 localStorage(模拟 cookie 被禁 / 服务端还没同步)----
|
||
page.evaluate(
|
||
"""([k, a, b]) => localStorage.setItem(k, JSON.stringify({[a]: 4, [b]: 2}))""",
|
||
[LS_KEY, ids[0], ids[1]]
|
||
)
|
||
page.reload(wait_until='networkidle')
|
||
n = page.locator('#cat-mine .card').count()
|
||
print('2) localStorage 驱动后 #cat-mine 卡片数:', n)
|
||
print(' 顶部导航入口:', page.locator('.cat-nav-mine').count(),
|
||
'| 抽屉入口:', page.locator('.cat-drawer-mine').count())
|
||
if n:
|
||
print(' 首卡文案:', page.locator('#cat-mine .card').first.inner_text().replace('\n', ' | ')[:90])
|
||
|
||
# ---- 3) 只点 1 个网址:冷启动阈值,不该展示 ----
|
||
page.evaluate("k => localStorage.setItem(k, JSON.stringify({}))", LS_KEY)
|
||
page.reload(wait_until='networkidle')
|
||
print('3) 清空 localStorage 后 #cat-mine 可见:',
|
||
page.locator('#cat-mine').count() and page.locator('#cat-mine').is_visible())
|
||
|
||
# ---- 4) 清除按钮 ----
|
||
page.evaluate(
|
||
"""([k, a, b]) => localStorage.setItem(k, JSON.stringify({[a]: 3, [b]: 1}))""",
|
||
[LS_KEY, ids[0], ids[1]]
|
||
)
|
||
page.reload(wait_until='networkidle')
|
||
print('4) 清除前 #cat-mine 数:', page.locator('#cat-mine').count())
|
||
clears = []
|
||
page.on('request', lambda r: clears.append(r.url) if '/site/api/my-clear' in r.url else None)
|
||
page.locator('#clear-mine').first.click()
|
||
page.wait_for_timeout(600)
|
||
print(' 清除后 #cat-mine 数:', page.locator('#cat-mine').count(),
|
||
'| localStorage:', page.evaluate("k => localStorage.getItem(k)", LS_KEY),
|
||
'| 请求:', clears)
|
||
|
||
browser.close()
|
||
print('DONE')
|