惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hacker News: Ask HN
Hacker News: Ask HN
WordPress大学
WordPress大学
H
Help Net Security
小众软件
小众软件
N
Netflix TechBlog - Medium
C
Check Point Blog
量子位
Last Week in AI
Last Week in AI
GbyAI
GbyAI
Martin Fowler
Martin Fowler
M
MIT News - Artificial intelligence
博客园 - 聂微东
Engineering at Meta
Engineering at Meta
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
J
Java Code Geeks
D
DataBreaches.Net
Project Zero
Project Zero
P
Proofpoint News Feed
T
Threat Research - Cisco Blogs
Security Latest
Security Latest
Cisco Talos Blog
Cisco Talos Blog
Recorded Future
Recorded Future
I
Intezer
L
Lohrmann on Cybersecurity
Cyberwarzone
Cyberwarzone
博客园_首页
C
Cyber Attacks, Cyber Crime and Cyber Security
L
LangChain Blog
P
Palo Alto Networks Blog
V
V2EX
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
The Exploit Database - CXSecurity.com
The Hacker News
The Hacker News
Blog — PlanetScale
Blog — PlanetScale
G
GRAHAM CLULEY
T
The Blog of Author Tim Ferriss
C
Cisco Blogs
The Register - Security
The Register - Security
L
LINUX DO - 热门话题
P
Privacy & Cybersecurity Law Blog
Scott Helme
Scott Helme
F
Full Disclosure
博客园 - 司徒正美
Recent Announcements
Recent Announcements
IT之家
IT之家
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Attack and Defense Labs
Attack and Defense Labs
Cloudbric
Cloudbric
Help Net Security
Help Net Security
The Last Watchdog
The Last Watchdog

晴雀堂

赛博斗蛐蛐 二周目了 后记 明天高考了 【虾塔完结篇】希腊决战 x 几维鸟 乔越 猪使 晨阳 封印椅 虾塔 2026新年快乐! 博客小修 博客踩坑与重生:解决无提示错误ERR_INVALID_URL switch大气层虚拟系统急救指南 无树莓派安装klipper固件 再次小改博客 两轮承载灵魂 旧文钞-明斯克卷 基于gpt4o的免费桌宠解决方案 如何在lunar端中安装模组 无视免费帐户限制!白嫖各家显卡爽玩SD webui 终于有独立域名啦 简评《饿殍:明末千里行》 博客成立两年啦 next主题使用Gemini进行ai文章总结
为hexo博客添加隐藏ai文本的功能
晴雀 · 2026-07-09 · via 晴雀堂

昨天刚刚斗完赛博蛐蛐,把文章上传到博客。这时我发现我的博客中,文章主要内容为ai生成的博客竟然已达6篇,就想到一个功能,那就是为hexo博客添加隐藏ai文本的功能。

我的初步构想是:在用户第一次进入博客是,弹窗询问:你是否能够接受AI-generated文本的展示?

如果用户选择是,则展示带有AI-gen标签的文章,用户选择否,则隐藏带有AI-gen标签的文章。而且此过程由cookie记录。为了简化代码量,可以提示:如需更改选项,只需清除cookie即可。

这样,能接受ai-gen的人,可以看到博客里一些自娱自乐性质的文章,以及我还读高三时创作的虾塔系列。陈家明读完(他显然难以读完这些又臭又长的后现代先锋狗屎)后告诉我,搭配上ai生成让这些奇异搞笑的故事具有类似迷幻剂的效果。

注:本博客是不存在100% ai生成的文章的,文章前的序都是我自己手写的,不过如果文章主体内容为ai生成,就会被我归入ai-gen,当然代码类内容除外。

不能接受ai-gen的人,将会获得一个干净的主页,可以看到100%我自行创作的文章,也就免去了被ai污染的烦恼。

说干就干,虽然这种小事交给美国豆包Gemini足以,但我还是要大炮打蚊子,搬出肥波来,只是为了满足一下我的好奇心而已。

撰写prompt,询问肥波:

1
2
3
4
5
6
7
我想让hexo博客实现如下功能:

在用户第一次进入博客是,弹窗询问:你是否能够接受AI-generated文本的展示?

用户选择是,则展示带有AI-gen标签的文章,用户选择否,则隐藏带有AI-gen标签的文章。而且此过程由cookie记录。为了简化代码量,可以提示:如需更改选项,只需清除cookie即可。

其他信息:hexo版本7.3.0 还安装了next主题版本8.12.2

肥波很快给出了一套方案,这也是我的第一套方案

方案1:全部隐藏

全部隐藏是包括主页/归档…等等其他页面都不能看到ai生成的文章,即使你用直链访问,也会看到空白界面。

肥波的方案如下:

思路:构建时用 Nunjucks 注入点把所有带 AI-gen 标签的文章路径输出成一个 JS 数组,前端脚本根据 cookie 决定是否弹窗、是否隐藏这些文章(首页/归档页的条目 + 文章页本身)。

1. 给文章打标签

在需要标记的文章 front-matter 中:

1
2
3
4
5
---
title: 某篇 AI 生成的文章
tags:
- AI-gen
---

