ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Hexo博客接入不蒜子统计完整教程:从原理到上线

Hexo博客接入不蒜子统计完整教程:从原理到上线

博客搭到第七篇,页面总算是整整齐齐能看了。但每次发完文章,心里都会犯嘀咕:这东西到底有没有人看?哪篇文章比别的更受欢迎?静态博客没有后台数据库,Hexo 自己给不了这些答案。我把不蒜子统计完整接了一遍,从原理到踩坑再到上线,整理成了这份详细到每一步的教程。它特别适合跟着本系列在 Win10 环境里搭 Hexo 博客、又不想为统计功能单独维护一套服务的同学,只要你已经能在本地跑起 hexo server,这篇基本可以照着抄作业。

1. 为什么给 Hexo 加统计,我最终选了不蒜子

1.1 静态博客的统计困境

Hexo 生成出来的是一堆纯静态 HTML 文件,没有 Node 服务端常驻,也没有数据库。我自己以前想过:要不写个后端记录访问量?但为了一个访问计数去维护服务器、数据库、定时备份,成本实在太高,而且和个人博客“轻量”的初衷完全背道而驰。

在这种前提下,可行的统计方案无非几类:站点分析工具、评论系统自带的统计、自建后端、以及不蒜子这种专门为静态博客设计的第三方计数脚本。我做了个简单的对比:

方案是否需要注册能否在页面上直接显示数字部署成本适合场景
站点分析工具需要一般不能直接展示中,需要埋点想看流量来源、用户画像、停留时长
评论系统自带统计部分需要部分能低已经接了评论系统,顺便用
自建后端统计不需要能高对数据有强定制需求
不蒜子统计不用注册核心功能就是显示数字极低,一行脚本只想让访问量被看见

当时选不蒜子就一个理由:它够简单。不用注册、不用申请密钥、不用在后台看报表,插一行脚本,页脚就能出现“本站总访问量 xx 次”。对于个人博客来说,这种“被看见”的仪式感比精确的数据分析重要得多。

1.2 不蒜子的一行脚本里藏了什么

不蒜子的实现逻辑,本质上就是一个跨域计数服务。页面加载时执行它提供的那段 busuanzi.pure.mini.js,脚本会完成几件事:

  1. 检查浏览器的 localStorage 里有没有一个用户唯一标识,没有就生成一个并存进去。
  2. 带着当前页面路径和这个用户标识,向统计服务器发请求。
  3. 服务器负责累加计数,并把最新数值返回给页面。
  4. 脚本把返回值填进对应的 span 标签里,于是页面上就出现了总访问量、访客数、本页阅读量。

理解 localStorage 这一环很重要。它相当于给每个访客发了一张“会员卡”,卡存在浏览器本地。下次再来,脚本直接刷卡,服务器就知道“又是这个人”,从而在统计 UV 时去重。这也是为什么清浏览器缓存、开无痕模式、换浏览器都会导致 UV 变多,因为“会员卡”没了,服务器只能把他当成新访客。

1.3 网上教程那么多,为什么还经常失败

我一开始也照着网上现成的教程复制粘贴,结果数字死活不出现。后来排查才发现,很多教程的失败点非常集中:

  • 老教程的脚本地址已经失效。不蒜子后台换过域名,早期教程里常见的旧地址早就停用了,照抄自然没反应。实际可用的地址我后面会给出。
  • 主题不一样。教程默认你用的是某个特定主题,但我用的主题模板路径完全不同,照着改 footer 文件,改完根本不是我那个文件。
  • 版本差异。即使同一个主题,新版本可能已经在主题配置文件里内置了不蒜子开关,旧版本却要手动改模板。两种操作完全是两码事。
  • 缺少本地验证步骤。很多人改完直接部署上线,然后凭感觉等数字,出了错也分不清是网络问题还是代码问题。

所以这篇我不会只给一套代码让你复制,而是先教会你怎么判断自己的主题属于哪种情况,再顺手把 Win10 环境下的操作细节一起讲了。

2. 动手前先确认这三件事:版本、主题结构和模板位置

