プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

はてなブログに移行しました (2/2)

前の記事に引き続き、ここからは実際の移行作業について、メモを残したいと思います。

主な流れは、

Joomla! -> Wordpress -> はてなブログ

です。

以下、バージョン情報です。

  • Joomla! 3.6.2
  • Wordpress 4.5.3
  • FG Joomla to WordPress 3.15.3

Wordpress の立ち上げ

まず、Joomla!のコンテンツをWordpressに移行するため、Joomla!を運用しているのと同じサーバーでWordpressを立ち上げます。 森ソフトは、さくらインターネットで運用しているのですが、さくらインターネットのレンタルサーバーには、クイックインストールという機能があり、Wordpressはそちらで簡単にセットアップできるようです。

https://help.sakura.ad.jp/app/answers/detail/a_id/2319#ac02help.sakura.ad.jp

手順通りにすれば、問題なくWordpressが立ち上がりました。

Joomla! サイトのコンテンツをWordpressに移行

次は、Wordpressの管理画面に入り、『プラグイン』から『新規追加』を選択します。プラグインの検索で、『FG Joomla to Wordpress』を探すと、すぐに見つかります。

f:id:junichim:20160826101110p:plain

問題なくインストールができれば、プラグインを有効にします。 プラグインが有効になったら、『プラグイン』→『FG Joomla to WordPress』の『import』を選択して、インポートを開始します。

インポート作業は、画面に従ってオプションを指定するだけです。 Joomla!のサイトおよびデータベースへの接続情報を正しく入力しておきます。『Test the database connection』を実行して正しく接続できることを確認しておいてください。

その他のオプションとしては、

  • Automatic removal : チェックを入れる(インポート前のコンテンツをすべて削除するため)
  • Import introtext : to the content を選択
  • Archived post : not imported を選択
  • Medias : Force media import. Keep unchecked except if you had previously some media download issues. : チェックを入れる

としました(他はデフォルトだったはずです)。

これで準備ができましたので、『Start/Resume the import』ボタンを押すとインポートが始まります。 問題なくインポートが完了したら、画面の一番下にある『Modify internal links』ボタンを実行して、内部リンクを更新しておきます。

画像もインポートしてくれるんで、非常にありがたいです。

なお、このプラグインを利用した際に、若干注意するべき点がありました。こちらにまとめてありますので、気になる方はお読みください。

Wordpress のコンテンツをはてなブログにインポート

さて、無事にJoomla!のコンテンツをWordpressにインポートできれば、次は、Wordpressのコンテンツをエクスポートします。 管理画面から『ツール』→『エクスポート』とすすみ、『すべてのコンテンツ』を選択して、『エクスポートファイルをダウンロード』とすると、コンテンツの内容がファイルにエクスポートされます。あ、エクスポート前に、不要な記事やカテゴリ・タグなどがあれば、消しておきます。

次に、エクスポートしたファイルを、はてなブログ側の『インポート』で指定すれば、記事のインポートは完了です!インポートの形式として、WordPress形式を指定してください。 はてなの場合、記事にインポートに続き、画像のインポートをしてくれます。これは、インポート元のサイトから画像のURLを使って、記事内の画像をすべてコピーして、はてなフォトライフに保存してくれるというものです。これは素晴らしいですね!

なお、この際、下記の点に気を付けてください。

  • 元サイトにアクセスできないと画像のインポートができません
  • 一度インポート後、インポートをやり直したい時があると思います。そのとき、『インポートの削除』を実行すると、記事は削除されますが、画像は削除されません。なので、引き続き同じサイトからインポートすると同じ画像が保存されることになります。

後者のような場合は、再インポート前に、一旦、はてなフォトライフに移り、インポートした画像を手作業で削除したほうが良いかもしれません。なお、はてなフォトライフ側には、『使用中の画像をチェックする』とか『未使用の画像をチェックする』のような機能はないので、あとから作業しようとすると結構大変そうな予感がしました。

これで、基本的にはインポートができるのですが、残念ながら、これですべて完了とはなりません。 いくつかの点については、手作業で対応する必要があります。今回の移行作業で行った部分を以下に書いておきます。

SyntaxHighLighterの導入

元々、コードの表示には、SyntaxHighlighterを利用した、Joomla!のプラグインを使っていました。はてなブログのシンタックスハイライト機能を使ってもよかったのですが、既存の記事に対する修正が不要になるので、Syntax Highlighter を使うことにしました。

Syntax Highlighter の使い方は、ネットを調べるといくつか出てきます。

はてなblogでsyntaxhighlighter.autoloaderをつかってC#ソースコードをきれいに表示させる方法 - kaz16a's blog

SyntaxHighlighterのautoloaderの使い方 Ver 3.0 | Asterlist

はてなブログの場合、『デザイン』を開き、『カスタマイズ』(スパナの画像)タブを選択し、『サイドバー』を選択します。 『モジュールを追加』をクリックし、『HTML』を選択します。その内部に、Syntax Highlighter を使うための設定を記述します。 今回は下記の様な、Autoloaderを使う設定にしています。

