Files
yunke/docs/superpowers/specs/2026-08-10-yunke-fix-group-scraper.md
T

53 lines
3.1 KiB
Markdown
Raw 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.
# 修复群抓取:friend_list/es + friendTypeYunke=2
> 日期:2026-08-10|分支:`feat/yunke-data-mirror`|scraper fix(后端)
> 云客真机核实(2026-08-10 Playwright):群数据 API = `POST /wechatweb/wxFriends/friend_list/es` body `{friendTypeYunke:"2", wechatId, ymdStart, ymdEnd, pageNum, pageSize, salesname}`——与好友共用端点,仅 friendTypeYunke 不同(1=好友,2=群)。
## 根因
`scrape_wechat_groups` 用 `POST /wechatweb/chatroom/getChatroomList` + body `{pageNum,pageSize}`——**端点错 + 缺 friendTypeYunke + 缺 wechatId**。云客返回 0(smoke.db chat_group 0 行)。
## 修复(spec + plan)
### 改 `app/scraper/wechat.py`
1. **`scrape_wechat_groups`**:改用 `FRIEND_LIST_PATH`(`/wechatweb/wxFriends/friend_list/es`)+ `_parse_friend_total` + `_parse_friend_rows`(复用好友的分页/解析,同端点同信封)+ 新 body builder `_build_group_body`(加 `friendTypeYunke:"2"`)。
2. **`_build_group_body(page_num, page_size)`**:返回 `{pageNum, pageSize, friendTypeYunke: "2"}`(最小 body;与好友 body builder 同模式 + friendTypeYunke;若测试返回 0 再加 ymdStart/ymdEnd/salesname)。
3. **`_normalize_chat_group`**:映射 friend_list/es 字段(替代 getChatroomList 字段):
| ChatGroup 字段 | friend_list/es 来源 |
|---|---|
| room_id | `friendWxId` (e.g. `51983915836@chatroom`) |
| room_name | `friendWxNickname` |
| owner_account_id | `wxId` (staff account that has this group) |
| owner_account_nickname | `ownerName` |
| member_count | `friendNum` |
| head_image_url | `friendHeadImageUrl` |
| message_count | `messageCount` |
| own_message_count | `sendNum` |
| last_chat_time | `lastChatTime` (ms-epoch) |
| owner_user_id | `userId` |
| owner_user_phone | `phone` or `wechatPhone` |
| version | `version` |
| member_ids / member_ids_list | None / [](friend_list/es 不含 memberIds;GroupMember 暂不创建) |
| raw_json | 整条 record |
4. **删除旧 getChatroomList 代码**:`CHATROOM_LIST_PATH`、`_parse_chatroom_total`、`_parse_chatroom_rows`、`_build_chatroom_body`。
5. `sync_wechat_groups`(orchestrator)不改(仍调 `scrape_wechat_groups`;签名不变)。
### 测试
```bash
cd yunke-server && DB_URL="sqlite+aiosqlite:///./smoke.db" .venv/Scripts/python.exe -m app.sync.cli sync --entity groups
```
Expected: smoke.db `chat_group` > 0。若 0(body 不全),给 `_build_group_body` 加 `ymdStart:"0000-00-00"`/`ymdEnd:""`/`salesname:""`/按员工 `wechatId` 遍历。
### 验收
- `pytest -q` 全绿(不破坏现有测试;group 相关测试如 `test_scraper_wechat` 或 `test_sync` 需更新 mock 响应——若有)。
- smoke.db `chat_group` > 0(实跑后)。
- `GET /api/groups` 返回群数据(GroupList 有数据)。
### 风险
- **friend_list/es 无 wechatId 可能返回 0**(云客页面带 wechatId)。测试确认;若 0,需按员工 wxId 遍历(类似 sync_wechat_accounts → per-account friend_list/es)。
- **GroupMember**:friend_list/es 不含 memberIds → GroupMember 表暂不填(群列表可用;成员详情后续)。
- **测试 mock 更新**:现有 group 测试若 mock getChatroomList 响应,需改 mock 为 friend_list/es 响应。