2.1 Win10 环境下的基础确认

不管前面几篇是怎么配置的,动手前先花两分钟确认环境。在 Win10 下,最常用的方式是 Win + R 打开运行窗口,输入 cmd 回车,进入命令行。

先看一下 Hexo 环境是否正常:

node -v hexo -v

能看到版本号就说明基础环境没问题。接下来进入博客目录。如果你的博客放在 D 盘,并且路径里带中文或空格,建议这样操作:

d: cd \你的博客目录 dir

dir能列出目录内容,确认当前路径没进错。这里有个 Win10 特有的坑:默认 PowerShell 不支持用&&把命令串起来执行,比如hexo clean && hexo g在 PowerShell 里会报错。如果你习惯用 PowerShell,可以分开执行,或者用分号:

hexo clean; hexo g; hexo s

如果你更习惯 cmd,那么&&是正常支持的。这个细节看起来小,但常常卡住新手半小时。

2.2 弄清楚你的主题属于哪种“体质”

不蒜子的接入方式,完全取决于你用的 Hexo 主题。花一分钟看一下博客根目录下的_config.yml,里面有个theme:字段,写的就是当前主题名。然后打开themes\你的主题名这个目录,就能看到主题的真实结构。

我通常把主题分成三类:

  • 类型 A:自带不蒜子开关。这类主题比较新,主题配置文件里已经有busuanzi、busuanzi_count或visit_counter之类的字段,你只需要把enable改成true就行。
  • 类型 B:没有开关,但结构标准。主题有统一的 footer 模板文件,所有页面都引用同一个 footer,手动加代码进去即可。
  • 类型 C:结构比较特立独行。首页、文章页、归档页用的模板互相独立,footer 不通用,这时候就不能只改一个文件,得多处添加。

快速判断方法很简单:用 VS Code 打开整个博客目录,在左侧文件树上右键选择“在文件夹中查找”,全局搜索busuanzi。如果主题配置或 layout 目录里已经有相关代码,说明是 A 类,直接去改配置;如果搜出来一片空白,就要准备手动改了。

2.3 备份第一,编辑器别用记事本

改文件之前,先把主题配置文件复制一份到桌面。我就是靠这个习惯救回过一次:有一次为了加统计把 footer 模板改乱了,整个页面报错,直接把备份文件拖回去就恢复了。

另外一个 Win10 下特别容易踩的坑是编辑器。系统自带的记事本打开 yml 或模板文件,保存时可能会带上 BOM 头或者改变编码,导致 Hexo 渲染出来的页面出现乱码,或者在配置解析时报错。我强烈建议用 VS Code 这类专业编辑器,打开文件后右下角确认编码是 UTF-8,再做修改。如果你实在不想装编辑器,至少不要用记事本直接改 yml 文件。

3. 不蒜子接入实操:从改配置到本地看到数字

3.1 先走主题自带的开关,省心省事

如果你的主题是“类型 A”,实操会简单到令人感动。找到主题目录下的_config.yml,搜索busuanzi或busuanzi_count,定位到类似这样的区域:

busuanzi_count: enable: false site_uv: true site_pv: true page_pv: true

把enable改成true,保存,然后重新生成页面:

hexo clean hexo g hexo s

打开本地预览地址,页脚如果出现了统计数字,说明主题已经帮你把模板、脚本、样式全部处理好了。不同主题的字段名可能不完全一样,有的叫site_uv,有的叫site_uv_section,但核心思路都是“开开关”。

这里要提醒一句:如果你用的主题支持“配置覆盖文件”,比如_config.主题名.yml,优先去那个文件里改,别动主题自带的_config.yml。否则以后更新主题版本,你改的东西可能被覆盖掉。

3.2 手动注入模板的通用方法

如果你的主题是 B 类或 C 类,就得手动加代码了。先找到 footer 类的模板文件,常见的路径和格式有几种:

  • themes\你的主题名\layout\_partial\footer.ejs
  • themes\你的主题名\layout\_partial\footer.swig
  • themes\你的主题名\layout\_partial\footer.pug