<!-- Syntax HighLighter -->
<link href="https://xxx.example.com/syntaxhighlighter/styles/shCore.css" rel="stylesheet" type="text/css" />
<link href="https://xxx.example.com/syntaxhighlighter/styles/shThemeDefault.css" rel="stylesheet" type="text/css" />
<script src="https://xxx.example.com/syntaxhighlighter/scripts/shCore.js" type="text/javascript"></script>
<script src="https://xxx.example.com/syntaxhighlighter/scripts/shAutoloader.js" type="text/javascript"></script>
<script type="text/javascript">
function path()
    {
        var args = arguments,
            result = []
            ;
             
        for(var i = 0; i < args.length; i++)
            result.push(args[i].replace('@', 'http://xxx.example.com/syntaxhighlighter/scripts/'));
             
        return result
      };
       
      SyntaxHighlighter.autoloader.apply(null, path(
        'applescript            @shBrushAppleScript.js',
        'actionscript3 as3      @shBrushAS3.js',
        'bash shell             @shBrushBash.js',
        'coldfusion cf          @shBrushColdFusion.js',
        'cpp c                  @shBrushCpp.js',
        'c# c-sharp csharp      @shBrushCSharp.js',
        'css                    @shBrushCss.js',
        'delphi pascal pas      @shBrushDelphi.js',
        'diff patch             @shBrushDiff.js',
        'erl erlang             @shBrushErlang.js',
        'groovy                 @shBrushGroovy.js',
        'java                   @shBrushJava.js',
        'jfx javafx             @shBrushJavaFX.js',
        'js jscript javascript  @shBrushJScript.js',
        'perl pl                @shBrushPerl.js',
        'php                    @shBrushPhp.js',
        'text plain             @shBrushPlain.js',
        'ps powershell          @shBrushPowerShell.js',
        'py python              @shBrushPython.js',
        'ruby rails ror rb      @shBrushRuby.js',
        'sass scss              @shBrushSass.js',
        'scala                  @shBrushScala.js',
        'sql                    @shBrushSql.js',
        'vb vbnet               @shBrushVb.js',
        'xml xhtml xslt html    @shBrushXml.js'
      ));
      SyntaxHighlighter.all();
</script>

なお、jsファイルやcssは自分が利用可能な適当なサーバーに配置するのがおすすめです。ちなみに、

http://alexgorbatchev.com/SyntaxHighlighter/hosting.html

を見ると、公式にホストされたものもありますが、きっと負荷も高いでしょうからあくまでもご参考までに。 これで、コードのハイライト表示は完了です。

画像以外のファイル置き場

はてなブログですが、画像は、はてなフォトライフに保存されますが、それ以外のソースコードのファイルやその他各種のファイルは、アップロードすることができません。

調べてみると、はてなブログのproであれば、はてなダイアリープラスが利用でき、そちらに任意のファイルをアップロードする機能があるので、それを使うことも可能です。

はてなブログでファイルをアップロードする方法 - ブログ鯖人

ですが、ちょっと試してみましたが、なんとなくいまいち。要は、はてなダイアリーはアップロード先としてだけ使いたくて、公開する必要もないのですが、公開設定にしないとリンク先が正しく表示されません。 まあ、元々の目的が違うんでしょうね、きっと。

ということで、dropboxに公開用のファイルを保存しておき、共有リンクでダウンロード可能としました。 なお、dropboxに置いたファイルをscript等で使う場合(.jsファイルを読み込むとか)は、リンクURLのパラメータでdl=1を与えるように変更します。

共有された Dropbox リンクのダウンロードを強制する | Dropbox ヘルプ

このようにしないとダウンロードが始まらないため、scriptファイル等を読み込めなくなります。

内部リンクの修正

さて、実はこれが一番手間がかかりました。 はてなブログでは、Wordpressのコンテンツのインポートはしてくれるのですが、同一サイト内の記事間の内部リンクの修正はやってくれません。そのため、ある記事内で別の記事を参照していたりすると、すべてインポート元(この場合は、Wordpressのサイト)を指してしまいます。

まあ、昔の記事で修正する意味がどれだけあるかは難しいところですが、一応過去の資産と考えて、修正しました。

一応、リンク切れについては、

リンクチェッカー(リンク切れチェックツール) dead-link-checker.com

などを使ってチェックできるので、これでエラーになった箇所で、かつインポート元を指しているものについて、一つずつ確認して、手作業での手直しになりました。

※本当は、一旦、はてなブログにインポートして、記事のURLがどう変化するかを把握して、Wordpressからエクスポートしたxmlファイルをスクリプトで処理するほうがいいんだと思いますが、今回は力技に逃げました。

URLの自動リンクを停止

はてなブログでは、URLが書かれていると、自動でリンクを張ってくれます。 通常は非常に便利なのですが、これが邪魔になるときもあります。

通常のURLの場合

通常の場合の自動リンクの抑制方法は、下記にあるように、URLの前後を [] で囲めばよいようです。

はてなブログ ヘルプ

https://hapilaki.hateblo.jp/entry/no-auto-linkhapilaki.hateblo.jp

