Files

25 KiB
Raw Permalink Blame History

三笙AI情报局独立版

三笙AI情报局是面向家纺、服装和跨境电商经营者的静态情报站参考实现。本仓库从 AI-News-Radar 主项目中独立出来,供公司 C# 后端研发、前端研发、测试和运维人员理解现有业务,再重构为长期稳定版本。

先明确边界:仓库名称中包含“AI”,但当前版本 没有调用任何 LLM、多模态理解模型或生图模型。没有 Qwen、Gemini、OpenAI 等模型请求,没有提示词模板,也没有“先让文本模型理解用户输入,再调用生图模型”的两阶段链路。现有智能能力来自一手信源抓取、规则解析、结构化计算、去重排序、公共机器翻译和静态 SEO/GEO 生成。

当前基线

当前提交数据以 data/*.json 为准,业务基准日为 2026-08-17:

指标 当前值
严格权威源 59/59
日历原始事件 / 聚合机会 1261 / 640
今日必看 24
展会 79
政策与召回 48
标准事实 4
跨境平台 28
跨境活动 65
趋势与灵感内容 208

这些数字是可回归的仓库快照,不是写死在页面里的宣传数字。每次数据更新后,应以 textile-intelligence.json.summary、source_target/source_success 和 textile-trends.json.total_items 重新核对。

五分钟理解系统

flowchart LR
  A[政府/平台/展会/博物馆等公开来源] --> B[Python 定时抓取]
  B --> C[证据词、状态码、语种和结构校验]
  C --> D[规则解析、规范化、聚合、去重和排序]
  D --> E[命中缓存或调用 Google 公共翻译接口]
  E --> F[生成两份公开 JSON]
  F --> G[生成首页、详情页、栏目页、Sitemap、JSON-LD、llms.txt]
  G --> H[原子替换 dist]
  H --> I[IIS/Nginx/对象存储/CDN 只提供静态文件]

生产访问端不需要 Python、Node、数据库、模型服务或 GitHub Pages。Python 只运行在更新节点;最终仅发布 dist/。

核心功能

功能 用户看到的结果 当前实现
今日必看 混合展示备货、展会、政策、活动和趋势任务 规则评分、截止日期、经营相关度和风险排序
备货日历 节日、国家、备货窗口、产品建议、平台动作 多来源日历规范化后按日期、名称和地区聚合
展会通 展期、城市、主办方、官方报名和译文入口 固定官方源与动态目录合并,优先保留官方报名页
政策预警 关税、召回、标签、知识产权和平台规则 权威来源证据校验,事实与经营建议分区
跨境活动 线上/线下活动、倒计时、报名入口和筛选 官方活动优先,行业媒体只承担发现作用
平台渠道 市场、品类、卖家准入和官方入驻入口 静态核验目录与信源状态组合
趋势雷达 趋势文章、灵感图库、时装趋势和原图查看 RSS/HTML/博物馆公开 API,URL 与标题规则去重
SEO/GEO 可直接索引的中文正文和稳定实体页面 静态 HTML、canonical、JSON-LD、Sitemap、robots、llms.txt

平台渠道页只向用户展示“平台官网”和“官方入驻”两个真实业务入口。类目 URL 仅作为内部研究数据保留,不在前台展示;消费者官网和类目页不提供网页翻译,只有非中文官方入驻页才显示“辅助翻译入驻说明”。

AI、模型与渠道清单

当前没有的模型链路

能力 当前状态 说明
LLM 文本理解 未接入 不调用 Qwen、Gemini、OpenAI 或其他大语言模型
多模态图片理解 未接入 不把用户图片或源站图片发送给视觉模型
文生图/图生图 未接入 灵感图库图片来自公开博物馆或来源站;活动无图时使用 CSS 文字海报
提示词拼接 不存在 没有 system/user prompt、提示词变量或模型输出 JSON
用户内容实时模型审核 不存在 当前站点没有用户投稿、聊天或生图输入

因此,C# 重构时不要创建“模型编排服务”、提示词数据库或生图任务队列来复刻当前功能。以后若产品明确加入模型能力,应作为独立版本设计,不能把未来方案写成当前依赖。

当前唯一的机器翻译请求

构建节点会对部分外文标题和摘要执行一次普通 HTTP 翻译请求。它不是 LLM,也不是生图模型:

GET https://translate.googleapis.com/translate_a/single
client=gtx
sl=auto
tl=zh-CN
dt=t
q={规范化后的原文标题或摘要}

变量只有 q;sl 固定为自动识别,tl 固定为简体中文。返回数组中每个翻译片段的首字段会按顺序拼接为中文。调用前先以完整原文字符串查询 data/textile-zh-cache.json,命中则不请求;未命中才请求,并限制每次任务的新翻译数量:

内容 单次最多新增翻译
趋势标题与摘要 250
日历标题 260
展会标题与摘要 200
政策标题/摘要 72
活动标题 72

请求失败时保留缓存中的上一版中文或官方原文,不会把线上字段清空。该 client=gtx 公共端点没有项目 API Key 和商业 SLA;稳定版若要求服务等级、配额和合规审计,应由公司统一替换为正式采购的翻译服务,但必须保持“缓存优先、失败保留上一版、官方原文可访问”的语义。

网页译文入口

网页翻译按钮只生成跳转 URL,不抓取也不保存整页译文:

Google: https://translate.google.com/translate?sl=auto&tl=zh-CN&u={URL 编码后的官网地址}
Yandex: https://translate.yandex.com/translate?url={URL 编码后的官网地址}&lang={源语种}-zh

处理规则:

  • 简体中文正文、.cn 域名、bizevent.ccpit.org 等已知中文页面不显示译文按钮。
  • 中国大陆 IP 默认使用 Yandex;明确的非中国 IP 默认使用 Google,并以另一渠道为备用。
  • IP 依次通过 Cloudflare trace、country.is、ipwho.is 判断;全部失败后再参考浏览器语种和时区。
  • cpsc.gov、zatca.gov.sa 等已验证不支持 Google 网页代理的域名只提供 Yandex。
  • abai.kgd.gov.kz 已验证两边都不可用,只保留本站中文摘要和官方原文。
  • 官方来源/报名按钮始终优先于译文按钮;报名、付款、验证码和资料提交必须回官方域名。

数据请求与处理流程

1. 输入

系统输入不是用户提示词,而是以下公开数据:

  • 政府、海关、监管机构和标准组织的 HTML、JSON、RSS。
  • 平台、展会和主办方官网的页面与公开接口。
  • Met、V&A 等博物馆的公开藏品信息和图片地址。
  • 已人工登记的信源元数据:ID、栏目、地区、URL、证据词、中文说明和经营动作。

2. 抓取前处理

  • 固定浏览器 User-Agent、语言头、连接/读取超时和有限重试。
  • 规范化 URL、文本空白、日期、地区、平台和节日名称。
  • 对已知证书兼容问题只在指定域名使用兼容适配器,禁止全局关闭 TLS 校验。
  • 动态 API Key 只从目标官网公开前端配置中提取并立即用于同站请求,不在仓库保存密钥。

3. 抓取后校验

  • 同时检查 HTTP 状态、内容类型、最终 URL、正文长度和登记的证据词;HTTP 200 不等于成功。
  • 为响应正文计算内容指纹,记录 verified_at、content_hash 和变更状态。
  • 严格源任一失败时,--strict 更新直接退出,正式 JSON 和 dist/ 不被半成品覆盖。
  • 活动发现源必须回到主办方或平台官方报名页;行业媒体页不能冒充官方来源。

4. 结构化、去重和排序

  • 日历:规范化节日名、日期和地区后聚合;当地名称折叠为辅助信息。
  • 展会:规范化展名、开始日和城市;官方固定源覆盖动态目录的弱字段。
  • 活动:以真实报名 URL、标题、日期和地区去重;中文站不生成翻译入口。
  • 趋势:先按 URL 去重,再按稳定 ID、标题和来源处理;V&A 泛化标题会加入藏品编号,避免多个 Hanging/Pattern 被误认为相同内容。
  • 今日必看:从各栏目混合选取可行动事项,按截止日期、经营相关性、影响和风险排序。

5. 发布

scripts/update_all.py 在 runtime/update-* 临时目录完成抓取、翻译、JSON 校验和站点预构建。只有全部成功后才替换正式数据,并把旧四份 JSON 压缩到 runtime/snapshots/。快照最多 14 份、总计不超过 120 MiB。

scripts/build_site.py 仅把以下运行数据复制到公开目录:

  • dist/data/textile-intelligence.json
  • dist/data/textile-trends.json

翻译缓存、源状态、日志和快照不会进入 dist/。

审核、预处理和后处理边界

当前没有用户生成内容,所以没有实时内容安全审核接口。现有“审核”是数据质量审核,不是模型审核:

  • 信源必须预登记并通过证据词和权威层级验证。
  • 页面语种、日期、URL、地区和栏目在进入正式 JSON 前规范化。
  • 付费墙、失效站点、二次转载和无来源图片按规则排除。
  • 机器翻译、官方事实和本站经营建议分别标注,不能混写成官方结论。
  • 前端不自行补造事实;缺字段时隐藏对应控件,不显示伪数据或占位按钮。

未来若加入搜索框自由文本、用户评论、文件上传或模型生图,才需要在 API 边界增加长度、格式、恶意 URL、版权、隐私和内容安全审核。该能力不属于当前版本。

前端必须保留的职责

即使后端改写为 C#,以下工作仍必须由前端完成:

  • 七个业务入口、趋势子分类、搜索和地区/平台/参与方式筛选。
  • IP 结果返回后选择 Google/Yandex 译文按钮;检测完成前不展示错误渠道。
  • 官方来源和官方报名链接在译文入口左侧,所有外链新窗口打开并隔离 opener。
  • 日历倒计时、活动状态、移动端单列布局和触控尺寸。
  • 灵感图库原图浮层、三笙 Logo 加载动画、关闭/下载/键盘操作。
  • 主题切换、分享、折叠的更新时间与源状态详情。
  • 只消费公开 JSON;不得请求 textile-zh-cache.json 或源状态文件。

事实聚合、内容指纹、去重、业务评分和翻译缓存应留在更新服务或后端,不能散落到 UI 组件里。

目录与入口

public/     独立 HTML、CSS、ES Modules、本地字体、Logo 和平台图标
data/       正式 JSON、源状态与中文翻译缓存
scripts/    抓取、翻译、聚合、去重、SEO 和原子发布
docs/       数据契约、信源、流水线、C# 交接、SEO/GEO 和运维说明
runtime/    计划任务、临时目录和本地快照;不参与公开发布
dist/       可直接部署的静态产物;构建生成,不提交版本库
tests/      Python 数据契约测试与 Node 前端契约测试

主要入口:

文件 职责
scripts/update_all.py 完整更新事务和原子发布入口
scripts/update_textile_intelligence.py 日历、展会、政策、平台、活动、今日必看主聚合
scripts/update_textile_trends.py 趋势文章、图库和时装趋势抓取
scripts/intelligence_sources.py 严格权威源注册表
scripts/intelligence_web_translation.py 页面语种和 Google/Yandex 链接策略
scripts/build_site.py 复制公开资产和数据、调用 SEO 构建、替换 dist/
scripts/build_seo.py 栏目页、详情页、年份页和结构化数据
public/assets/js/render-intelligence-core.js 情报站核心 UI、筛选和翻译按钮

本地运行

Windows 11 可直接双击:

  1. start.bat:缺少 dist/ 时先构建,再自动寻找从 8765 开始的空闲端口。
  2. update.bat:首次创建 .venv,从清华 PyPI 镜像安装依赖,严格更新并构建。
  3. install-schedule.bat:安装每天 09:30 的 Windows 计划任务。

命令行:

python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
.\.venv\Scripts\python.exe scripts\update_all.py
.\.venv\Scripts\python.exe scripts\serve.py

只基于仓库快照构建,不联网更新数据:

$env:SANSHENG_SITE_URL='https://intel.example.com'
.\.venv\Scripts\python.exe scripts\build_site.py --site-url $env:SANSHENG_SITE_URL

C# 稳定版重构建议

最低风险的迁移顺序:

  1. 冻结 docs/DATA-CONTRACT.md 描述的 JSON v2,C# 先读取当前两份公开 JSON。
  2. 用 Worker Service 或独立计划任务承载采集,禁止在 ASP.NET Web 请求中同步抓取 59 个源。
  3. 使用 HttpClient、System.Text.Json 和正式 HTML 解析器逐个迁移稳定源;每迁移一个源,与 Python 对同一 URL 双跑比对。
  4. 将 Source、FetchRun、IntelligenceItem、ItemSource、UserPreference、UserTask 分表保存;自动事实与人工结论分离。
  5. API 稳定后再迁移前端;服务端渲染静态正文,客户端仅增强筛选、收藏、任务和翻译渠道选择。
  6. 最后切换正式域名 canonical,并为旧 URL 建立 301 映射。

C# 实现必须保留以下语义:稳定 ID、UTC generated_at、业务 as_of_date、内容指纹、源证据、严格失败不发布、缓存翻译失败不清空、官方事实/机器翻译/经营分析分区、原子发布和可回滚快照。

不要一次性重写全部抓取器,也不要先引入 LLM。先让 C# 后端稳定消费现有 JSON,再按源逐步替换,最容易定位数据差异和回滚。

复现主站的全自动更新与部署

独立站不依赖 GitHub Actions 或 Pages,但现有命令可以直接接入 GitHub Actions、Gitea Runner、Windows 计划任务和 Linux systemd。研发人员应先按实际网络与服务器条件选择方案,不要在 Web 请求中执行抓取。

条件 推荐方案 更新节点 Web 节点
希望最快复现主站效果 私有 GitHub 仓库 + GitHub Actions + Cloudflare Pages GitHub Hosted Runner Cloudflare Pages
公司有可访问全部源站的 Server Gitea Runner、Windows 计划任务或 Linux systemd 公司 Server 同机 IIS/Nginx,或另一台内网 Web Server
Web Server 无外网,但有其他外网节点 外网更新节点生成 dist/,通过制品库、SFTP、SMB 或对象存储传入 外网更新节点 只接收并发布 dist/
公司任何机器都不能访问部分境外源 合规代理、统一出口、GitHub Hosted Runner 或外部更新 Worker 具备合法网络出口的节点 内网 Web Server

最快复现:私有 GitHub 仓库 + GitHub Actions

该方案最接近个人主站:GitHub Actions 每天抓取、测试、构建并提交新数据;Cloudflare Pages 监听数据提交并重新发布 dist/。GitHub 仓库必须设为私有,避免把翻译缓存、信源状态和运行信息公开。

  1. 在 GitHub 创建一个私有空仓库,把公司 Gitea 中的本项目推送到该仓库的 main 分支。这个 GitHub 仓库可以只是研发复现环境,不要求替代公司 Gitea 主仓库。
  2. 打开 Settings -> Actions -> General -> Workflow permissions,选择 Read and write permissions,允许工作流提交更新后的数据快照。
  3. 打开 Settings -> Secrets and variables -> Actions -> Variables,创建:
    • SANSHENG_SITE_URL:独立站最终访问根地址,不带末尾 /。
    • PUBLIC_SITE_URL:已经部署完成并可访问的站点根地址;尚未部署时可以暂不创建。
  4. 在 GitHub 仓库创建 .github/workflows/update-standalone.yml:
name: Update Sansheng Intelligence

on:
  workflow_dispatch:
  schedule:
    # UTC 01:30,即北京时间 09:30。
    - cron: "30 1 * * *"

concurrency:
  group: update-sansheng-intelligence-${{ github.ref }}
  cancel-in-progress: true

permissions:
  contents: write

jobs:
  update:
    runs-on: ubuntu-latest
    timeout-minutes: 35
    env:
      SANSHENG_SITE_URL: ${{ vars.SANSHENG_SITE_URL }}

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Setup Python
        uses: actions/setup-python@v6
        with:
          python-version: "3.11"
          cache: pip
          cache-dependency-path: requirements.txt

      - name: Setup Node
        uses: actions/setup-node@v6
        with:
          node-version: "24"

      - name: Validate configuration
        run: |
          if [ -z "$SANSHENG_SITE_URL" ]; then
            echo "Repository variable SANSHENG_SITE_URL is required"
            exit 1
          fi

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt

      - name: Update data and build dist
        run: python scripts/update_all.py --site-url "$SANSHENG_SITE_URL"

      - name: Run contracts
        run: |
          python -m unittest discover -s tests -p "test_*.py"
          node --test tests/test_frontend.mjs

      - name: Commit data snapshots
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
          git add \
            data/textile-intelligence.json \
            data/textile-trends.json \
            data/textile-intelligence-source-status.json \
            data/textile-zh-cache.json
          if git diff --cached --quiet; then
            echo "No data changes to commit"
          else
            git commit -m "chore: update sansheng intelligence snapshot"
            git push
          fi

      - name: Upload static artifact
        uses: actions/upload-artifact@v4
        with:
          name: sansheng-intelligence-dist
          path: dist/
          if-no-files-found: error
          retention-days: 7

      - name: Verify public deployment
        if: ${{ vars.PUBLIC_SITE_URL != '' }}
        run: |
          python scripts/verify_public_snapshot.py \
            --base-url "${{ vars.PUBLIC_SITE_URL }}" \
            --expected-file data/textile-intelligence.json \
            --retries 12 \
            --interval 30
  1. 在 GitHub 的 Actions 页面手动运行一次 Update Sansheng Intelligence。首次验收应确认:抓取成功、测试通过、仓库出现数据提交、sansheng-intelligence-dist 制品可以下载并直接由静态服务器访问。
  2. 若使用 Cloudflare Pages,在 Pages 项目中连接这个 GitHub 仓库并配置:
    • 生产分支:main。
    • 构建命令:python scripts/build_site.py --site-url "$SANSHENG_SITE_URL"。
    • 输出目录:dist。
    • 环境变量:SANSHENG_SITE_URL 使用与 GitHub 仓库变量相同的正式站点根地址。
  3. Cloudflare Pages 会在 Actions 推送数据提交后自动构建。设置 PUBLIC_SITE_URL 后,Actions 最后一步会比较公开 JSON 与本次数据;公开站仍是旧快照时工作流会失败,不能把“构建成功”误当成“部署成功”。

GitHub Hosted Runner 的公网出口通常比内地 Server 更适合抓取境外官方源,但仍可能被个别源站按机房 IP、地区或反爬规则拒绝。项目的严格模式会保留旧版并拒绝发布不完整数据;不要为了让工作流变绿而删除 --strict 或绕过 source_target == source_success。

有外网访问能力的 Windows/Linux Server

这种环境不需要 GitHub,也不需要 Pages。Server 直接从公司 Gitea 检出代码,作为更新节点运行:

检出或更新代码
  -> 创建 Python 虚拟环境并安装 requirements.txt
  -> 设置 SANSHENG_SITE_URL
  -> 运行 update_all.py
  -> 运行 Python 与 Node 契约测试
  -> 得到不可变的 dist/ 制品
  -> 发布到 IIS/Nginx 新版本目录
  -> 请求公开 JSON 校验 generated_at 和 as_of_date

Windows Server 可以复用 update.bat 和 install-schedule.bat,或由 Task Scheduler/Windows Service 定时运行:

git pull --ff-only
$env:SANSHENG_SITE_URL='https://实际独立站域名'
.\.venv\Scripts\python.exe scripts\update_all.py --site-url $env:SANSHENG_SITE_URL
.\.venv\Scripts\python.exe -m unittest discover -s tests -p 'test_*.py'
node --test tests\test_frontend.mjs

Linux Server 使用同一组 Python 命令,由 systemd timer、Cron 或 Gitea Runner 调度;构建成功后把 dist/ 同步到新的 Nginx 版本目录,再通过 current 软链接原子切换。完整的 Windows/IIS、Linux/Nginx、版本目录和回滚方式见 Java/C# 自托管方案。

Web Server 没有外网,但存在外网更新节点

这是公司内网环境的推荐架构。外网更新节点可以是 GitHub Hosted Runner、公司代理区 Server、境外云主机或具备统一出口的 Gitea Runner;内网 Web Server 不运行抓取代码。

  1. 外网更新节点运行 update_all.py,生成完整 dist/。
  2. 将 dist/ 压缩为带版本时间和提交 SHA 的制品,并生成 SHA-256。
  3. 通过公司制品库、对象存储、SFTP、SMB 或人工审批通道传入内网。
  4. Web Server 把制品解压到新版本目录,校验 SHA-256、JSON、Sitemap 和首页。
  5. 验证通过后切换 IIS 物理路径或 Nginx current 软链接;失败则继续服务旧版本。
  6. 发布完成后,在能访问公开站点的节点运行 verify_public_snapshot.py。

Web 节点只接收 dist/。不要把仓库、.venv、data/textile-zh-cache.json、data/textile-intelligence-source-status.json、runtime/ 或抓取日志放进网站目录。IIS/Nginx 必须优先返回真实静态文件,不能让 /data/*.json 被 SPA fallback 替换成首页 HTML。

任何可用机器都没有境外网络能力

这种情况下不能复现“全部官方源自动更新”。代码无法替代网络出口,也不能安全地用空数据或旧时间伪装成功。只能选择以下路径之一:

  • 由公司网络团队提供合规的 HTTP_PROXY、HTTPS_PROXY、统一出口或官方域名白名单。
  • 使用 GitHub Hosted Runner、外部更新 Worker 或具有合法外网能力的云主机生成制品,再传入内网。
  • 由研发人员在具备外网能力的工作站运行 update.bat,人工提交带 SHA-256 的 dist/ 制品。
  • 明确缩减信源范围,并同步调整数据契约、严格源数量和产品承诺;不能静默跳过不可访问源。

如果没有任何合规外网节点,也不允许人工制品交接,就只能基于仓库里最后一次已验证快照运行 build_site.py,可以持续提供静态站,但不能声称数据仍在自动更新。

仓库不预置绑定具体服务器账号的 Gitea 部署 workflow,因为 Runner 标签、发布协议、IIS/Nginx 路径、制品库和密钥名必须由公司环境决定。确定这些参数后,把本节相同命令接入现有流水线即可,不需要修改抓取、数据结构或前端代码。

SEO/GEO 基线

  • 品牌实体统一为“三笙AI情报局”,简称“三笙AI”;“家纺AI”是能力词,不替代品牌。
  • 核心主题覆盖家纺AI、三笙AI、家纺情报、跨境家纺平台、家纺跨境平台。
  • SANSHENG_SITE_URL 是 canonical、Open Graph、Sitemap 和 llms.txt 的唯一域名来源。
  • 独立版不覆盖 https://www.sanshengai.net/ 根目录,未确定正式域名前不要修改线上 canonical。
  • 每条静态详情包含可直接索引的中文正文,不要求搜索引擎执行 JavaScript。
  • 页面区分官方事实、机器翻译和本站经营建议,结构化数据不把分析冒充官方原文。

测试与发布门槛

python -m unittest discover -s tests -p 'test_*.py'
node tests\test_frontend.mjs
python scripts\build_site.py --site-url http://127.0.0.1:8765

发布前至少确认:

  • Python 与 Node 契约测试全部通过。
  • source_target == source_success,核心栏目非空。
  • dist/index.html、robots.txt、sitemap.xml、llms.txt 和两份公开 JSON 存在。
  • 桌面、390px 和 375px 移动端无横向溢出,七个入口可发现。
  • 中文站不出现译文按钮,已知 Google/Yandex 阻断域名选择正确。
  • 随机抽查 canonical、JSON-LD、官方链接、报名链接、日期和图库原图。

提交与更新日志规范

每次影响代码、数据结构、业务规则、信源、部署或 UI 的提交,都必须先在 CHANGELOG.md 顶部增加日期条目,至少写明:

  • 改了什么、为什么改、影响哪些目录或数据字段。
  • 修复了什么可观察问题,是否有兼容性变化。
  • 实际运行过的测试和构建命令。
  • 回滚该提交后需要同步回滚的数据、缓存或静态目录。

提交信息正文应与日志条目一致,禁止只写“update”“fix”或“优化”。普通回滚使用 git revert <commit>,不要重写共享分支历史。

进一步文档