Appearance
聊天消息采集技术方案
1. 目标
面向第三方服务商聊天存档页面,建设一套可落地的聊天消息采集能力,用于完成以下目标:
- 采集员工列表、会话列表、聊天消息索引
- 解密并还原文本、表情、图片等真实消息内容
- 支持大消息量场景下的全量补采与日常增量同步
- 支持登录失效后的人工扫码恢复与断点续跑
- 将采集结果沉淀为结构化数据,供后续分析、客服质检、运营回访等场景使用
本方案聚焦技术设计与实现路径,不包含当前阶段的正式编码交付。
2. 现状判断
2.1 页面性质
当前聊天页面属于第三方服务商页面,不是我方自有页面源码,不能通过直接修改前端代码解决采集问题。
页面本身更像一个承载壳,真实消息数据并不完全存在于首屏 HTML,而是依赖以下两层接口链路:
- 第三方服务商接口返回消息索引
- 企业微信开放接口返回解密后的真实消息内容
2.2 已确认接口
2.2.1 消息索引接口
域名:
https://weibanzhushou.com
接口:
/api/chat/staff_session/msg
示例参数:
limit=40session_ext_id=wmt_7EDAAABnmm-ZJnpwSB4D805vR1iwstaff_ext_id=MiaoDaYemsg_source=oa
已确认可返回字段:
idext_idmsg_typedirectionmsgtimefrom_idfrom_nameto_idsession_idsession_typestaff_ext_idsecret_key
该接口的特点是:
- 返回的是消息索引和元信息
text_content、content可能为空- 真正明文内容不能完全依赖本接口
2.2.2 消息解密接口
域名:
https://open.work.weixin.qq.com
接口:
/chatdata/getchatdata
请求体结构:
itemssidreqid
其中每条 item 至少包含:
msgidencrypt_info.secret_key
已确认可返回字段:
msgidmsgtypetext.contentemotion.url
该接口的特点是:
- 支持批量解密
- 需要有效登录态
sid是关键鉴权参数reqid更像请求跟踪 ID,可由客户端生成
2.3 当前关键结论
基于现有抓包结果,可以得出以下结论:
- 聊天消息采集应以接口采集为主,不建议以 DOM 抓取为主
- 消息索引与消息明文必须拆成两段式采集
- 已打开过的聊天页面可能不会再次触发解密请求,因此不能依赖页面行为被动抓取
getchatdata - 大消息量场景下,若每次全量重爬,将产生明显延迟和限流风险
- 登录态失效后需要人工扫码恢复,因此整体系统应设计为“半自动恢复”模式
3. 总体方案
3.1 方案原则
- 优先采接口,不依赖复杂页面结构
- 索引先落库,明文异步补齐
- 支持断点续跑,不做重复全量扫描
- 登录失效后自动检测,人工扫码恢复
- 所有采集过程尽量可观测、可重试、可恢复
3.2 总体架构
建议整体拆成 5 个模块:
- 登录态管理模块
- 员工与会话枚举模块
- 消息索引采集模块
- 消息解密模块
- 数据存储与调度模块
数据链路如下:
- 浏览器登录第三方后台并保持登录态
- 采集员工列表
- 采集员工下的客户、同事、群聊会话列表
- 对每个会话调用
msg接口采集消息索引 - 将
ext_id + secret_key批量送入getchatdata - 合并消息索引与明文解密结果
- 落库并更新同步游标
4. 数据采集流程设计
4.1 员工列表采集
员工列表来源可分为两类:
- 页面列表接口
- 当前页面 DOM
建议优先级如下:
- 优先定位员工列表接口
- 若短期内无法稳定定位,则先解析左侧 DOM 作为过渡方案
建议采集字段:
staff_ext_idstaff_namestaff_aliasavatarstatuscorp_idis_activeraw_json
4.2 会话列表采集
会话列表指每个员工下的:
- 客户
- 同事
- 群聊
当前已确认会话列表接口:
/api/chat/session/staff/list
示例参数:
staff_ext_id=DaBaioffset=0limit=50session_type=roomsession_type=other_staffsession_type=ext_user
对于同事会话,当前已确认还会附带参数:
use_union_mode=1
当前已确认该接口返回:
session_listtotal_count
建议将该接口定义为员工维度会话枚举主接口,不同会话类型通过 session_type 区分。
当前已确认的会话类型至少包括:
room:群聊会话other_staff:同事会话ext_user:外部客户会话
建议优先通过接口拿取以下字段:
session_ext_idsession_namesession_typelast_msglast_msg_timestaff_ext_idavatarremark_nameremarktypegroup_typechat_statuslast_msg_thumbroom_user_listagree_msgauditagree_status_textraw_json
该接口建议采用分页枚举:
- 从
offset=0开始 - 固定
limit - 每次处理
session_list offset += limit- 直到
offset >= total_count
字段映射建议如下:
ext_id映射为session_ext_idname映射为session_namesession_type直接落库group_type区分staff_group与external_groupchat_status作为会话活跃状态last_msg_thumb作为最近一条消息预览last_msg_time作为最近活跃时间room_user_list保留原始 JSON 字符串,并按需解析为成员 ID 列表
其中 room_user_list 建议重点保留,原因如下:
- 可用于还原群成员范围
- 可区分内部员工与外部客户
- 外部客户成员通常表现为
wmt_* - 内部员工成员通常表现为员工
staff_ext_id
针对 session_type=other_staff,当前已确认以下特征:
session_ext_id可直接使用同事的ext_idroom_user_list = nullstaff_ext_id为当前员工标识agree_msgaudit可能为true或null- 列表层
session_type = other_staff - 消息层
session_type可能表现为staff
因此实现层建议:
- 保留列表层原始
session_type - 消息层允许出现
staff - 不强行要求列表层与消息层类型命名完全一致
- 增加一层内部标准化类型映射,例如统一映射为
internal_staff
如其他类型会话接口短期未定位到,可先通过中间栏 DOM 过渡采集,但最终仍建议回归接口方式。
4.3 消息索引采集
对每个会话调用:
/api/chat/staff_session/msg
已确认该接口支持分页参数:
max_id
当前可将该接口定义为“按消息主键倒序翻页”的历史索引接口,推荐规则如下:
- 首次请求不带
max_id - 取当前页最后一条消息的
id - 下一页请求带
max_id=最后一条.id - 持续翻页直到返回空列表或返回条数小于
limit
建议采集并落库字段:
msg_row_idmsg_ext_idsession_ext_idroom_ext_idstaff_ext_idmessage_typedirectionmsg_typemsgtimefrom_idfrom_nameto_idsecret_keyraw_index_json
此阶段目标不是拿完整内容,而是快速把消息索引稳定落地。
4.4 消息解密采集
对消息索引中的未解密消息,按批量方式调用:
/chatdata/getchatdata
请求体核心字段:
items[].msgid = ext_iditems[].encrypt_info.secret_key = secret_keysidreqid
建议将解密结果落到单独字段:
decoded_msgtypetext_contentemotion_urlimage_urlfile_urlvoice_resultmixed_items_jsonrevoke_item_jsonraw_decoded_json
4.5 索引与解密合并
最终对外使用的消息记录建议为一条统一消息表记录,合并以下内容:
- 索引层元数据
- 解密层真实消息体
- 同步状态
- 失败重试信息
5. 登录态管理设计
5.1 登录态组成
当前方案至少涉及两套登录态:
- 第三方服务商站点登录态
- 企业微信开放消息页登录态
其中关键参数包括:
- 第三方站点
session_id - 第三方站点相关 Cookie
- 企业微信开放页会话凭证
- 请求头字段:
open-msg-user-sid - 请求体字段:
sid
- 请求头字段:
- 企业微信
wwopen.open.sid
5.2 登录失效处理
登录失效是本方案中的高频问题,必须作为系统级能力设计。
建议定义以下状态:
RUNNINGSESSION_EXPIREDWAIT_RELOGINRESUME
处理流程:
- 采集任务调用接口
- 若判定登录失效,则立即停止采集
- 发送告警通知人工扫码
- 人工恢复登录后,系统自动从断点继续
6. 大消息量与性能设计
6.1 性能瓶颈
消息量大时,主要瓶颈来自以下几类:
- 员工枚举耗时
- 会话枚举耗时
- 消息索引分页耗时
- 消息解密二次请求耗时
- 限流与失败重试
6.2 正确的性能策略
建议拆成两个独立队列:
- 索引采集队列
- 明文解密队列
索引先入库,明文异步补齐,避免全流程串行阻塞。
6.3 同步模式设计
建议支持两类同步模式:
6.3.1 全量历史补采
适用于首次接入:
- 允许耗时较长
- 支持断点续跑
- 分员工、分会话逐步完成
6.3.2 日常增量同步
适用于日常运行:
- 只抓新消息
- 优先最近 1 天、3 天、7 天
- 延迟目标设为分钟级到小时级
7. 数据库设计建议
7.1 建议核心表
chat_staffchat_sessionchat_message_indexchat_message_contentchat_sync_cursor
7.2 设计原则
- 索引表和明文表分离
- 会话和消息保留原始字段,方便后续排障
- 单独维护同步游标,支持断点续跑
- 对高敏感字段保留最小必要集
8. 调度与运行设计
8.1 运行形态建议
建议采用“常驻浏览器 + 定时采集 Worker”的方式:
- 浏览器进程负责保留登录态
- 采集 Worker 负责调用接口和落库
8.2 推荐运行环境
- 固定一台 Windows 机器
- 固定浏览器 Profile
- 固定网络环境
- 定时任务驱动增量同步
8.3 调度策略
建议调度拆为:
- 每日或每小时同步员工与会话
- 每 5 到 15 分钟执行消息增量同步
- 凌晨低峰期执行历史补采任务
- 登录失效时暂停任务并告警
9. 风险与边界
9.1 已知风险
- 第三方页面结构和接口可能调整
- 登录态会失效,无法完全无人值守
- 企业微信开放接口可能限流
- 历史分页机制尚需继续确认
- 某些消息类型可能存在额外解析复杂度
9.2 当前边界
本方案适合:
- 半自动采集
- 可接受人工扫码恢复
- 以增量同步为主要目标
本方案不承诺:
- 永久稳定免扫码
- 零延迟全量同步
- 在第三方接口完全变更后无需维护
10. 最终建议
综合当前信息,推荐的最终路线如下:
- 以接口采集替代页面爬取
- 采用“消息索引 + 明文解密”双阶段方案
- 用固定浏览器登录态解决
sid获取与扫码恢复问题 - 采用“首次全量、后续增量”的同步策略
- 将系统目标设为“低频人工介入 + 自动断点恢复”