写一个 WordPress 评论转换工具

在把博客迁出 WordPress 的时候难免要一块儿把评论迁出来。怪了,全网常用的评论系统,Valine,Twikoo,怎么就没有 WordPress 导入呢?另一个评论系统,Artalk,倒是有个 Artransfer 工具,通过 WordPress 全部的导出文件解析评论,导出 Artrans 格式。但 sadly, it simply didn’t work. 它也并不能很好地处理重定向。

那总不能把评论一个一个输到 Twikoo 里面吧,那未免太不优雅了。何况即使五分钟手工能干成的事情,也要花两个小时去自动化完成(狗头)。

导出方法

WordPress 备份文件的组织形式我觉得挺麻的,幸好还有另一种获取评论的方式,即 REST API。该接口虽然是公开的,但是在进行认证之后,可以读取到评论的全部信息,包括发送者邮箱、IP 和 user-agent 等。而在以前使用的全部资料导出方式中,根本没办法导出 UA。

读出来某条评论大概是这个样子:

json
 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
    {
        "id": 123, // 评论 ID
        "post": 2345, // 文章 ID,即代表 /archives/2345 的那篇文章
        "parent": 0, // 父评论 ID,0 代表没有父评论
        "author": 0, // 作者 ID,0 代表未登录用户
        "author_name": "AuthorName", // 作者名
        "author_email": "author@example.com", // 作者邮箱
        "author_url": "https:\/\/example.com", // 作者网站
        "author_ip": "1.1.1.1", // 发送 IP
        "author_user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0", // 发送者浏览器 UA
        "date": "2000-00-00T00:00:00", // 本地和 GMT 发送时间
        "date_gmt": "2000-00-00T00:00:00",
        "content": {
            "rendered": "content", // HTML 评论内容
            "raw": "" // 纯文字评论内容
        },
        "link": "", // 评论链接,指向对应文章的对应评论
        "status": "approved", // 是否过审
        "type": "comment", // 好像只有 comment
        "author_avatar_urls": { // 三种尺寸的头像链接。很难想象 WordPress 会直接预存三种链接,虽然都是 Gravatar 的
            "24": "",
            "48": "",
            "96": ""
        },
        "meta": [], // 用于存放一些额外的 metadata
        "_links": { // 相关 API endpoint
            "self": [
                {
                    "href": "https:\/\/example.com\/wp-json\/wp\/v2\/comments\/123"
                }
            ],
            "collection": [
                {
                    "href": "https:\/\/example.com\/wp-json\/wp\/v2\/comments"
                }
            ],
            "children": [
                {
                    "embeddable": true,
                    "href": "https:\/\/example.com\/wp-json\/wp\/v2\/comments?parent=123"
                }
            ]
        }
    },

详细解析见 WordPress REST API Handbook

要获取完整内容,需要在 WordPress 后台-用户-个人资料中生成一个“应用程序密码”(或使用 其他认证方式),然后在请求中加入对应的认证信息,并将 context 设为 edit。比如使用 cURL:

bash
1
curl --user "username:password" -X GET https://example.com/wp-json/wp/v2/comments?context=edit

输出格式

作为一个 Twikoo 用户,为什么不输出为 Twikoo JSON 呢,是因为不想用吗?

想啊,很想啊,但只有 Artalk 的 Artran 有现成的格式定义,而且数据定义也相对简单,起码比逆向 Twikoo JSON 简单得多。

json
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
    "id": "123", 
    "rid": "233", 
    "content": "Hello Artalk", 
    "ua": "Artalk/6.6", 
    "ip": "233.233.233.233",
    "created_at": "2021-10-28 20:50:15 +0800 +0800", 
    "updated_at": "2021-10-28 20:50:15 +0800 +0800", 
    "is_collapsed": "false", 
    "is_pending": "false", 
    "vote_up": "666", 
    "vote_down": "0", 
    "nick": "qwqcode", 
    "email": "qwqcode@github.com", 
    "link": "https://qwqaq.com", 
    "password": "", 
    "badge_name": "管理员", 
    "badge_color": "#FF716D", 
    "page_key": "https://artalk.js.org/guide/transfer.html", 
    "page_title": "数据迁移", 
    "page_admin_only": "false", 
    "site_name": "Artalk",
    "site_urls": "http://localhost:3000/demo/,https://artalk.js.org"
}

文档示例,简单易懂,对吧?唯一需要解释的就是 rid,即父评论 ID。在不存在父评论的时候,可以直接设为 0。

实际上只含有下面的这些字段的话,也能用:idridcontentuaipis_collapsedcreated_atupdated_atnickemaillinkpage_key。在不太复杂的情况下,page_key 可以仅写作 /guide/transfer.html

链接重定向

如果迁移前后的评论系统附属网站 permalink 的格式不一样,那么评论的 page_key 也要做相应的修改。个人迁移前后的博客站点暂时是同时开放的,而迁移后 Hugo 也可以方便地设立重定向页面。

举个例子吧,假设原页面为 old.example.com/archives/2345,对应新页面为 new.example.com/post/new-post,则 Hugo 设立 alias 之后会在 new.example.com/archives/2345 生成一个重定向页面,内容为:

html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<!DOCTYPE html>
<html lang="zh-cn">
  <head>
    <title>https://new.example.com/post/new-post/</title>
    <link rel="canonical" href="https://new.example.com/post/new-post/">
    <meta name="robots" content="noindex">
    <meta charset="utf-8">
    <meta http-equiv="refresh" content="0; url=https://new.example.com/post/new-post/">
  </head>
</html>

假设我们在之前的 WordPress REST API 中已经获取到旧 WordPress 网站中某条评论的 post 字段值为 2345,那么只需要访问 new.example.com/archives/2345 ,运用正则表达式提取 refresh URL 即可提取到新的 page_key,即 /post/new-post

代码实现

GitHub repo

后记

写完程序之后,我变成了一个 Artalk 用户。

许可证:CC BY-SA 4.0
最后更新于 Jun 18, 2023 11:15 +0800