做个人站长这些年,我最不愿意碰但又绕不开的一件事,就是合规。它不像配置 Nginx 那样改完立刻能看到效果,也不像写文章那样有正反馈。它更像买保险:平时完全感觉不到,出事那天才知道有没有。
这两年身边至少有四个站出过问题:两个是因为用了没备案的域名做国内解析,被运营商拦了;一个是文章里带了某个不该带的关键词,收到了通知;还有一个是在页面上挂了一个来路不明的广告联盟代码,结果被判定为落地页有问题,连带整站被降权。四件事的共同点是:都不是技术故障,但只要发生,处理起来比技术故障麻烦得多,因为技术故障你能自己修,合规问题得等别人给你答复。
所以这篇不做攻略,只做一张清单——把「一个内容站需要长期自查的东西」按我自己的实际执行顺序列出来,包括每项看什么、多久看一次、发现了怎么办。你们可以按自己的站调整,但顺序建议保留,因为它是按「出问题的代价从高到低」排的。
一、域名与备案:最容易被忽略的地基
如果有国内业务、要在国内服务器上放站,ICP 备案是硬门槛,没有例外。但备案不是「办完就完了」的一件事,它有几个持续的约束,很多人只在办的时候看一眼。
第一,备案主体信息必须和实际一致。如果你的备案是用个人身份办的,那站点就不能有明显的经营性内容——比如在线售卖、付费会员、接受赞助并公示。这条的边界在实践中比较模糊,但保守的做法是:个人备案的站,不做任何形式的收款页面。如果确实需要收费,正规路径是换成企业主体重新备案,或者把收费部分放到另一个合规主体下。
第二,服务器换了要重新核对。备案是「主体 + 域名 + 接入服务商」三者的绑定关系,换了机房和接入商,需要做接入备案变更。有些人图省事,先把服务器迁到新服务商,想着「反正域名没变应该没事」,结果是在新服务商那边查不到接入记录,属于典型的「未备案接入」,被扫描到就会被要求整改,整改期内域名可能被阻断。
第三,备案号要挂在页面上。通常是页脚,链接指向工信部备案系统,并且按规范标注。这一条看着像形式主义,但检查的时候是硬性的,缺了就是问题。我见过有人把备案号写在图片里,或者写在一个 display:none 的 div 里,这些做法在自动扫描面前都等于没有。
第四,香港和海外服务器不需要备案,但代价是别的。如果你的用户主要在国内,海外服务器的访问速度会明显吃亏,而且国内搜索引擎对海外服务器的抓取频率往往更低(这条不是官方规则,但从我自己的日志看,同样的站点迁到国内之后,蜘蛛的日抓取量涨了三成左右)。所以「不备案」不是一个免费选项,它用合规成本换来了速度和收录上的劣势。
二、内容层面的自查:三个必看项
内容是内容站的核心资产,也是风险最集中的地方。我每月固定查三件事。
第一件:历史文章里的外链还有效吗,指向的站还是那个站吗。这件事同时是 SEO 问题和合规问题。一个域名到期之后很可能被新的人注册,内容和性质完全变了,而你页面上的链接还指着它。如果那个新站有问题,你的页面就成了它的推荐来源。我在去年清理过一批,200 多个外链里有 17 个已经指向了完全无关的站,其中 3 个指向的是赌彩类落地页——这些链接挂在我站上至少挂了半年。
# 从数据库里抽出所有文章正文,提取外部链接做存活与重定向检查
mysql -N -B -e "SELECT cid, text FROM typecho_contents WHERE type='post'" zz1984 \
| awk -F'\t' '{print $1"\t"$2}' \
| grep -oE 'https?://[^ )>]+' \
| sed 's#/$##' \
| sort -u > /tmp/outlinks.txt
# 逐条看最终落地的 URL 与状态码(-L 跟随跳转,-m 限制超时)
while read -r u; do
code=$(curl -s -o /dev/null -L -m 8 -w '%{http_code}' "$u")
final=$(curl -s -o /dev/null -L -m 8 -w '%{url_effective}' "$u")
[ "$code" != "200" ] && echo "BAD $code $u -> $final"
done < /tmp/outlinks.txt跑完不要只看状态码,一定看 url_effective。一个链接返回 200 但跳到了完全不相干的站,比 404 更危险,因为它看起来是「好的」。这条脚本我建议每季度跑一次,站大一点的话可能要好几分钟,值得。
第二件:评论区和留言板。如果站开了评论且不审核,那评论区就是别人往你站上放内容的地方。这是历史上大量站点出事的源头。我的做法很朴素:所有评论先进待审核队列,只对通过审核的老用户放开直发;同时在数据库里定期搜一遍高危词,命中的评论直接删。
# 定期扫评论里的可疑内容(按需扩充词表,这里只给几个典型类别)
mysql -N -B -e '
SELECT coid, cid, ip, LEFT(text,80)
FROM typecho_comments
WHERE type="comment"
AND (text REGEXP "加(微信|QQ|VX|薇)|代开|包过|一手货源|日赚|撸羊毛|加群"
OR text LIKE "%http%" AND text NOT LIKE "%zz1984%")
ORDER BY coid DESC LIMIT 100;' zz1984注意第二个条件:评论里带外链但链的不是自己站的,一律人工看一眼。正常的读者引用链接很少,多数带外链的评论都是来做外链的。这类内容留着不但没用,还会给你的站贴上一个「外链农场」的标签。
第三件:聚合页和标签页。如果一个标签下只挂着一篇文章,这个标签页本质上就是重复内容;如果一个标签名是「未分类」「杂项」这种,那这个页面既没有搜索价值也没有用户体验。这类页面的处理方式我在之前的文章里写过,这里只补充一个合规视角:自动生成的聚合页最容易把不合适的内容聚到一起,比如「热门」「推荐」这种由算法选出来的列表,可能把一篇早期写得比较随意的文章推到首页。定期看一眼这些自动列表,比看文章本身更重要。
三、广告与第三方代码:最容易被忽视的入口
第三方代码是站点的「外人」。它跑在你的页面上、你的域名下,但你不控制它。这里有三条硬规矩。
第一条:不要挂来路不明的联盟代码。判断一个广告联盟靠不靠谱,不能只看它给的单价。要看三件事:它有没有正规的公司主体和联系方式、它的落地页是什么内容、它有没有要求你把代码插在不容易被发现的位置。第三点尤其重要——正规广告代码都是希望被看见的,只有需要隐藏的东西才要求你藏在页脚小字里或者用脚本动态插入。
第二条:所有第三方脚本都要能被你一键关掉。不要在模板里散着写 script 标签,统一收进一个配置项,出问题的时候能在一分钟内全部下掉。这个能力我吃过教训:有一次某个统计服务出了供应链问题,我的页面被插了跳转,排查了半小时才找到是哪个 <script>,因为它写在侧边栏模板里,那个文件我一年没动过。
第三条:给外部脚本加 integrity 校验。只要 CDN 上的文件内容变了而哈希没变(不可能)或者你写的哈希和实际内容不符,浏览器就拒绝执行。这是防止 CDN 被投毒的最直接手段。这条我在讲 SRI 的时候详细写过,这里只提醒一句:加了 integrity 之后一定要做加载失败的兜底,否则哪天 CDN 改了文件版本,你的页面会静默丢功能,而且前端控制台里可能只有一条不显眼的错误。
<!-- 有 SRI 的外链脚本必须配一个失败兜底 -->
<script src="https://cdn.example.com/lib.min.js"
integrity="sha384-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
crossorigin="anonymous"
onerror="this.onerror=null;this.src='/js/lib.min.js';"></script>四、数据与隐私:小站也躲不开
如果你的站面向的是国内用户,那《个人信息保护法》是适用的,不管站有多小。落到实操上,只有几件事需要做,但必须做。
隐私说明要有,而且要写实话。不要抄一份网上的模板,里面写着收集手机号、身份证,而你实际上只记了一个 IP。写清楚三件事就够了:收集什么(比如访问日志里的 IP 和 UA)、为什么收集(安全与统计)、保留多久(比如日志保留 90 天)。这三句话的写法不用多专业,但必须和你实际做的一致。
日志保留时间要真的执行。很多人的 logrotate 配置里根本没写保留天数,日志一直堆着,三年五年的原始访问记录躺在服务器上。这不只是隐私风险,也是磁盘风险。我的做法是 access log 保留 30 天、error log 保留 60 天,脱敏后的聚合统计数据长期保留。具体天数按你的业务定,关键是「配置里要有这个数,并且真的删得掉」。
如果收集了邮箱或者手机号,要能删。做订阅、做留言、做注册的站,用户提出删除时,你要能在几分钟内定位到这个人并清掉,而不是翻半天数据库。这件事看起来是个小概率事件,但真遇到的时候很被动。我建议在建表的时候就把「用户标识 + 数据位置」列清楚,写进自己的运维笔记里。
五、应急:出事的时候按什么顺序动
这一节希望永远用不上,但必须提前想清楚。所有应急流程的共同点是:时间窗口很短,而你在那一刻的判断力很差,所以要提前把顺序固定下来。
如果收到的是「某个页面有问题」的通知,顺序是:先定位页面 → 立刻把该页面设为 404 或加 noindex → 再改内容 → 改完之后申请复查。不要直接删,因为删除之后你就失去了「原来是什么」的证据,而且在搜索引擎侧的反馈也会慢一拍。设成 410 或者加 noindex 都是更好的中间态。
如果收到的是「域名被阻断」,顺序是:先确认是不是解析层面的问题(换个 DNS 服务器测一下)→ 再确认是不是接入商层面的问题(联系接入商)→ 同时把站点的静态备份准备好,随时能迁到备用域名。备用域名这件事我强烈建议所有人都提前准备:一个主域名之外,至少留一个已经注册好、已经在做正常解析的备用域名,平时就指向一个「维护中」的页面。真出事的时候,把你的内容切到备用域名可能只需要几分钟,但如果临时去买域名、去解析,光是 DNS 生效那一段就够你难受一天。
如果收到的是「被投诉侵权」,顺序是:先看投诉的具体内容(是哪一篇文章、哪一段、什么权利)→ 核实是否属实 → 属实的立刻下架并保留处理记录 → 如果认为不属实,准备好你的原创证据(发布时间、编辑记录、草稿文件)。这里有一个很多人忽略的细节:原创证据要在平时就留下,比如每篇文章发布时把源文件按日期归档一份,或者用一个带时间戳的 git 提交。等到被投诉了再去回溯,很多证据已经没了。
六、一张可以照着执行的周期表
最后把这些事压成一张表,直接放进日历。
每周:看一次评论待审核队列,清掉明显是垃圾的;看一次异常访问来源(某个 IP 突然爆量、某个 UA 突然出现),判断是不是采集。
每月:跑一次内容里的高危词扫描;看一眼自动生成的聚合页有没有把奇怪的文章推上去;确认备份可恢复(不是「备份跑完了」,是真的解压看过一次)。
每季度:跑一次全站外链检查(含 url_effective 判定);核对备案信息与实际服务器是否一致;确认第三方脚本清单和实际页面里的一致,删掉不用的。
每年:域名续费与所有者的确认(这是最高优先级,忘了续费的代价最大);隐私说明与实际收集行为的一致性复核;备用域名的可用性演练一次。
这张表看起来很多,但真正花时间的只有季度那一档,一两个小时就够。我把每年那一档的域名续费设成了提前 90 天的提醒,因为域名到期这件事一旦忘掉,后面所有努力都白费——这是我见过最多、也最惨的一类事故。
合规这件事的本质不是应付检查,而是让你的站能够长期存在。一个技术做得再漂亮、SEO 做得再好的站,如果在某个早上打不开了,前面所有的工作都会在一瞬间归零。把这张清单放在自己能看到的地方,比任何优化技巧都更值得投入。