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

推荐订阅源

P
Privacy International News Feed
WordPress大学
WordPress大学
Security Latest
Security Latest
Cyberwarzone
Cyberwarzone
K
Kaspersky official blog
Cisco Talos Blog
Cisco Talos Blog
Microsoft Security Blog
Microsoft Security Blog
G
GRAHAM CLULEY
N
News | PayPal Newsroom
Apple Machine Learning Research
Apple Machine Learning Research
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V
Visual Studio Blog
美团技术团队
J
Java Code Geeks
I
Intezer
The Cloudflare Blog
SecWiki News
SecWiki News
S
Secure Thoughts
Microsoft Azure Blog
Microsoft Azure Blog
V2EX - 技术
V2EX - 技术
C
Cyber Attacks, Cyber Crime and Cyber Security
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Spread Privacy
Spread Privacy
D
DataBreaches.Net
S
Security Affairs
Help Net Security
Help Net Security
S
Securelist
F
Full Disclosure
C
Check Point Blog
F
Fortinet All Blogs
Know Your Adversary
Know Your Adversary
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Y
Y Combinator Blog
云风的 BLOG
云风的 BLOG
阮一峰的网络日志
阮一峰的网络日志
The Register - Security
The Register - Security
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
人人都是产品经理
人人都是产品经理
博客园_首页
G
Google Developers Blog
Google Online Security Blog
Google Online Security Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
H
Help Net Security
酷 壳 – CoolShell
酷 壳 – CoolShell
I
InfoQ
Application and Cybersecurity Blog
Application and Cybersecurity Blog
H
Hacker News: Front Page
L
LINUX DO - 热门话题
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
L
LangChain Blog

半方池水半方田

小球称重问题及其引申的思考 蓝色的结构色 病毒是不是生物? 把博客发布交给 GitHub Actions 省外居民身份证的补换领(苏州) hexo-filter-titlebased-link:构建你的数字花园 Vercel 应用实践学习 通过与 Keycloak 配合实现博客文章的受限访问功能 非公开的文章 Soft Mode 非公开的文章 Strict Mode 试试用代码块在 Hexo 中插入实况照片 动态图片测试 Hexo-Butterfly 主题 Preloader 加载页定制 Keycloak 的部署以及 Hexo-Butterfly 网页应用的接入 Authentik 的部署记录 Waline 自建 Auth 认证 记一次行李托运理赔流程(南航) Docker 镜像的制作、拉取与运行 Hexo-Butterfly 主题中对 Algolia 搜索框 Power By 的定制 Hexo 动态加载配置(钩子函数) 设计原则 VSCode 中的配置
随机访问文章的实现(Sitemap+本地缓存优化)
wuanqin · 2026-04-08 · via 半方池水半方田

|总字数:855|阅读时长:4分钟|浏览量:|

|出链:0|入链:1

一份古老的代码传承至今,已经有很多的版本…这里介绍我的版本。

随机访问文章的实现思路

随机文章跳转的基本原理就三步:

  • 提前准备好一张站点列表
  • 读取列表,并随机挑一个出来
  • 访问目标地址

站点列表的准备

站点列表可以自己准备,或者使用插件 hexo-generator-sitemap 来生成。

站点列表的样子:

1
2
3
4
5
6
https://blog.uuanqin.top/p/18bbd410/
https://blog.uuanqin.top/p/c7d4d021/
https://blog.uuanqin.top/pages/copyright/index.html
https://blog.uuanqin.top/p/51890a9/
https://blog.uuanqin.top/p/91b7dad/
https://blog.uuanqin.top/pages/about/index.html

优化点

为了保证函数的精简和高效,本文代码有以下优化点:

  • 不重复请求 sitemap.txt,而是利用浏览器本地缓存(带过期)加速网站列表的获取
  • 随机跳转有不依赖任何框架的 CSS 简单提示
  • 随机跳转时将保持 url 参数,如想移除,可自行在REMOVED_PARAMS中填入。

Hexo-Butterfly 主题的使用

这里以菜单栏按钮为例。_config.butterfly.yml 中配置如下:

1
2
3
4
5
6
7
8

menu:
随机: javascript:randomPost(); || iconfont icon-suijibofang

inject:
head:

- <script src="/js/random.js"></script>

random.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



const RANDOM_CONFIG = {
SITEMAP_URL: '/sitemap.txt',
PATH_FILTER: '/p/',
CACHE_KEY: 'random_post_data',
CACHE_TIME: 24 * 60 * 60 * 1000,
FALLBACK_URL: '/',
REMOVED_PARAMS: []
};

async function randomPost() {

const showNotice = (msg) => {
let snack = document.getElementById('random-snack');
if (!snack) {
snack = document.createElement('div');
snack.id = 'random-snack';

Object.assign(snack.style, {
position: 'fixed', bottom: '30px', left: '50%', transform: 'translateX(-50%)',
backgroundColor: '#333', color: '#fff', padding: '10px 20px', borderRadius: '5px',
zIndex: '9999', fontSize: '14px', transition: 'opacity 0.3s'
});
document.body.appendChild(snack);
}
snack.innerText = msg;
snack.style.opacity = '1';
setTimeout(() => snack.style.opacity = '0', 2000);
};

try {
let urls = [];
const cached = localStorage.getItem(RANDOM_CONFIG.CACHE_KEY);
const now = Date.now();


if (cached) {
const { data, timestamp } = JSON.parse(cached);
if (now - timestamp < RANDOM_CONFIG.CACHE_TIME) urls = data;
}

if (urls.length === 0) {
showNotice('正在同步文章列表…');
const res = await fetch(RANDOM_CONFIG.SITEMAP_URL);
if (!res.ok) throw new Error();
const text = await res.text();

urls = text.split('\n')
.map(l => l.trim())
.filter(l => l !== '')
.map(u => {
try {
let p = new URL(u).pathname;
return p.endsWith('/') ? p : p + '/';
} catch(e) { return null; }
})
.filter(p => p && p.includes(RANDOM_CONFIG.PATH_FILTER));

localStorage.setItem(RANDOM_CONFIG.CACHE_KEY, JSON.stringify({ data: urls, timestamp: now }));
}


const current = window.location.pathname.endsWith('/') ? window.location.pathname : window.location.pathname + '/';
const candidates = urls.filter(p => p !== current);

if (candidates.length === 0) {
showNotice('没有发现其他文章,正在返回主页…');
setTimeout(() => location.href = RANDOM_CONFIG.FALLBACK_URL, 1500);
return;
}

const targetPath = candidates[Math.floor(Math.random() * candidates.length)];


const params = new URLSearchParams(window.location.search);
RANDOM_CONFIG.REMOVED_PARAMS.forEach(p => params.delete(p));

const search = params.toString() ? '?' + params.toString() : '';
const finalUrl = targetPath + search + window.location.hash;

showNotice('正在穿越到随机文章…');
setTimeout(() => location.href = finalUrl, 800);

} catch (err) {
console.error('RandomPost Error:', err);
showNotice('跳转失败,正在返回主页…');
setTimeout(() => location.href = RANDOM_CONFIG.FALLBACK_URL, 1500);
}
}

本文参考

版权声明 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 半方池水半方田

封面生成即梦 AI - 图片 5.0 Lite

Prompt扁平2D卡通插画,「随机文章」封面图,颜色鲜明,元素丰富,主次分明,无文字,包含循环箭头和骰子元素,画面活泼有趣

赞助

  • 微信

    微信

  • 支付宝

    支付宝


avatar

wuanqin

只能懂一点点

最新文章

蓝色的结构色