文件后缀可能是.ejs、.swig或.pug,千万别把.ejs的写法直接粘到.pug文件里,Pug 对缩进极其敏感,很容易报错。稳妥的做法是,打开 footer 文件看看里面已经是什么语法,然后在文件末尾追加内容。

最通用的不蒜子统计代码块是这样的:

<script async src="//busuanzi.icerecord.cn/busuanzi/2.3/busuanzi.pure.mini.js"></script> <span id="busuanzi_container_site_pv" style="display:none"> 本站总访问量 <span id="busuanzi_value_site_pv"></span> 次 </span> <span id="busuanzi_container_site_uv" style="display:none"> 访客数 <span id="busuanzi_value_site_uv"></span> 人 </span> <span id="busuanzi_container_page_pv" style="display:none"> 本文阅读量 <span id="busuanzi_value_page_pv"></span> </span>

这段代码有几个细节值得说明:

  • 脚本地址用了//开头的协议相对地址。如果你的站点是 https,它会自动按 https 加载,不会触发浏览器的混合内容拦截。
  • busuanzi_container_*这类外层 span 默认是display:none隐藏状态。不蒜子的脚本加载成功并且拿到数值之后,会自动把它改成可见状态。所以不要手贱替它加display:block,否则在脚本加载失败时,页面上会留下一个空荡荡的“本站总访问量”,丑且尴尬。
  • 三个核心 span 的 id 含义要记清楚:busuanzi_value_site_pv是站点总访问量,busuanzi_value_site_uv是站点总访客数,busuanzi_value_page_pv是当前页面的阅读量。脚本会自动扫描这些 id 并填数字,你不用额外写 JavaScript。

保存模板后,重新生成并本地预览。注意,我每次改完模板都会老老实实执行一次hexo clean,再hexo g。Hexo 有缓存,不 clean 直接生成,有时候会把旧页面残留下来,改了半天没效果,其实看的是缓存文件。

3.3 本地预览时数字不显示怎么办

本地地址默认是http://localhost:4000。很多人以为本地预览时统计一定显示不出来,其实不蒜子是允许 localhost 请求的,正常情况下照样会显示数字。

如果本地就没显示,先别急着部署。按下 F12 打开开发者工具,切到 Console 标签页看有没有红色的报错信息,再切到 Network 标签页,筛选框输入busuanzi,看看脚本请求到底有没有发起、返回状态是什么。

如果 Console 里提示脚本文件 404,十有八九是地址写得不对,回头检查一下是不是抄成了老教程里的失效地址。如果网络请求正常但没有数字,那问题多半出在 span 标签的 id 写错了,比如少写了一个字母。这些在本地阶段发现,比部署上线后再折腾要省事得多。

4. 踩坑实录:数字不显示、计数不准、文章页没有统计

4.1 数字一直是 0 或者页面空白

这是最让人抓狂的问题。我在排查这类问题时,基本按照固定顺序递进:

  1. 脚本地址失效。不蒜子经历过多轮域名调整,网上旧教程大量充斥着已经停用的地址。访问不到脚本,后面的 span 自然不会被填充。可以用浏览器直接访问脚本地址,能返回一段 JS 就说明地址存活。
  2. 网络问题。统计服务器有时候响应慢,比如在公共 Wi-Fi、校园网这类环境下,脚本加载超时。多刷新几次,或者换手机流量试试。
  3. 浏览器插件拦截。广告拦截类插件对第三方统计脚本很敏感,可能直接拦截掉。在无痕模式或者关了拦截插件后测试一次,能区分是不是插件问题。
  4. 页面缓存。本地预览或线上页面被浏览器缓存了,旧页面没有脚本。按 Ctrl + F5 强制刷新,去掉缓存重新加载。
  5. 模板放错位置。比如你把统计代码加进了某个只有首页会引用的局部模板,文章页自然看不到。这种情况可以直接看页面源代码,搜索busuanzi关键词确认代码到底有没有被渲染出来。

