wechat-site-ops
SKILL.md 内容
{
"name": "wechat-site-ops",
"content": "---\nname: wechat-site-ops\ndescription: 微信生态网站运营——微信分享卡片(og:image)、域名被微信拦截的排查与申诉(验证文件部署)、风控字眼防御清理。当用户说\"微信分享只显示网址\"\"微信打不开我的网站\"\"申请恢复访问\"\"域名被微信拦截/封禁\"时使用。\ncategory: web\n---\n\n# 微信生态网站运营\n\n自运营 ToB 站点(aicnnc.com / aiadmin.com.cn 等)在微信内分享、访问、申诉的标准打法。\n\n## 何时用\n\n| 触发词 | 场景 |\n|--------|------|\n| \"微信分享只显示网址\" | 微信内分享链接没有卡片(图标/标题/简介),只有纯 URL |\n| \"微信打不开/拦截\" | 微信内打开显示\"如需浏览,请长按网址复制后使用浏览器访问\" |\n| \"申请恢复访问\" | 用户已进入微信申诉流程,需要部署验证文件 |\n| \"把招商/代理字眼去掉\" | 防御性清理,避免域名被微信风控误判 |\n\n## 1. 微信分享卡片(og:image)\n\n**症状**:微信分享后只显示网址,无卡片。\n\n**根因**:缺 `og:image`(分享卡片图)。微信抓取分享信息需要:og:title + og:description + **og:image(绝对 URL)**。只有 og:title/description 不够。\n\n**修复步骤**:\n1. 生成分享图:1200×630 PNG(微信推荐尺寸),PIL 绘制(中文字体用 `/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc`,品牌紫色渐变 + 黄色标签 + 白色大标题 + 底部域名)\n2. 部署到网站根目录:`/var/www/<域名>/og-share.png`,chmod 644\n3. 页面 head 加标签(**必须绝对 URL**):\n```html\n<meta property=\"og:image\" content=\"https://<域名>/og-share.png\">\n<meta property=\"og:image:width\" content=\"1200\">\n<meta property=\"og:image:height\" content=\"630\">\n```\n4. 多站各自独立分享图(文案不同则各做一张),部署后 curl 验证 200\n\n**多页静态站(推荐):nginx sub_filter 全站注入,一改生效含未来新页**\naicnnc.com / aiadmin.com.cn 已用此法(2026-09-07):站点 nginx 443 server 块在销售浮窗 sub_filter 后追加:\n```nginx\nsub_filter '</head>' '<meta property=\"og:image\" content=\"https://<域名>/og-share.png\"><meta property=\"og:image:width\" content=\"1200\"><meta property=\"og:image:height\" content=\"630\"><meta property=\"og:description\" content=\"<站点兜底描述>\"></head>';\n```\n- ⚠️ **2026-09-25 修正口径:按标签分而治之,别整段删**。原假设\"注入在页面自带 meta 之后 → 爬虫取首个 → 不覆盖\"**只对了一半**:页面自带 og 的站会变成**一页两份 `og:description`、文案还不同**(注入那份是当年的旧文案),抓取方取哪份不可控 —— aiadmin.com.cn 的\"卡片简介不更新\"就是这么来的。但**整段删 `sub_filter '</head>'` 是过度修复**:\n - `og:description` → **删掉注入**(页面自己写;注入版只会添乱)\n - `og:image` → **保留注入**(真·全站兜底)。删之前先数一遍有多少页自己没写:\n ```bash\n cd ~/projects/<站> && grep -L \"og:image\" *.html | wc -l # aiadmin 实测 54/55 页没有!\n ```\n 整段删掉 = 54 个页面的分享图一起消失(2026-09-25 实际踩到,随后补回)。页面自带 og:image 的首页会变成**两份但取值相同** → 抓取方取哪个都一样,无害。\n - 按页出图才用 `map $uri $og_image` + `sub_filter` 变量(见下);真要全站兜底就写进页面模板/生成器,别在出口改写描述。\n- 适用前提:页面全小写 `</head>`;改完 `nginx -t && systemctl reload nginx`\n- 验证:`curl -s <某文章页> | grep -c og-share.png` 应 ≥1;自带图页(如 policy)og:image 计数 = 自带+1\n\n\n**分享卡片「图标 + 名称 + 简介」三件套(2026-09-24 aicnnc 实测补齐)**\n\n用户说的「ico / 名称 / 简介」= 卡片上的缩略图 / 标题 / 描述,三样都要在 head 里显式给:\n\n| 卡片元素 | 标签 | 备注 |\n|---|---|---|\n| 图标(缩略图) | `og:image`(**绝对 URL**)+ width/height | 也顺手补 `rel=\"icon\"`(页面缺 favicon 声明时浏览器/收藏也难看) |\n| 名称 | `og:title`(与 `<title>` 同文本) | 加 `og:site_name` 更稳 |\n| 简介 | `og:description`(自己写,别用全站兜底那句) | 加 `og:url` / `og:type` |\n\n**生成分享图别手搓 —— 用脚本**:`~/projects/aicnnc-site/scripts/gen_share_card.py`(一张卡 = 踢标 + 两行大标题 + 一排白牌 + 两行说明;`python3 gen_share_card.py -o /tmp` 出全部)。\n- 字体用 `/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc`(`ImageFont.truetype(..., index=0)`),**绝对不要在图上写 emoji/彩色图标** —— 本机字体缺字形,会渲染成 **▯ 豆腐块**(旧 og-share.png 就这么废的)。\n- 出完 `assert` 体积 < 400KB(微信抓取超时),再 `sudo cp` 到站根 / share 子目录 + `chmod 644`。\n\n**按页一张图,别全站共用**:全站共用会出现「点进 A 页、卡片上写的是 B 页」的不匹配。做法是 nginx `map $uri $og_image` + `sub_filter` 用变量(sub_filter 替换串**支持变量**,实测可用;细节与 `/run/nginx.pid` 空导致 reload 假成功的坑见 skill `nginx-domain-ops`)。\n\n**改完必须 curl 验收**(`nginx -t` 通过 ≠ 已加载):`curl -s https://站/页.html | grep -oE '<meta property=\"og:image[^>]*>'` 看值对不对、是不是只有一条。\n\n**用户说\"卡片的图/标题/简介还是旧的\"——按这三道查,别先怀疑 logo**(2026-09-25 aiadmin 实战)\n\n1. **页内标签**:`curl -s https://<域>/ -A \"MicroMessenger/8.0\" | grep -c og:description` —— 正常 = **1**。>1 就是出口注入造成的重复(见上一条),先解决重复。\n2. **出口有没有被改写**(最容易漏的一层):拿**公网抓到的页面**和**磁盘文件**比,字节数/行数不等就是出口在改写:\n ```bash\n curl -s https://<域>/ -A \"MicroMessenger/8.0\" -o /tmp/served.html\n wc -c /tmp/served.html /var/www/<域>/index.html # 差值 = 注入的体积\n diff /tmp/served.html /var/www/<域>/index.html | head\n sudo nginx -T > /tmp/dump.txt; grep -n \"sub_filter\" /tmp/dump.txt\n ```\n ⚠️ **`include /etc/nginx/sites-enabled/*` 是通配、不过滤 `.conf` → 目录里躺着的 `.bak` / `.deploy` 备份文件也会被当配置加载**。本次就是两个 `aiadmin.com.cn.conf.bak_*` 各自带着同一段旧 og 注入,光改主配置没用。处置:把非配置的备份**移出**该目录(`sudo mkdir -p /etc/nginx/backups-moved-out-of-sites-enabled && sudo mv …`,**只移不删**)→ `nginx -t` → `systemctl reload nginx` → 重抓复验。\n3. **微信自己的缓存**:同一个 URL 已经发出去的卡片基本不回刷。要立刻看新卡片,用**带参数的新 URL**(`https://<域>/?v=2`)发一次;答复里要明说\"已发过的卡片得等微信重抓\",别让用户以为没改。\n\n**一条命令代替手工 grep(先跑这个)**:`python3 ~/projects/scripts/tools/check-share-card.py <url>...`\n微信 UA 抓页面 → 报出 `<title>` / `og:title` / `og:description` / `og:image` 各出现几次、取值是什么、分享图能否下载且 ≥300×300;退出码 0/1,可直接进巡检。\n- **重复且取值不同 = 失败**(本类 bug 的判据);**重复但取值相同 = 只报警告**(页面自带 + 兜底注入,无害)\n- 2026-09-25 一次扫 4 个 URL:顺手发现 aicnnc 首页也有同款重复(值相同才没出事)、`/docs` 干脆没有分享图。**别只查用户报的那一个 URL。**\n\n**另外两条判据(省一轮来回)**\n- **别拿微信内置浏览器的顶栏当判据**:顶栏显示的是页面 `<title>`,卡片用的是 `og:title` —— 两处文案本来就可以不同,拿顶栏对比一定会说\"没生效\"。\n- **图有独立缓存**:换参数 URL 能绕页面缓存,但 `og:image` 指向的**图片 URL** 微信也单独抓过 —— 换了图内容、路径不变,卡片还是老图。**处置:改文件名**(`og-share.png` → `og-share-v2.png`),页内 `og:image` 同步改,老文件留着不动。\n\n**用户只回\"还不行\"时别接着猜**:给 4 个具体选项让他勾 —— ① 根本没卡片,只有纯链接 ② 卡片在但标题/简介是旧的 ③ 标题简介新、只有图旧 ④ 图空白 —— 并要一张卡片截图。一次问清,好过连改三轮。\n\n**favicon ≠ 卡片图标**:个人微信分享卡片的缩略图**只认 `og:image`**,没有 favicon 的位置 —— 换 favicon(`rel=\"icon\"`)不会让卡片变。用户说\"ico 没生效\"时,先按上面三道查 og,再解释这条;改 favicon 交不了这个差。\n**卡片的图 = `og:image` 这张设计稿**(默认没有 logo 也行)。要让品牌标出现在卡片上,是把字标**画进 og-share.png**,不是换 favicon;贴字标位置**先出图看一眼**(本次右下角压住了第三行文案,改到右上空白区才对)。\n\n**坑**:\n- 微信对分享信息有缓存——改过 og 标签后,已分享过的链接可能仍显示旧信息(等 24h 或换带参数 URL 触发重抓)\n- og:image 必须绝对 URL,相对路径无效\n- 图片中文字体缺失时 PIL 会 fallback 到 load_default(方块字)——先确认 wqy 字体存在\n\n## 2. 域名被微信拦截(排查 + 申诉)\n\n**症状**:微信内打开显示\"如需浏览,请长按网址复制后使用浏览器访问\" + \"申请恢复访问\"按钮。\n\n**先诊断**(网站本身是否正常):\n```bash\ncurl -s -o /dev/null -w \"HTTP:%{http_code}\\n\" https://<域名>/ --max-time 10\ncurl -s https://<域名>/ | grep -oE \"京ICP备[0-9]+号-[0-9]\" # 备案在不在\ncurl -s https://<域名>/ | grep -oE \"招商|代理|合伙人|区域合作|加盟|躺赚|回本|收益\" | sort | uniq -c\n```\n- 网站 200 + 备案正常 + 内容无违规 = **微信风控拦截**(非网站故障)\n- 常见触发:新域名 + 营销页(招商/代理字眼)易被误判;被访客举报\n\n**申诉流程**(微信\"申请恢复访问\"页面):\n1. 选择\"部署验证文件并提交证明材料\"(比纯材料审核优先级高)\n2. 微信给 **TXT 文件名** + **文件内容**(两串不同的 32 位 hex)——让用户把两串**复制粘贴**发来(勿靠截图 OCR)\n3. 在**网站根目录**创建该 TXT,内容填另一串 hex\n4. 申诉理由模板(内部系统型站点):\"本站为企业内部 XX 管理系统,无对外营销内容,域名已 ICP 备案(主域备案号),请求恢复访问\"\n\n**拦截诱因排查**(新补充,didi 案例):\n- 页面**没挂 ICP 备案号** + 标题非常规(如\"司机反巡访\")+ 新子域 = 微信风控高危组合\n- 解封后**必须补备案号到页面底部**(同主体主域备案即可),降低再被拦概率\n\n**验证文件部署要点**(关键坑):\n- 文件名 = 用户从微信**复制**的为准(32 位 hex 标准验证名);截图 OCR 读文件名不可靠(可能漏字符)——两处来源不一致时**两个文件名都放**,保险\n- 内容 = 另一串 hex,**无换行**(`printf '%s'` 写入,不要 echo 带换行)\n- **无静态根目录的站(location / 是 proxy_pass 反代)不能\"放文件\"**——文件放不进后端服务,后端返回 404。改用 nginx 直出(2026-09-17 didi.canjinbao.com 实战验证):\n ```nginx\n # http 和 https 两个 server 块都要加(http 块加在 return 301 之前,否则 http 访问拿不到)\n location = /<32位hex>.txt {\n default_type text/plain;\n return 200 \"<另一串hex>\";\n }\n ```\n 加完 `nginx -t && systemctl reload nginx`。reload 后有秒级延迟:公网 404 别慌,`curl --resolve <域名>:443:127.0.0.1` 直连 200 即配置正确,稍等重试\n- 静态站放根目录:`sudo cp <file> /var/www/<域名>/` + chmod 644\n- **http 和 https 都要能访问**;www 子域也要验证(微信可能要求 www 也通)——nginx 若 http→https 301 且微信验证器不跟随,可能失败;确认 `curl -sL` 跟随后 200\n- 部署后 curl 验证:`curl -s https://<域名>/<文件名>` 应返回内容原文\n\n**失败排查**:\n- 验证失败但文件 200 → 检查文件名是否与微信显示完全一致(多/少一个字符都失败)\n- 微信有验证缓存,文件对也可能要等 10min-几小时\n- 内容是否误带换行/空格\n\n## 3. 风控字眼防御清理\n\n**原则**:真风险词全删;正常营销词保留(删了伤转化,且正常词不是拦截原因)。\n\n| 类别 | 词 | 处理 |\n|---|---|---|\n| 招商/代理(真风险) | 区域合作、合伙人、代理、招商、加盟、躺赚、回本、收益 | **全删** |\n| 正常营销(保留) | 免费试用、14天、月订阅、按效果可退款 | 保留(aicnnc 有且没被封) |\n\n**清理后**:\n- 全站复查清零:`curl -s https://<域名>/ | grep -oE \"区域合作|代理|招商|加盟|合伙人|躺赚|回本|收益\" | sort | uniq -c`\n- 冒烟测试确认页面仍正常\n- 注意:**移除入口只降低未来风险,已触发的拦截不会自动解除**(拦截是快照式,需重新访问重新评估)\n\n**渠道/代理需求不丢**:从公开页撤下 ≠ 放弃——规划文档保留,解封后走\"仅提交证明材料\"申诉或做登录后可见页面承接。\n\n## 验证\n\n- [ ] 分享卡片:og:image 绝对 URL + 图片 200 + 尺寸 1200×630\n- [ ] 拦截申诉:验证文件 200 + 内容原文一致 + http/https/www 全通\n- [ ] 防御清理:风险词全站 0,冒烟全绿\n\n## 4. 客户触达通道:能不能\"自动邀客户聊天 / 自动回微信\"(2026-09-24 增补)\n\n用户问这类问题的**默认答案**:**能做,工具不用买 —— 通道我们已经接了**(企微智能机器人 + 个人微信均在线)。但\"主动\"要看通道规则:企微群发**每客户每天 1 条**、个人微信**只对已聊过的人**、批量主动要换电话/短信/邮件/WhatsApp。**个人微信外挂类工具(协议逆向 / PC Hook)一律不碰**(违约 + 封号高危),也别给客户推荐。\n\n- 完整通道对照、封号事实、企微认证与会话存档口径、自动回的分级线(可自动回 6 类 / 必须人审 6 类)、能力包卖法 → `references/wechat-outreach-channels-and-rules.md`\n- 先看这份再答,别凭印象说\"能做/不能做\"。\n\n## 相关 skill\n\n- `wechat-article-extraction` / `wechat-article-fetch`:公众号文章抓取(注意:两 skill 重叠,建议 curator 合并)\n- `static-site-editing`:页面区块删除的 HTML 平衡验证\n- 实录参考:`references/aiadmin-wechat-block-2026-08.md`(静态站路线)· `references/didi-wechat-block-2026-09.md`(**反代站 nginx 直出路线** + 无备案号拦截诱因)\n- 卡片不更新实录:`references/share-card-og-forensics-2026-09.md`(**出口注入重复 og / sites-enabled 混入 .bak / 图独立缓存** 三条根因 + 取证命令 + 正确 vs 有病的 nginx 注入写法 + 回滚路径)\n- 体检脚本(git 跟踪,可直接跑):`~/projects/scripts/tools/check-share-card.py <url>...`\n",
"path": "/home/agentuser/.hermes/skills/wechat-site-ops/SKILL.md",
"size": 8468
}