Files
alibaba/docs/PROJECT.md
T
2026-08-27 16:12:37 +08:00

12 KiB
Raw Blame History

阿里国际站询盘数据采集与管理系统 · 项目介绍

基于 2026-08-27 代码现状整理(扩展 d:\alibb + 服务端 d:\alibb-server)。 部署细节见 DEPLOY-ALIBB.md,后端设计见 superpowers/specs/2026-07-13-alibaba-inquiry-backend-design.md。

1. 项目概述

本项目是一套阿里国际站(alibaba.com)询盘数据的采集与管理系统,由三个部分组成:

组成部分 位置 技术 角色
采集端 Chrome 扩展 d:\alibb(本仓库) Chrome MV3、原生 JS 抓取询盘列表、客户资料、行为数据、聊天记录
服务端 后端 API d:\alibb-server\backend Node.js + Express + TypeScript + Prisma + MySQL 接收推送、幂等入库、提供查询/统计/导出 API
服务端 管理后台 d:\alibb-server\frontend Vue3 + Element Plus + Pinia + ECharts 询盘列表/详情/聊天查看/统计报表

核心链路:

浏览器(登录阿里主账号)
  Chrome 扩展 content.js
   ├─ 列表抓取(DOM 翻页)→ 详情抓取(DOM)→ 聊天抓取(阿里内部 API 直拉)
   ├─ 双写 A(本地):chrome.storage 汇聚 + customerId 去重 → CSV 导出
   └─ 双写 B(推送):IndexedDB 队列 → alarm 每分钟消费 → POST /api/ingest(Bearer Token)
        ↓ 失败指数退避(≤8 次),成功出队
服务器(阿里云 ECS,1Panel + OpenResty + MySQL 8.4,:23010)
  后端 zod 校验 → 幂等入库(同客户合并 / 消息级去重 / 早返回)
        ↓
管理员浏览器 → Vue3 后台(JWT 登录):列表筛选 / 聊天详情 / 统计 / CSV 导出

使用模式:主管理员账号一人操作扩展手动触发抓取(非实时同步),后台数据 = 最近一次抓取的快照;询盘记录的 manager 字段天然区分业务员,无需多人登录。


2. 采集端:Chrome MV3 扩展(本仓库)

2.1 文件结构

文件 行数/大小 职责
manifest.json — MV3 清单:权限 storage/activeTab/alarms/unlimitedStorage/scripting;host 覆盖 message/alicrm/onetalk.alibaba.com;optional_host_permissions 运行时授权任意后端地址
content.js ~1300 行 核心:注入 message.alibaba.com 的抓取状态机
background.js 145 行 Service Worker:推送队列调度 + 本地数据汇聚(双写)
push/queue.js — IndexedDB 持久化队列(库 inquiry_push)
push/worker.js — 队列消费:POST /api/ingest,指数退避,8 次后标 failed
push/payload.js — 页面数据 → 后端 zod schema 的字段适配层
push/config.js — 推送配置(chrome.storage.local)
popup.html / popup.js — 操作界面:抓取控制 + 后端推送配置
tests/ 5 个文件 vitest 单测(config/queue/payload/sync/worker,fake-indexeddb)
scripts/ — e2e-push.mjs(推送端到端)、verify-chat-range.mjs、verify-risk-detect.mjs
使用手册.html — 面向操作者的图文五步指南

2.2 抓取状态机与断点续抓

content.js 的核心是跨页面持久化的状态机:state.phase ∈ idle | list | detail | paused | done,存储于 chrome.storage.local(键 alibaba_scraper_state)。每跳转一个详情页 content script 就被销毁重建,靠恢复 queueIndex 继续队列 —— 整轮抓取可跨导航、可暂停恢复、可扩展重载续跑。

抓取编排由 processCurrentDetailPage() 完成:等待渲染 → 聊天抓取(API 优先)→ 详情提取 → 双写(本地 storeDetail + 推送 enqueue)→ 跳下一条。

