hexo修改短链及浏览量恢复

最近使用博客的时候发现,复制出来的文章URL都太长了,所以想启用短链,记录一下修改过程。

修改短链

URL优化

Hexo默认的链接是permalink: :year/:month/:day/:title/,文章名称是新建的md文件的文件名,很多时候我都是建中文名字,但是中文路径复制下来会特别长,对于搜索引擎优化不友好,而且一旦文章名字改变,链接也跟着改变,一个好的URL设计,不仅有利于网络爬虫的爬取,更有利于用户的体验。正确的URL设计应该满足:长度尽量短,目录层次尽量少,全小写,连字符使用中划线-,具有描述性,包含关键词等。

我选择了 rozbo/hexo-abbrlink 插件解决上面所说的问题,abbrlink生成的链接短小精悍,并且可以同时保证唯一和持久。

  1. 安装abbrlink插件:
1
npm install hexo-abbrlink --save
  1. 在站点配置文件里修改:
1
2
3
4
5
6
7
8
9
10
# permalink: posts/:year/:month/:day/:title.html  // 默认永久链接冗长,title中存在中文字符
permalink: post/:abbrlink/
# 结尾的"/"如果去掉,在我本地点开文章时会有问题,所以加了"/"
# 还可以使用类似 post/:abbrlink.html 这种链接

abbrlink:
alg: crc16 # 算法:crc16(default) and crc32
rep: hex # 进制:dec(default) and hex
# 使用crc16已经能生成65535篇文章了,对于个人博客感觉已经够用了
# 使用hex是因为我觉得带字母好看一点
  • 优化前:

image-20190509141956909

http://localhost:4000/posts/2019/04/19/hexo%E4%BF%AE%E6%94%B9%E7%9F%AD%E9%93%BE%E5%8F%8A%E6%B5%8F%E8%A7%88%E9%87%8F%E6%81%A2%E5%A4%8D/

  • 优化后:

image-20190509142150265

http://localhost:4000/posts/5389/

成功修改短链后我发现一个问题,那就是文章的浏览量没了,访问量我们使用的是leancloud来记录的(使用next只需要简单的配置就可以使用leancloud记录访问量),而访问量的消失主要是因为文章的链接都改了,接下来我们尝试恢复一下每篇文章的访问量。

浏览量恢复

我们先看一下leancloud是如何存储我们的浏览记录的:

img

可以看到主要有title(标题)、url和time(次数),我们的主要问题是记录的url变了,所以对应关系丢失了,只要恢复正确的url,对应关系就可以重建了,而time对我们恢复关系没有用,只有根据title恢复了。

所以我们要先查到每篇文章的标题,然后从库里找出对应的记录,修改url为正确的地址,这样对应关系就能回来了,获取每篇文章的内容我想到了两种方法:一种是遍历本地生成的html文件获取title,另一种是写个爬虫爬自己的网站。

遍历本地文件实现

本地hexo目录的public/posts文件夹下存放了生成的静态文件,我们遍历这个文件夹拿到每篇文章:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const fs = require('fs')

function getPostsByDir(postDir) {
const htmlList = fs.readdirSync(postDir)

const postList = htmlList.map((abbrLink) => {
// 从本地文件获取html
const html = fs.readFileSync(`${postDir}/${abbrLink}/index.html`).toString()
// 加载html 获取title
const $ = cheerio.load(html)
const postTitle = $(".post-title").text()
return {
abbrLink,
postTitle,
}
})
return postList
}

爬虫实现

hexo生成的是静态页面,我们可以用简单的GET请求爬取页面内容,然后使用cheerio分析处理:

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
const axios = require('axios')
const cheerio = require('cheerio')

const getPostList = ($) => {
const postList = []
// 获取首页标题
$(".post-title-link").each((i, elem) => {
postList.push({
abbrLink: $(elem).attr('href').replace('posts', '').replace(/\//g, ''),
postTitle: $(elem).text(),
})
})
return postList
}

async function getPostsByReptile(domain) {
let postList = []
// 获取总页数
const homePage = await axios.get(domain)
const postPages = cheerio.load(homePage.data)(".page-number").last().text()
// 获取每页的文章标题和链接
for (let i = 1; i <= postPages; i++) {
const url = i > 2 ? `${domain}/page/${i}/` : domain
const html = await axios.get(url)
const $ = cheerio.load(html.data)
postList = postList.concat(getPostList($))
}
return postList
}

tip:针对静态页面的爬虫还是比较简单的,如果是动态页面就需要搭配Puppeteer(一种Chrome的无界面/Headless工具)进行了。

恢复浏览量

通过title搜到文章,然后修改对应的文章链接:

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
const AV = require('leancloud-storage')

AV.init({
appId: 'GxfYzf5roQxLdedcwOheEnWE-gzGzoHsz',
appKey: 'MomkTz6Tq1aBGWvzNDSv8o31'
})

Promise.resolve(postList).then(result => {
result.forEach((post) => {
// 查询同一标题下的所有记录
const query = new AV.Query('Counter')
query.equalTo('title', post.postTitle)

// 留下times最多的一个 修改url 并修改其他脏数据url
query.find().then((results) => {
let maxResult = results[0]
results.forEach((result) => {
if(result.attributes.time > maxResult.attributes.time) maxResult = result
})
maxResult.set('url', `/posts/${post.abbrLink}/`)
maxResult.save()

console.log(maxResult)

// 更改短链后有一些新的访问 属于脏数据 把他们的链接修改错误来解除关联关系
results.forEach((result) => {
if(result.attributes.url === maxResult.attributes.url && result.id !== maxResult.id) {
result.set('url', `/posts/${post.abbrLink}`)
result.save()
}
})
})
})
})

总结

首先使用了 rozbo/hexo-abbrlink 设置了文章的短链,然后因为浏览量丢失,写脚本恢复了访问量,恢复的代码放在这里,欢迎使用和提bug。