还有一个非常隐蔽的坑:把统计代码粘进了 Markdown 文章正文里。别人教程里给的是模板代码,你复制粘贴到source\_posts\xxx.md里,结果页面正文直接显示出一堆 HTML 标签,统计却一点反应都没有。记住,统计代码要进layout模板,不是进文章正文。

4.2 PV 和 UV 的概念别混淆

看到数字后,不少人会疑惑:为什么自己刷新了好几次页面,站点总访问量涨了,但访客数不变?

这就是 PV 和 UV 的区别。PV 是浏览量,每次页面被打开都加 1,包括你自己刷新页面。UV 是访客数,依赖浏览器本地存储的那个用户标识,同一浏览器在一定时间内只算一次。不蒜子的 UV 统计受 localStorage 影响很大,清缓存、无痕模式、换浏览器都会导致 UV 增加,这是所有前端计数方案的通病,不需要追求绝对精确,看趋势就足够了。

4.3 首页有统计,文章页却没有

这个问题我在 C 类主题上遇到过。很多主题的首页模板和文章模板是独立的,footer 文件可能被多个页面共用,也可能各自引用不同的 footer。你只改了首页那个 footer 文件,文章页引用的是另一个。

排查方法:打开一篇文章页面,右键查看网页源代码,搜索busuanzi,如果在源代码里完全找不到,那说明文章页的模板里根本没引入这段统计代码。解决办法是把统计代码放到所有页面共同继承的公共布局文件里,通常是layout.ejs或layout.swig,在 body 底部的某个公共位置加入。如果实在不放心,可以在文章模板的post-meta区域单独放一个page_pv的 span,脚本全局只引入一次,多个 span 都会生效。

4.4 HTTPS 页面加载 HTTP 资源被浏览器拦掉

如果你给站点配了自定义域名并且开启了 HTTPS,就要特别注意脚本地址别写成http://开头的完整地址。浏览器遇到 HTTPS 页面加载 HTTP 资源时,会直接拦截,控制台会报Mixed Content错误,页面上什么都显示不出来。

解决办法就是前面代码里写的:统一使用//协议相对地址,或者直接写成https://的完整地址。顺便说一句,如果页面上还有其他第三方资源,比如字体、头像之类的,也顺手检查一遍,这种混合内容问题经常一起出现。

4.5 常见问题速查表

症状最可能的原因解决建议
脚本 404脚本地址是旧版失效地址换成当前可用的地址
页面完全没数字浏览器插件拦截了统计脚本关闭拦截插件或无痕模式重试
只显示文字没数字span id 写错或脚本未加载检查 id,刷新页面
首页有、文章页没有模板改错地方改公共布局文件,不要只改局部 footer
本地有、线上没有线上缓存了旧页面Ctrl+F5 强刷
HTTPS 报 Mixed Content脚本地址写了 http改用//协议相对地址

4.6 一个兜底方案:把脚本放到本地

第三方统计服务再稳,也有可能因为域名解析、服务器波动而抽风。如果你实在不放心,可以把busuanzi.pure.mini.js这个文件下载下来,放到博客主题的source\js目录里,然后把模板里的脚本地址改成:

<script async src="/js/busuanzi.pure.mini.js"></script>

这样页面加载的脚本文件来自你自己的服务器/静态空间,不会再出现“脚本文件本身加载不出来”的情况。但有一点必须说清楚:脚本本地化只是保证了 JS 文件能加载,真正的计数接口还是在不蒜子的远程服务器上。如果统计服务器本身挂了,本地化脚本同样拿不到数据。这个方案是兜底,不是包治百病。

5. 上线部署后的验证与几个提升体验的做法

5.1 部署流程与上线检查清单

本地预览确认没问题后,就可以部署上线了。先退出本地预览(Ctrl + C),然后:

hexo clean hexo g hexo d

部署完成后,打开线上站点按 Ctrl + F5 强制刷新一次,等一两秒看页脚统计数字。我习惯按下面这个清单逐项检查:

  • 首页能看到站点总访问量,数字不为 0。
  • 访客数也正常显示,并且数值小于等于访问量(正常情况下 UV 不会超过 PV)。
  • 随机打开一篇文章,页面上能看到“本文阅读量”,并且这个数字和首页的站点总访问量是分开统计的。
  • 手机上关掉 Wi-Fi 用流量访问一次,确认不同网络环境下页面也正常。
  • 浏览器地址栏的小锁图标正常,没有红色警告。