2.3 数据抓取能力

  • 列表页:DOM 解析 a.inquiry-item(询价单号/时间/买家/国家/消息预览/负责人/状态等 13 字段),100 条/页,自动翻页;
  • 详情页:客户资料(邮箱/电话/公司/注册时间等)、买家标签(8 词表)、买家特征(12 词表)、近 90 天行为数据(产品浏览/有效询盘/RFQ/登录天数/垃圾询盘/黑名单数)、店内行为与最近询盘产品;
  • 聊天记录(最复杂模块):
    • API 直拉主路径:querySummary.htm 拿会话加密参数 → getOpMessages.htm 游标循环翻页(复用页面 cookie 凭据),单询盘实测 8000+ 条;实测全量 4576 询盘 + 68058 条消息零风控;
    • DOM 滚动回退:API 失败时模拟 wheel 事件滚动 .common-load-more 懒加载;
    • 同客户去重:同买家多询盘共享同一会话,只抓首个(seenChatCustomer);
    • 消息归一化(apiMsgToChat):方向(incoming/outgoing/system)、富媒体(img:/file:/video: 前缀 + clouddisk 直链构造)、翻译(嵌套 JSON 双重 parse)。

2.4 反风控设计(贯穿全文件)

机制 说明
随机时延 翻页 1.2–3s、聊天每轮 2–5s、每 15 轮插入 30–90s"模拟走神"
作息时段 默认 8–12 / 14–18 点工作,会话级 ±30 分钟抖动,非工作时段自动挂起
风控检测 RISK_KEYWORDS(验证码/captcha/blocked 等)命中 → 暂停 + popup 红色横幅报警;只浅扫 API 响应顶层字段,不扫消息正文防误判
跳过策略 注销/管控账号(SKIP_KEYWORDS)直接跳过不暂停
增量水位 按 inquiryId 记录已抓最新消息(lastTopMsg_*),重抓只拉增量,只前进不倒退
时间范围 近 1/2/3 月或自定义起止;until 跳游标直接从截止时间往回翻,大幅减少请求量 —— 同时是风控减压手段

2.5 推送链路(可靠性)

content.js 抓完一条 → sendMessage 'enqueue' → SW 写 IndexedDB(不丢)
  → 立即 + alarm 'push-tick'(每 1 分钟)触发 processQueue()
  → 每批 3 条,POST {serverUrl}/api/ingest(Bearer Token)
  → 成功标 sent;失败指数退避(2^n 秒,封顶 1h),8 次后标 failed(popup 红字提示)

关键设计:worker 每次自己 loadConfig()(无状态),因为 MV3 SW 休眠重启会清空模块级变量 —— 缓存配置会导致永不推送。

2.6 popup 界面