2. 开启 NexT 自定义注入点

编辑 NexT 配置文件(_config.next.yml 或主题 _config.yml):

1
2
custom_file_path:
bodyEnd: source/_data/body-end.njk

3. 新建 source/_data/body-end.njk

1
2
3
4
5
6
7
8
9
10
11
12
13
{# 输出所有带 AI-gen 标签的文章路径 #}
<script>
window.AI_GEN_POSTS = [
{%- for post in site.posts.toArray() -%}
{%- for tag in post.tags.toArray() -%}
{%- if tag.name == 'AI-gen' -%}
"{{ url_for(post.path) }}",
{%- endif -%}
{%- endfor -%}
{%- endfor -%}
];
</script>
<script src="{{ url_for('/js/ai-gen-filter.js') }}"></script>

4. 新建 source/js/ai-gen-filter.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
(function () {
var COOKIE_NAME = 'ai_gen_consent';


function getCookie(name) {
var match = document.cookie.match(new RegExp('(?:^|;\\s*)' + name + '=([^;]*)'));
return match ? decodeURIComponent(match[1]) : null;
}
function setCookie(name, value, days) {
document.cookie = name + '=' + encodeURIComponent(value) +
'; path=/; max-age=' + days * 86400;
}


function normalize(href) {
try {
return new URL(href, location.origin).pathname;
} catch (e) {
return href;
}
}

var aiPaths = (window.AI_GEN_POSTS || []).map(normalize);
if (!aiPaths.length) return;


function hideAIGenPosts() {

if (aiPaths.indexOf(normalize(location.pathname)) !== -1) {
var post = document.querySelector('.post-block') || document.querySelector('.main-inner');
if (post) {
post.innerHTML =
'<div style="text-align:center;padding:80px 20px;color:#888;">' +
'<p style="font-size:18px;">本文包含 AI-generated 内容,已根据您的选择隐藏。</p>' +
'<p>如需更改选项,清除本站 Cookie 后刷新即可。</p>' +
'</div>';
}
}

document.querySelectorAll('a[href]').forEach(function (a) {
if (aiPaths.indexOf(normalize(a.getAttribute('href'))) !== -1) {
var block = a.closest('.post-block, article');
if (block) block.style.display = 'none';
}
});
}


function showModal() {
var overlay = document.createElement('div');
overlay.id = 'ai-gen-modal';
overlay.style.cssText =
'position:fixed;inset:0;z-index:99999;background:rgba(0,0,0,.55);' +
'display:flex;align-items:center;justify-content:center;';
overlay.innerHTML =
'<div style="background:#fff;max-width:420px;width:90%;border-radius:8px;' +
'padding:28px 24px;text-align:center;box-shadow:0 8px 30px rgba(0,0,0,.25);">' +
'<h3 style="margin:0 0 12px;font-size:18px;color:#333;">内容展示确认</h3>' +
'<p style="margin:0 0 8px;color:#555;line-height:1.7;">' +
'你是否能够接受 AI-generated 文本的展示?</p>' +
'<p style="margin:0 0 20px;color:#999;font-size:13px;">' +
'提示:如需更改选项,清除本站 Cookie 即可。</p>' +
'<button id="ai-gen-yes" style="margin:0 8px;padding:8px 26px;border:none;' +
'border-radius:4px;background:#409eff;color:#fff;cursor:pointer;">是</button>' +
'<button id="ai-gen-no" style="margin:0 8px;padding:8px 26px;border:1px solid #ccc;' +
'border-radius:4px;background:#fff;color:#555;cursor:pointer;">否</button>' +
'</div>';
document.body.appendChild(overlay);

document.getElementById('ai-gen-yes').onclick = function () {
setCookie(COOKIE_NAME, 'yes', 365);
overlay.remove();
};
document.getElementById('ai-gen-no').onclick = function () {
setCookie(COOKIE_NAME, 'no', 365);
overlay.remove();
hideAIGenPosts();
};
}


function main() {
var consent = getCookie(COOKIE_NAME);
if (consent === 'no') {
hideAIGenPosts();
} else if (!consent) {
showModal();
}

}

if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', main);
} else {
main();
}


document.addEventListener('pjax:success', function () {
if (getCookie(COOKIE_NAME) === 'no') hideAIGenPosts();
});
})();

5. 重新生成

1
hexo clean && hexo g && hexo s

说明

  • cookie 有效期 365 天,键名为 ai_gen_consent,值为 yes / no;用户清除 cookie 后再次访问会重新弹窗。
  • 弹窗只在没有 cookie(即首次访问或清除后)时出现。
  • 选择”否”时:文章列表(首页、归档、标签页等)中带 AI-gen 标签的条目被隐藏;若用户通过直链进入 AI-gen 文章页,正文会被替换为提示信息。
  • 文章列表由构建时生成的 window.AI_GEN_POSTS 数组驱动,无需在前端解析标签,兼容 NexT 各种列表样式。
  • 如果你开启了 NexT 的 pjax: true,脚本已通过监听 pjax:success 做了兼容。

方案2:只在主页隐藏