preタグ内の場合

Syntax Highlighterを使っていると、preタグ内にURLを記述する、という場面が多く出てくると思います。 何もしなければ、このpreタグ内のURLに対しても、リンクが張られてしまいます。ま、それが正しく表示されれば別にいいのですが、preタグ内のためか、<a href="・・・ なんて、文字列が見えるので、いただけません。 また、preタグ内のため、前述の [] を使った方法も正しく動作しません。

この場合の回避方法も、すでに確立されているようで、

はてなブログでSyntaxHighlighterを利用する時は「data-unlink」をお忘れなく - altere5's blog

にあるように、data-unlink 属性を追記すれば、避けることができるそうです。

mimeTex を復活

はてなブログでは、LaTeX 記法による数式表示が使えるようです。 森ソフトのサイトでは、Joomla!のアップデートに伴い、mimeTexのプラグインが使えなくなっていたので、はてなブログ用の記法を使って書き直しました。 とはいっても、記事1つだけなんですけどね。

終わりに

ここまでやれば、移行作業はほぼ終わりです。たぶん、新しいブログを運用していくと、改善しないといけない点も出てくるでしょうが、とりあえずOKとします。 しばらく様子をみて、問題なさそうなら、元サイトの記事のクローズとリダイレクト設定を行いたいと思います。

(参考)FG Joomla to Wordpress 使用上の注意点について

改行文字

普通にインポートすると、preタグ内のコードが1文につながってしまうという問題がありました。 Joomla! 側のデータベースで、記事本文を格納しているのが、 (prefix)_content テーブルの introtext カラムでしたので、これらの手掛かりに、該当部分を探すと、

        public function process_content($content, $post_media) {

            if ( !empty($content) ) {
                $content = str_replace(array("\r", "\n"), array('', ' '), $content);
                                                                                                                                                              
                // Replace page breaks
                $content = preg_replace("#<hr([^>]*?)class=\"system-pagebreak\"(.*?)/>#", "<!--nextpage-->", $content);
                                                                                                                                                              
                // Replace media URLs with the new URLs
                $content = $this->process_content_media_links($content, $post_media);

                // Replace audio and video links
                $content = $this->process_audio_video_links($content);
                                                                                                                                                              
                // For importing backslashes
                $content = addslashes($content);
            }                                                                                                                                                 
                                                                                                                                                              
            return $content;
        }

となっており、改行コードを空白で置き換えていることがわかります。

今回の場合、Wordpressのコンテンツとして扱う分に、何か支障があるかもしれませんが、最終的にはてなブログで思ったように取り込めればよいと考え、かなり乱暴ですが、この部分の処理をコメントアウトしてからインポート処理を行うことで、preタグ内のコードがすべてつながってしまうという事態を避けることができました。

画像ファイルコピー失敗時の原因調査について

最初、FG Joomla to WordPress を使ってインポートしようとしたら、記事のインポートは問題なかったのですが、画像のインポートにことごとく失敗していました。 こんな感じのエラーメッセージが出ていました。

f:id:junichim:20160826224705p:plain

結局のところ原因は、作業をしていたサイトが、特定のIPアドレスからの接続のみを受け付ける設定となっており、自分自身のIPでの接続を許可していなかったためでした。

この原因の探り方を参考に書いておきます。 まず、

https://wordpress.org/support/topic/plugin-fg-joomla-to-wordpress-media-does-not-copy

にあるように、copy関数呼び出しでエラーメッセージが抑制されていそうなので、これを知りたいと思い、該当部分を探すと、今回使ったバージョンだと、

wp-content/plugins/fg-joomla-to-wordpress/admin/class-fg-joomla-to-wordpress-admin.php

の1813行に、

if ( ! @$this->remote_copy($old_filename, $new_full_filename) ) {
    $error = error_get_last();
    $error_message = $error['message'];
    $this->display_admin_error("Can't copy $old_filename to $new_full_filename : $error_message");
    return false;
}                                                                                                                                                 

という記述があり、コピー時のエラーメッセージが抑制されていました。 これを、

if ( ! $this->remote_copy($old_filename, $new_full_filename) ) {

のようにエラー解除すると、エラーメッセージとエラーの発生行を知ることができます。

今回の場合は、エラー発生時に表示された該当行付近を見ると、

            $response = wp_remote_get($url, array(
                'timeout'     => $this->plugin_options['timeout'],
            )); // Uses WordPress HTTP API
                                                                                                                                                              
            if ( is_wp_error($response) ) {                                                                                                                   
                trigger_error($response->get_error_message(), E_USER_WARNING);
                return false;
            } elseif ( $response['response']['code'] != 200 ) {
                trigger_error($response['response']['message'], E_USER_WARNING);
                return false;
            } else {                                                                                                                                          
                file_put_contents($path, wp_remote_retrieve_body($response));
                return true;
            }

となっており、レスポンスステータスが200以外(若干のデバッグ文も加えたところ、403でした)となっているが判明し、そこから、IPアドレスを制限していることを思い出しました。

ご参考までに。