将 vBulletin 4 论坛迁移到 Discourse

是的,它们会被转换。我明天会发邮件给您!

3 个赞

您需要达到 1 级信任等级才能解锁私信功能,目前您在此处阅读主题的时间还不足以达到该等级。

4 个赞

你好,我正在使用 Docker 容器(DigitalOcean),并尝试导入 mybb(我知道这个教程是针对 Vbulletin 的,但 Gemfile 部分类似)。我在运行 bundle install 时卡住了:

你好,
我们尝试将 vBulletin 3.8 导入 Discourse。该脚本在导入包含 300MB 数据库、约 4 万用户和 6 万帖子的数据时运行正常。但在导入过程结束时,我们遇到了字符集问题。

  • 我们的 vBulletin 3.8 使用 latin1 字符集编码。
    ----> 在运行导入脚本时,Discourse Docker 中的 MySQL 5.6 配置为 UTF-8 字符集。
  • 导入脚本强制将数据转换为 UTF-8 进行导入。
    因此,导入过程结束后,Discourse 论坛显示的数据出现 UTF-8 编码错误。效果如下所示:
  1. 导入前,vB 3.8

  2. 导入到 Discourse 后

我们尝试了以下方法:

  • 在运行导入脚本之前,将 vB 3.8 的字符集转换为 UTF-8。
  • 在新的 MySQL 服务器上测试该 vB 3.8 数据库,文本显示正常,未出现编码错误。
    请问您对此情况有什么建议吗?

非常感谢您的支持(如果我的英语表达让您难以理解,深表歉意)。

1 个赞

这是我解决类似问题的部分代码:

    ### WIN1252 编码
    win_encoded = ''
    begin
      win_encoded = raw.force_encoding('utf-8').encode("Windows-1252",
                            invalid: :replace, undef: :replace, replace: ""
                           ).force_encoding('utf-8').scrub
    rescue => e
      puts "\n#{'-'*50}\nWin1252 对以下数据转换失败:\n\n#{raw}\n\n"
      win_encoded = ''
    end
    raw = win_encoded
5 个赞

你救了我的命。
为了省事,我尝试了在帖子 Migrate a phpBB3 forum to Discourse - #540 by gerhard 中提到的转换脚本,帮我快速修复了数据库字符集问题,现在一切顺利。
非常感谢你的建议。

3 个赞

有人使用 vBulletin 5 导入器进行过迁移吗?我将来可能会使用它,想知道它是否已经过无故障的验证。

2 个赞

我刚刚导入了 vBulletin5 并添加了一些功能(永久链接、部分格式化,可能还有一些我记不清的其他内容)。我打算提交一个拉取请求(PR),但尚未完成。

3 个赞

我有一个包含附件的 vb5 数据库转储文件。我可以直接将它们导入 Discourse 吗?还是必须将所有附件作为文件单独处理?

对此我也感到困惑。我究竟应该把附件文件复制到 Discourse 文件夹中的哪个具体位置?:thinking:

2 个赞

再次你好,
据我理解,来自数据库的附件应该可以正常工作,因为它们似乎与同样存储在数据库中的头像以相同的方式处理。

我的导入进展顺利,但在导入 91% 的帖子时遇到了一个错误 :weary_face:

正在导入帖子...
  1425149 / 1564573 ( 91.1%)  [1040 项/分钟]  回溯(最近一次调用在最后):
        14: 来自 script/import_scripts/vbulletin5.rb:726:in `<main>'
        13: 来自 /home/canapin/discourse/script/import_scripts/base.rb:47:in `perform'
        12: 来自 script/import_scripts/vbulletin5.rb:49:in `execute'
        11: 来自 script/import_scripts/vbulletin5.rb:300:in `import_posts'
        10: 来自 /home/canapin/discourse/script/import_scripts/base.rb:862:in `batches'
         9: 来自 /home/canapin/discourse/script/import_scripts/base.rb:862:in `loop'
         8: 来自 /home/canapin/discourse/script/import_scripts/base.rb:863:in `block in batches'
         7: 来自 script/import_scripts/vbulletin5.rb:320:in `block in import_posts'
         6: 来自 /home/canapin/discourse/script/import_scripts/base.rb:508:in `create_posts'
         5: 来自 /usr/local/rvm/gems/ruby-2.6.5/gems/rack-mini-profiler-2.0.4/lib/patches/db/mysql2.rb:8:in `each'
         4: 来自 /usr/local/rvm/gems/ruby-2.6.5/gems/rack-mini-profiler-2.0.4/lib/patches/db/mysql2.rb:8:in `each'
         3: 来自 /home/canapin/discourse/script/import_scripts/base.rb:509:in `block in create_posts'
         2: 来自 script/import_scripts/vbulletin5.rb:321:in `block (2 levels) in import_posts'
         1: 来自 script/import_scripts/vbulletin5.rb:450:in `preprocess_post_raw'
