Pukiwikiの文書をエクスポートして、textile形式に変換し、RedmineWikiに移行する


なぜやるのか

  • まずPukiwikiが社内共有ツールとして立てられた
  • タスク管理としてRedmineが立てられた
  • チケットに対応内容が蓄積されてRedmineがナレッジ化してきた
  • Pukiwikiもまとめて情報共有をするツールとしてほそぼそ使われてきた。
  • 情報の二元管理状態に区切をつけたい。
  • チケットとWikiを一元検索できるようにRedmineに寄せよう←今ここ

環境と要件

要件

  • Wikiページは200弱
  • 殆どテキストのみなので、画像ついては一括移行時は割愛する。
  • ディレクトリ構造もないのでページをとにかく移管する。
  • 情報の移管を優先するので、その他変換できなかった記法も割愛する。(テーブルなど)

Pukiwikiの環境

  • PukiWiki 1.5.0
  • Windows上のXAMMPにて稼働

Redmineの環境

  • Redmine version 3.3.0.stable
  • Bitnami Redmine Stack にてPukiwikiと同じWindows7上に構築

実行端末の環境

  • Windows7 Pro 64bit
  • PowerShell 3.0
  • Python 3.6.4
  • selenium

移行作業

概要

いろいろ調べた結果、以下の手順が根性作業ではあるが、簡単なのでこちらで行うことにした。

  1. Pukiwikiのdump機能でRawデータを取得
  2. PowerShellにてpukiwiki記法からtextile記法への置換を行う。
  3. Python+Seleniumにてページへの書込を行う。

Pukiwikiデータの取得

/pukiwiki/index.php?cmd=dump へアクセスすると以下の様にページが表示され、Pukiwikiのデータを取得できる。

この際、 エンコードされているページ名をディレクトリ階層付きのファイルにデコード へチェックをいれることで、ページ名がファイル名となっているtxtファイルを取得することができる。

Pukiwiki記法からtextile記法への変換

以下のサイトのjavascriptを参考にさせて頂いた。
http://yakinikunotare.boo.jp/pukiwiki2textile/


    $tgtDir = "C:\wikidata"
    $files = Get-ChildItem -File $tgtDir
    foreach($file in $files){
        $filepath=$file.FullName
        $fileContent = Get-Content $filepath -Encoding UTF8

        $fileContent=$fileContent -replace '^#contents$', '{{toc}}'
        # caption
        $fileContent=$fileContent -replace '^\*([^\*]+?)$', ('h1. $1'+"`r`n")
        $fileContent=$fileContent -replace '^\*\*([^\*]+?)$', ('h2. $1'+"`r`n")
        $fileContent=$fileContent -replace '^\*\*\*([^\*]+?)$', ('h3. $1'+"`r`n")
        $fileContent=$fileContent -replace '^\*\*\*\*([^\*]+?)$', ('h4. $1'+"`r`n")

        # タブを削除する
        $fileContent=$fileCOntent -replace "`t"," "

        # list
        $fileContent=$fileContent -replace '^-([^-]+)$', '*$1'
        $fileContent=$fileContent -replace '^--([^-]+)$', '**$1'
        $fileContent=$fileContent -replace '^---([^-]+)$', '***$1'
        $fileContent=$fileContent -replace '^----([^-]+)$', '****$1'
        # list(number)
        $fileContent=$fileContent -replace '^\+([^+]+)$' , '#$1'
        $fileContent=$fileContent -replace '^\+\+([^+]+)$' , '##$1'
        $fileContent=$fileContent -replace '^\+\+\+([^+]+)$' , '###$1'
        $fileContent=$fileContent -replace '^\+\+\+([^+]+)$' , '####$1'

        $UTF8woBOM = New-Object "System.Text.UTF8Encoding" -ArgumentList @($false)
        [System.IO.File]::WriteAllLines((Join-Path $tgtDir"\textile\" $file), @($fileContent), $UTF8woBOM)
    }

注意点

powershellでの変換時に失敗した点

Out-Fileでファイルを出力するとBOM付UTF8になる

当初はデータの出力を以下のように行っていた。

Out-File $tgtDir"\textile\" $file -Encode UTF8

しかし、この書き方で出力したファイルをRedmineで書込を行うと、1行目のh1.タグが正しく認識されなかった。
ファイルを確認したところ、行頭にU+FEFFが埋め込まれており、send_keysで送り込まれてしまっていたようだった。

タブを変換しておく

Pukiwikiから出力したRawデータにはタブが含まれているが、これの置換を行わないと、Redmineにsend_keysした際にタブオーダーが移動してしまう。

Redmineへの登録

あとは出力されたファイルをループしながらSeleniumで書込を行うだけ、00年台のレガシーなWEBアプリも10年代の便利な仕組みでガンガン移行する。

from selenium import webdriver
from selenium.webdriver import Chrome, ChromeOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.select import Select
import os
from dateutil.relativedelta import relativedelta

# 対象ファイル一覧の取得
tgtdir ="C:/wiki/textile/"
files = os.listdir(tgtdir)
# Driverの指定
drvpath="C:/selenium/webdriver/chromedriver.exe"
driver = webdriver.Chrome(drvpath)
# ログイン
driver.get("http://localhost/redmine/login")
driver.find_element_by_id("username").send_keys("myname")
driver.find_element_by_id("password").send_keys("mypassword")
driver.find_element_by_id("password").submit()
for f in files:
    #本文のタイトル=ファイル名の取得
    title = f.replace('.txt','')
    #本文の取得
    txtdata = open(tgtdir+f,'r',encoding="utf-8")
    wikibody = txtdata.read()

    # wiki新規作成ページへアクセス
    driver.get("http://localhost/redmine/projects/projectname/wiki/new")
    # タイトルを入力
    elem = driver.find_element_by_id("page_title")
    elem.send_keys(title)
    elem.submit()
    # コンテンツを展開
    elem = driver.find_element_by_id("content_text")
    elem.clear()
    elem.send_keys(wikibody)
    driver.find_element_by_name("commit").click()
driver.quit()


最終確認

この一連の手順ではわかっているだけで以下の移行が行われていないので、あとは目視でチェックする。

  • テーブル記法の変換
  • 画像の登録
  • ページ内リンク