抓取模式(仅列表/列表+详情)、条数(全部/前10/前50)、customerId 去重开关、聊天上限、聊天时间范围(全部/近1-3月/自定义日期)、后端推送设置(服务器 URL + Token + 授权域名 + 启用开关,默认指向生产 http://219.157.255.213:23010)、实时推送状态条(已推/待推/失败,2s 刷新)、开始/暂停/恢复/导出 CSV/清空数据。


3. 服务端后端(d:\alibb-server\backend)

3.1 技术栈与结构

Express 4 + TypeScript + Prisma 5 + MySQL 8,zod 校验,Docker 两阶段构建(node:20-slim),容器启动自动 prisma migrate deploy。目录:src/{routes,services,middleware,utils,config,lib} + prisma/ + tests/(vitest + testcontainers 真库集成测试)。

3.2 API 清单

方法 + 路径 鉴权 功能
GET /api/health 无 探活(DB 连通性)
POST /api/ingest/ Ingest Token + 60次/min 限流 扩展推送入口,幂等入库
POST /api/auth/login / refresh 无 / JWT 管理员登录(bcrypt)、续签
GET /api/inquiries JWT 列表:分页 + 国家/业务员/状态/时间筛选 + 关键词搜索 + 排序
GET /api/inquiries/:id JWT 详情 + 客户 + 行为 + 消息数
GET /api/inquiries/:id/messages JWT 聊天游标分页(复合键 (sendTime, messageId),微信式向上翻页)
GET /api/inquiries/:id/messages/export JWT 单询盘聊天 CSV 流式导出(预留)
GET /api/stats/overview JWT 总数 / 国家 Top10 / 业务员分布 / 近 12 月趋势
GET /api/export JWT 询盘列表 CSV 导出(21 列中文表头,与列表筛选一致)

3.3 ingest 幂等核心(亮点)

  1. 同客户合并:同一 customerId 只保留一条"代表询盘"(最早创建),后续询盘追加进 allInquiries JSON 数组,消息统一归入代表 —— 不产生冗余行;
  2. 消息级幂等:按 message_id 唯一约束 createMany skipDuplicates,500 条/批,单批失败只计数不回滚(has_failed_batches 标记,下次推送强制重插);
  3. 早返回优化:"消息数 + 最大 sendTime + 无失败批次" 三项指纹未变 → 跳过批量插入直接返回,避免重复重写几千条消息;
  4. customer upsert 用 skipNulls,本次没抓到的字段不覆盖已落库值。

3.4 数据模型(4 张表)

  • customers:customer_id 唯一;资料 + 行为七字段(可空,区分"无数据"与"为 0")+ 店内行为 JSON 列;
  • inquiries:inquiry_id 唯一;all_inquiries(同客户合并)、messages_count/last_send_time(幂等指纹)、has_failed_batches;
  • chat_messages:message_id 唯一(幂等键);content MEDIUMTEXT;复合索引 (inquiry_id, send_time, message_id) 恰好覆盖游标分页;
  • users:管理员(bcrypt,空表时按环境变量播种)。

3.5 鉴权

两套并行:扩展 → 静态 INGEST_TOKEN(timingSafeEqual 常量时间比较防时序攻击);后台 → JWT(HS256,7 天,登录签发)。


4. 管理后台前端(d:\alibb-server\frontend)

4.1 页面

路由 页面 功能要点
/login 登录 JWT + open-redirect 防护
/inquiries 询盘列表 筛选栏(国家/业务员/状态/时间范围/搜索/排序)、表格分页、CSV 导出复用当前筛选;列表状态存 sessionStorage,进详情返回后恢复
/inquiries/:id 询盘详情 客户信息卡 + 行为数据卡(复刻阿里详情页行为区)+ 同会话多询盘列表 + 完整聊天
/stats 统计 数字卡(总数/本月新增)+ ECharts:国家 Top10 环形图、业务员柱状图、12 月趋势折线

4.2 聊天组件(核心体验)

  • 虚拟滚动(vue-virtual-scroller):几千条消息流畅渲染,可变高度气泡自动测量;
  • 游标分页:首屏拉最新一页自动滚到底,顶部按钮向上加载历史,prepend 后保持视觉位置不跳动;
  • 微信式气泡:incoming 左 / outgoing 右 / system 居中;消息类型协议(img:/file:/video:/纯链接/纯文本);
  • XSS 防护:文本一律插值不用 v-html;富媒体 URL 走 alibaba 域名白名单,纯 URL 只许 http/https。

4.3 工程细节

axios 封装(401 全局跳登录、错误脱敏不含 token)、Pinia auth store(JWT 存 localStorage,MVP 可接受)、路由守卫、全套 vitest 单测、双 lint(oxlint + eslint)。


5. 部署与运维

生产环境(详见 DEPLOY-ALIBB.md):

  • 阿里云 ECS 219.157.255.213(Ubuntu 26.04),对外端口 23010;
  • 1Panel 面板管理:OpenResty(host 网络,站点 alibaba)→ SPA 静态 + /api/* 反代 → alibb-backend 容器(127.0.0.1:8090)→ 1Panel MySQL 8.4(库 alibaba,utf8mb4,仅本机可达);
  • client_max_body_size 50m 配合大聊天 payload;备份:mysqldump → 本机 D:\alibb-server\backups\(权威)+ 服务器副本;
  • 三份代码位置:扩展 d:\alibb(master)、后端 d:\alibb-server\backend(master)、前端 d:\alibb-server\frontend(main);服务器重装恢复 runbook 见 superpowers/plans/。

6. 已知限制

  • 客户资料折叠面板字段抓不到(阿里校验 event.isTrusted 只认真实鼠标点击),好在多数买家本就是 "-";
  • 公网明文 HTTP(23010),内网/测试可接受,长期公网建议套域名 + HTTPS;
  • 数据时效 = 上次手动抓取快照,需浏览器保持阿里页打开;
  • 同 messageId 内容被上游修订时早返回会跳过更新(MVP 接受,重推主场景是新增消息)。