239868531f
Co-Authored-By: Claude <noreply@anthropic.com>
53 lines
3.1 KiB
Markdown
53 lines
3.1 KiB
Markdown
# 修复群抓取: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 响应。
|