另外提醒一下,不蒜子按域名区分站点,不同域名、不同端口看到的统计数字是独立的。如果你本地 localhost 显示了一部分数字,部署到线上域名又是一个全新的计数,这不是出 bug,是正常现象。

5.2 控制统计展示的细节

不是所有人都想在页面上展示全部三类统计。有些人只想显示总访问量,不想暴露访客数;有些人不希望“本文阅读量”出现在文章顶部,怕自己刚发文章就被人看到个位数。

控制方式很简单,不需要动脚本,只需要决定保留哪些 span。不想显示的统计,直接把对应的 span 从模板里删掉就行,其他统计照常工作。比如不想要访客数,就删掉busuanzi_container_site_uv那一整段,站点总访问量和文章阅读量仍然会正常显示。

如果想让某些特定页面完全不显示统计,可以通过 Hexo 的页面变量做判断。以 ejs 模板为例,在统计代码外层套一个条件:

<% if (!(page.layout === 'post' && page.no_busuanzi === true)) { %> <span id="busuanzi_container_site_pv" style="display:none">...</span> <% } %>

然后在文章的 Front Matter 里加一个no_busuanzi: true,那篇文章就不会显示统计了。这个方法对于“关于我”“隐私声明”这类不太需要展示访问量的页面很实用。

5.3 统计、字数与评论信息的整合

博客搭到这一步,页脚光秃秃一串数字其实不太好看。很多主题提供文章信息栏(post-meta),可以把“本文阅读量”和字数统计、评论区信息整合到同一行。比如在文章模板的 meta 区域放入:

<span id="busuanzi_container_page_pv" style="display:none"> 本文阅读量 <span id="busuanzi_value_page_pv"></span> </span>

脚本依然只需要在全局引入一次,页面上任意位置的 span 都会被自动填充,不需要每个 span 都配一个 script 标签。把统计放在文章标题下方,比放在页脚更容易被访客看到,对内容创作者的正反馈也更强。

5.4 别把统计当成唯一的数据来源

不蒜子解决的是“页面显示数字”这个需求,但它给不了用户的来源渠道、停留时长、跳出率这些流量分析数据。如果你把博客当成一个长期经营的项目,想认真分析读者从哪里来、喜欢看什么,可以考虑在不蒜子之外再引入一个站点分析工具,把埋点统计代码加到页面的 head 区域。两者不冲突,一个负责“给你看”,一个负责“给你分析”。

我的建议是,不要一开始就全副武装。先把不蒜子跑通,享受一下访问量从 0 到 1 的快乐,等博客内容稳定更新了,再考虑要不要上更重的分析工具。

6. 写在最后:一点实操体会

不蒜子统计接入本身不复杂,但它在整个 Hexo 博客系列里承担着一个微妙的角色:让“维护个人主页”这件事从单向输出变成了双向反馈。以前发完文章,阅读量全靠自己脑补;现在数字摆在页脚,每次打开网站都有种“被看到了”的实感。

我个人实操下来最大的体会是,这类第三方功能接入,最难的不是代码,而是判断“该改哪里”。同一个教程,别人一条直线走通,你可能因为主题结构不同、脚本地址过期、PowerShell 不支持&&这些弯弯绕绕,硬生生卡一下午。所以这篇特意把“先看主题配置,再定位模板,最后本地验证”的流程放在前面,就是希望你能少走这些弯路。

最后再分享一个小技巧:每次改完主题文件,hexo clean一定要记得执行,这几乎成了我发布前的肌肉记忆。清缓存、生成、本地预览、部署,这一套流程走顺之后,后面再加赞赏、地图、SEO 这些功能时,节奏都会快很多。博客真正开始有自己的样子,往往就是从这些一个个小功能落地开始的。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进