script/import_scripts/vbulletin5.rb:450:in `gsub': 无效的 UTF-8 字节序列 (ArgumentError)

我该如何正确识别该帖子,以便查看其在 vBulletin 数据库中的内容是什么样的?

1 个赞

有人建议使用 rescue 来解决这些问题,你可以回去找找相关讨论(我不确定是在这个主题里还是另一个主题)。你可以在 rescue 中加入一个 put 语句,打印出导致问题的 id 和/或文本。

你遇到了编码问题。

我在类似的导入过程中使用了以下方法(我认为你应该将其放在 preprocess_post_raw 中):

    begin
      win_encoded = raw.force_encoding('utf-8').encode("Windows-1252",
                            invalid: :replace, undef: :replace, replace: ""
                           ).force_encoding('utf-8').scrub
    rescue => e
      puts "\n#{'-'*50}\nWin1252 failed for \n\n#{raw}\n\n"
      win_encoded = ''
    end
3 个赞

你好,
我修改了导入器,并按以下方式添加了你的脚本:

  def preprocess_post_raw(raw)
    return "" if raw.blank?
    begin
      win_encoded = raw.force_encoding('utf-8').encode("Windows-1252",
                            invalid: :replace, undef: :replace, replace: ""
                           ).force_encoding('utf-8').scrub
    rescue => e
      puts "\n#{'-'*50}\nWin1252 失败,内容如下:\n\n#{raw}\n\n"
      win_encoded = ''
    end
    # 解码 HTML 实体
    raw = @htmlentities.decode(raw)

    # 修复空白字符
    raw = raw.gsub(/(\r)?\n/, "\n")
      .gsub("\t", "\t")

UTF-8 无效字节序列错误出现在这一部分:raw = raw.gsub(/(\r)?\n/, "\n") .gsub("\t", "\t")

随后我重新启动了导入器。虽然它跳过了已导入的数据,但花了大约 6 小时才到达生成错误的那条帖子,而且它并没有添加预期的信息来查看帖子内容。:confounded_face: 有什么想法吗?

编辑:

这很可能是导致错误的帖子原始内容:

I wonder if Billy is enjoying the parade.

Qwertyuiopasdfghjklzxcvbnm&#55356;&#57174;

我将尝试修改导入器脚本,使其真正跳过之前的 140 万条帖子。祝我好运吧。:crossed_fingers:

2 个赞

我已修改了许多其他导入器,添加了 import_after 设置,以便仅导入最近的数据。你可以查看其他导入器的实现,了解我是如何做到的。

2 个赞

你好,
我已经成功导入了几乎所有帖子!我手动修复了几十个问题,每次遇到新的 UTF-8 错误就重启导入过程……:sweat_smile:

现在,我需要导入附件(它们存储在 VBulletin 数据库中),但无法正常工作:
当导入过程开始时,我的内存使用量在大约 10 到 20 秒内急剧上升,随后出现以下错误:

正在导入附件...
创建上传失败:无法分配内存 - grep
失败

我的内存使用情况:

我在 Windows 10 的 Ubuntu 18 子系统上运行 Discourse 开发版本,拥有 16 GB 内存。

附件占用了 VBulletin 数据库(共 13 GB)中的 7 GB。
请注意,我使用的是 vbulletin5 导入器。

问题出在这个查询上:

    SELECT n.parentid nodeid, a.filename, fd.userid, LENGTH(fd.filedata) AS dbsize, filedata, fd.filedataid
      FROM #{DB_PREFIX}attach a
      LEFT JOIN #{DB_PREFIX}filedata fd ON fd.filedataid = a.filedataid
      LEFT JOIN #{DB_PREFIX}node n on n.nodeid = a.nodeid

如果我在 MySQL 中执行此查询,剩余内存会在几秒钟内被占满。


(编辑我的帖子,移除无用信息和问题,因为我正在逐步解决问题并提供变通方案)

变通方案:

我在导入器的 SQL 查询中添加了 LIMIT 和 OFFSET。我每次选择 20000 条附件进行导入:

    uploads = mysql_query <<-SQL
    SELECT n.parentid nodeid, a.filename, fd.userid, LENGTH(fd.filedata) AS dbsize, filedata, fd.filedataid
      FROM #{DB_PREFIX}attach a
      LEFT JOIN #{DB_PREFIX}filedata fd ON fd.filedataid = a.filedataid
      LEFT JOIN #{DB_PREFIX}node n on n.nodeid = a.nodeid
      LIMIT 20000 OFFSET 0
    SQL

我还在 uploads.each do |upload| 循环末尾添加了 exit,以防止导入脚本在导入完 20000 条附件后继续执行。

当我的 10000 条附件导入完成后,我编辑脚本(感谢使用 nano +353 ./scripts/import_scripts/vbulletin5.rb 可以直接打开文件到正确行),将 SQL 查询的 OFFSET 增加 10000,然后重新启动导入器……如此重复直到完成全部 65000 条附件的导入。

在导入附件过程中,我遇到了多个错误和警告,包括:

  • W, [2020-08-20T12:05:37.402860 #31042] WARN -- : 日期/时间值无效 "0000:00:00 00:00:00": 月份超出范围
  • 未找到帖子 490451(我猜是悬空的旧附件?)
  • 一些 EXIF 数据错误
  • 失败 这个错误让我很困惑,并导致导入脚本停止。我检查了第一个“失败”记录,发现对应的论坛附件似乎已损坏(没有文件名),因此我注释掉了 exit 指令,让导入器在遇到“失败”时继续执行,希望这不会破坏任何东西。
       puts "失败"
       #exit

我还遇到了一个更烦人的错误,导致导入中断:

1: from /usr/local/rvm/gems/ruby-2.6.5/gems/activerecord-6.0.3.2/lib/active_record/validations.rb:53:in `save!'
/usr/local/rvm/gems/ruby-2.6.5/gems/activerecord-6.0.3.2/lib/active_record/validations.rb:80:in `raise_validation_error':
验证失败:正文长度限制为 32000 字符;您输入了 32323。 (ActiveRecord::RecordInvalid)

幸运的是,这是一个罕见的错误,我只需跳过该附件,直到遇到下一个相同的错误。在总共 65000 条附件中,这种情况大约发生了十几次。我只需使用不同的 SQL 查询 OFFSET 重新启动导入脚本即可。

1 个赞

你好,

我注意到,在我剩余的 27000 名用户中(已清理了 154000 名不活跃用户),大约有 400 名用户缺少自定义字段 import_pass

请问这可能是什么原因?

论坛是在 5 月份从 phpBB 迁移到 vBulletin 的。这是否与此有关?

我暂时不打算“修复”这个问题,也不打算为这 400 名用户导入密码(除非有简单的方法……),这也不是什么大问题,所以我主要是出于好奇才来询问的。

1 个赞

大家好,
导入的图片宽高比不正确,除非我重新烘焙帖子。我想找到一种方法(例如在导入时)来获得正确的宽高比,而无需重新烘焙。

更详细的描述:

据我了解,当 Discourse 创建相应帖子时,导入的帖子并未被“烘焙”(尽管 cooked 字段以某种方式生成),因此导入帖子比烘焙现有的 Discourse 帖子快得多。

我的问题是,我导入的图片宽高比不正确。

以下是与导入图片相关的原始 Discourse 文本示例:

![SH-MUniFrame.JPG|600x800](upload://6Li1nnjbA8zDz6YJ3FqeYHV5zXK.jpeg)

“cooked”字段的内容:
<img src="https://d11a6trkgmumsb.cloudfront.net/original/3X/0/3/0379f53ed8221730ccb31807238e9c46e9fe1d37.jpeg" alt="SH-MUniFrame.JPG" data-base62-sha1="6Li1nnjbA8zDz6YJ3FqeYHV5zXK" width="517" height="500" class="d-lazyload">

图片在帖子中的显示效果:


这是原始图片:
https://d11a6trkgmumsb.cloudfront.net/original/3X/f/7/f73a0ae8594219dd5a1620e59b3c17f9b02b1583.jpeg

来自 vBulletin 数据库的原始图片尺寸为:

select width, height from filedata where filedataid = 76237
+-------+--------+
| width | height |
+-------+--------+
|   600 |    800 |
+-------+--------+

我的理解是,height 属性受到 Discourse 设置的限制,该设置将最大高度设为 500 像素,因此 <img> 标签中的 height 属性值也为 500。不过,<img> 的 width 从 600 修改为 517,但我无法弄清楚这是如何以及为何发生的。

对于 vBulletin 附件字段中宽度和高度均为 0 的旧图片,也存在同样的问题。这些图片的宽高比也不正确。我不知道这些值是否在导入过程中真正被使用。

重新烘焙(重建 HTML)帖子可以解决此问题。之后图片将被正确调整大小,并添加图片查看器。但我有 160 万篇帖子,更倾向于避免对所有帖子进行重新烘焙。

一个快速的解决方法是在我的 Discourse 中使用以下 CSS:

.cooked img:not(.emoji) {
    height: auto;
    width: auto;
}

但这意味着用户将无法在上传图片时选择任意尺寸,而且可能会产生我尚未意识到的副作用。

关于如何在导入附件时获得正确的图片宽高比,有什么建议吗?

我怀疑这是因为你在导入后没有让它们进行烘焙。我想不出一种不重新烘焙帖子就能解决问题的方法。也许你只想重新烘焙那些出问题的帖子,而不是全部?

1 个赞

它们应该在导入后随时间自动重新渲染吗?是从最后创建的帖子开始,还是从最早创建的帖子开始?

不过这不算什么大问题。如果它们不会自动重新渲染,我可能会启动对所有帖子的重新渲染,然后耐心等待。不过我得承认,几天前我读过这篇帖子,它让我有点担心:https://meta.discourse.org/t/my-journey-into-a-massive-posts-rebake-job/84816。我对此也有一些疑问,但我会到合适的主题中提问。:blush:

嗯,是的,这看起来确实是我的代码。对此很抱歉。:confused:

这应该遵循以下模式:

   batches(BATCH_SIZE) do |offset|
       (SQL 代码)
        LIMIT #{BATCH_SIZE}
        OFFSET #{offset}
        (其他代码)
    end
1 个赞

只需在导入前将站点设置中的 最大帖子长度 调高即可。

2 个赞