我最终采用了这个方案

只需调整 hideAIGenPosts 的作用范围:仅在首页(含首页分页)生效,归档页、标签页、文章页均不做处理。

1. 修改 source/_data/body-end.njk

增加输出站点根路径,方便前端判断当前是否为首页:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{# 输出所有带 AI-gen 标签的文章路径 #}
<script>
window.AI_GEN_POSTS = [
{%- for post in site.posts.toArray() -%}
{%- for tag in post.tags.toArray() -%}
{%- if tag.name == 'AI-gen' -%}
"{{ url_for(post.path) }}",
{%- endif -%}
{%- endfor -%}
{%- endfor -%}
];
window.SITE_ROOT = "{{ config.root }}";
</script>
<script src="{{ url_for('/js/ai-gen-filter.js') }}"></script>

2. 替换 source/js/ai-gen-filter.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
(function () {
var COOKIE_NAME = 'ai_gen_consent';


function getCookie(name) {
var match = document.cookie.match(new RegExp('(?:^|;\\s*)' + name + '=([^;]*)'));
return match ? decodeURIComponent(match[1]) : null;
}
function setCookie(name, value, days) {
document.cookie = name + '=' + encodeURIComponent(value) +
'; path=/; max-age=' + days * 86400;
}


function normalize(href) {
try {
return new URL(href, location.origin).pathname;
} catch (e) {
return href;
}
}

var aiPaths = (window.AI_GEN_POSTS || []).map(normalize);
if (!aiPaths.length) return;


function isHomePage() {
var root = window.SITE_ROOT || '/';
var path = location.pathname;

return path === root ||
new RegExp('^' + root.replace(/\//g, '\\/') + 'page\\/\\d+\\/?$').test(path);
}


function hideAIGenPostsOnHome() {
if (!isHomePage()) return;

document.querySelectorAll('a[href]').forEach(function (a) {
if (aiPaths.indexOf(normalize(a.getAttribute('href'))) !== -1) {
var block = a.closest('.post-block, article');
if (block) block.style.display = 'none';
}
});
}


function showModal() {
var overlay = document.createElement('div');
overlay.id = 'ai-gen-modal';
overlay.style.cssText =
'position:fixed;inset:0;z-index:99999;background:rgba(0,0,0,.55);' +
'display:flex;align-items:center;justify-content:center;';
overlay.innerHTML =
'<div style="background:#fff;max-width:420px;width:90%;border-radius:8px;' +
'padding:28px 24px;text-align:center;box-shadow:0 8px 30px rgba(0,0,0,.25);">' +
'<h3 style="margin:0 0 12px;font-size:18px;color:#333;">内容展示确认</h3>' +
'<p style="margin:0 0 8px;color:#555;line-height:1.7;">' +
'你是否能够接受 AI-generated 文本的展示?</p>' +
'<p style="margin:0 0 8px;color:#999;font-size:13px;">' +
'选择"否"仅会在首页隐藏相关文章,归档页与直链访问不受影响。</p>' +
'<p style="margin:0 0 20px;color:#999;font-size:13px;">' +
'提示:如需更改选项,清除本站 Cookie 即可。</p>' +
'<button id="ai-gen-yes" style="margin:0 8px;padding:8px 26px;border:none;' +
'border-radius:4px;background:#409eff;color:#fff;cursor:pointer;">是</button>' +
'<button id="ai-gen-no" style="margin:0 8px;padding:8px 26px;border:1px solid #ccc;' +
'border-radius:4px;background:#fff;color:#555;cursor:pointer;">否</button>' +
'</div>';
document.body.appendChild(overlay);

document.getElementById('ai-gen-yes').onclick = function () {
setCookie(COOKIE_NAME, 'yes', 365);
overlay.remove();
};
document.getElementById('ai-gen-no').onclick = function () {
setCookie(COOKIE_NAME, 'no', 365);
overlay.remove();
hideAIGenPostsOnHome();
};
}


function main() {
var consent = getCookie(COOKIE_NAME);
if (consent === 'no') {
hideAIGenPostsOnHome();
} else if (!consent) {
showModal();
}

}

if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', main);
} else {
main();
}


document.addEventListener('pjax:success', function () {
if (getCookie(COOKIE_NAME) === 'no') hideAIGenPostsOnHome();
});
})();

3. 重新生成

1
hexo clean && hexo g && hexo s

相比上一版的改动点

项目 上一版 本版
首页 隐藏 AI-gen 条目 隐藏 AI-gen 条目(不变)
归档页 / 标签页 隐藏 正常展示
直接访问文章链接 正文被替换为提示 正常展示全文

关键实现是新增的 isHomePage():通过对比 location.pathname 与站点根路径(以及 /page/N/ 形式的首页分页),确保过滤逻辑只在首页触发。归档页(/archives/...)、标签页、分类页和文章详情页都不会匹配,因此完全不受影响。

注意:如果你的博客部署在子目录(例如 https://xxx.github.io/blog/),请确保 Hexo _config.yml 中的 root: /blog/ 配置正确,isHomePage() 依赖它来判断首页路径。


这样就大功告成了。