Author Archives: susumuis

About susumuis

メイドカフェによく居るWebエンジニア

WordPressに持ってきてしまった、はてなキーワードリンクを解除しました(XMLRPC + wordpress-javaを使用)

前回 はてなダイアリーから持ってきたはてなダイアリーの記事がはてなキーワードリンクを含んでしまっているので、解除するためにスクリプト組むと宣言していました。
今日そのためのスクリプトを書いてリンク解除に成功したので報告します。

変換方法

WordPressのXMLRPC機能を使ってAPI経由でデータ変換をしました。

イメージとしては一つ一つのページを手で開いて、エディタに記事を貼り付けて正規表現置換して保存を繰り返すのと同じです。

この方法のメリットは

  • インターネットに繋がっていればどの端末からも実行できる
  • 履歴データまでは置換しない(WordPressは記事を変更した履歴を保持しています)
  • 変更履歴が残る(その気になればいつでも変換前に戻せる)

デメリットは

  • 前記事分の通信が発生する
  • APIの仕様を調べなければならない
  • APIを有効にしなければならない

当初SQL一本流して変換しようとしましたがMySQLは正規表現で文字列置換をすることができないらしく、それならPHPでスクリプトを組もうとも思ったのですが、DB直接操作するより外部から触ったほうが安全だと考え、API方式を選択しました。

WordPressのAPIはXMLRPC方式と、AtomPub方式の二種類提供されていますが、後者はデフォルトで無効になっていたり、日本語の情報が皆無に近く、XMLRPC方式の場合は、もう少し状況がマシなようで、 wordpress-java というJavaクライアントライブラリもありましたので、今回はこちらを使用しました。

変換プログラム全文

public class App {
    static String user = "******";
    static String pass = "****************";
    static String url = "*************/xmlrpc.php";

    public static void main(String[] args) throws MalformedURLException, XmlRpcFault {
        WordPress wp = new WordPress(user, pass, url);
        List<Page> recentPosts = wp.getRecentPosts(1000);
        Pattern pattern = Pattern.compile("<a class=\"keyword\" href=\"[^\"]+\">([^<]+)</a>");
        for (Page page : recentPosts) {
            String contents = page.getDescription();
            if (contents.contains("keyword")) {
                Matcher m = pattern.matcher(page.getDescription());
                System.out.println(page.getPermaLink());
                while (m.find()) {
                    System.out.println("\t\t" + m.group(1) + "\t" + m.group());
                    contents = contents.replace(m.group(), m.group(1));
                }
                page.setDescription(contents);
                System.out.println("\tsaved status = " + page.getPost_status());
                wp.editPost(page.getPostid(), page, page.getPost_status());
            }
        }
    }
}

実行結果はこんなかんじです。

http://www.susumuis.info/entry/2014/03/31/103829
        コンストラクタ <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%B9%A5%C8%A5%E9%A5%AF%A5%BF">コンストラクタ</a>
        インスタンス  <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>
        API <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>
        hoge    <a class="keyword" href="http://d.hatena.ne.jp/keyword/hoge">hoge</a>
        コンストラクタ <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%B9%A5%C8%A5%E9%A5%AF%A5%BF">コンストラクタ</a>
        インスタンス  <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>
        インスタンス  <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>
        コンストラクタ <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%B9%A5%C8%A5%E9%A5%AF%A5%BF">コンストラクタ</a>
        インスタンス  <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>
        インスタンス  <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>
        インスタンス  <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>
        Java5   <a class="keyword" href="http://d.hatena.ne.jp/keyword/Java5">Java5</a>
        インスタンス  <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>
        GC  <a class="keyword" href="http://d.hatena.ne.jp/keyword/GC">GC</a>
    saved status = publish
http://www.susumuis.info/entry/2014/03/30/004202
        Mayaa   <a class="keyword" href="http://d.hatena.ne.jp/keyword/Mayaa">Mayaa</a>
続く...

キーワードの変遷を見ると当時どんなことに注目していたのか見られて面白いです。

実行後、変換された記事のリビジョンが1増加しています。差分を表示すると、たしかにキーワードの箇所のみ置換されています。

キーワードだけ置換されている

プログラム解説

解説するまでもない短いプログラムですが、正規表現によって検索をし、置換のところは正規表現を使わずに完全一致で置換しています。こうすることで、どこが変わったのかログに出力することができます。

contents = contents.replace(m.group(), m.group(1));

の部分は記事本文をまるごと置換しているのでメモリ効率の点で言えば有利ではありません。が、以前業務で作った変換ツールはこの方式でトータル数十万行のファイル群を平気で置換できてしまっていたのでこの程度気にするほどではないでしょう。ただし、件数によっては時間がかかるかもしれません。

wp.editPost(page.getPostid(), page, page.getPost_status());

の部分は第三パラメータがJavaDocで

String pubulish : publish status

となっていて、それ以上の説明がありません。WordPressのAPIの仕様書を見てもよくわからなかったので、当てずっぽうでprivateまたはpublicを返すpost.getPost_status()にしたら、うまくいきました。

newPostの場合はbooleanなので、この辺り統一性がないなと思いました。

キーワードリンクの是非について

自分がはてなブログ内にいたら、キーワード被リンクでSEO効果もあったかもしれませんが、はてな外にいますからその恩恵はありません。じゃあ、はてなブログを使用しているならどうかといえば、最近の検索エンジンは外部リンクが多すぎることに対して厳しくなってきていますから、その効果も今はどれほどなのかとも思います。

ユーザーとしてページを見ると、リンクが多すぎるとうるさい感じがしますし、キーワードリンクをクリックして便利だと思ったことはあまりありません。分からない語句があったらはてな内を探すより「ぐぐる」のが自然だと思います。

今後はてなキーワードが終了したり、使用が変わったりすると、外部のブログからのキーワードリンクは全部リンク切れになってしまいますから、引っ越してきたサイトでキーワードリンクが残ってしまっている状況は百害あって一利なしと思います。

実行にJavaが必要ではありますが、同じ状況の方がいらっしゃったら使っていただいて構いません。ただし、事前にバックアップを取るなど自己責任にてお願いします。MySQLのバックアップは

mysqldump -u ユーザー名 -p DB名 > ファイル名.dump

にて取れます (^^;

はてなブログからWordPressに移行するためにしたこと

ほっとくと忘れてしまいそうなので、忘れないうちに、記録残そうと思います。

はてなブログから、WordPressへ結構苦労して移行しました。その時やったことをざっと書きたいと思います。

記事の移行

はてなブログ用ツールで記事データの取得

定番ですが、下記のツールを利用しました。
はてなブログ用ツール

.NETで作られているのでWindowsかMonoの環境が必要です。MacもMono環境を整えればできるかもしれないと書いてましたが、Windowsマシン持ってきてやってしまいました。

はてなのAPIを使用しているらしいので、それなら、自分もAPI使ってもいいんですが、せっかくあるツールが使えるなら、やっぱ楽さには叶いません。

このツールでデータをエクスポートしたものは、完全ではありません。次の問題点があります。

  • コメントが含まれない
  • 画像などがはてなフォトライフのままである
  • シンタックスハイライトなどの装飾が一部崩れている

はてなダイアリーのエクスポート機能を使用

はてなブログにはエクスポート機能がありませんが、はてなダイアリーにはあります。はてなブログに移行する前ははてなダイアリーを使っていて、はてなダイアリー時代が大半だったので、はてなダイアリーにログインすることではてなダイアリー時代のデータを抜くことは出来ました。

方法は下記の記事と同じです。

はてなダイアリーからWordPressへ全記事を移行した件 | ツインズパパの徒然日記 Ver.2

上記記事にも書いてあるとおり、次の問題点があります。

  • はてなキーワードのリンクもそのまま持ってきてしまう
  • 一部の記事の日付が1970年になってしまう

    • →これは、時刻 00時代のAMがうまく取り込めないという問題。リンク先や、その方が参考にされたサイトでは01時に変更することで対処されていましたが、僕の場合はAM自体を取り除いたらうまくいきました。
  • シンタックスハイライトがガタガタ
  • 画像がはてなフォトラ(ry
  • なぜか一部の記事がうまく移行できないで画面が真っ白になった(すごい大昔の記事)

RSSからインポート

はてなブログはRSSも配信しています。そしてWordPressは公式でRSSからインポートすることができます。しかし、これは、.NETのツールの下位互換でした。

  • 新着7件しか取ってこれない
  • コメントデータを取ってこれない

結局どうしたか

  • はてなダイアリー時代の記事のうち、真っ白にならなかったものは、はてなダイアリーで移行
  • はてなブログ時代の記事ははてなブログで移行
  • はてなブログ時代のコメントは、3件しかなかったので手でSQLを発行して移行:
insert into
    wp_comments (
        comment_post_ID,
        comment_author,
        comment_author_url,
        comment_date,
        comment_date_gmt,
        comment_content,
        comment_karma,
        comment_approved,
        comment_parent,
        user_id

    ) values (
        614,
        'susumuis',
        'http://www.susumuis.info/',
        '2014-03-30',
        '2014-03-30',
        'id:faith_and_braveさん コメントありがとうございます。 共感いただいて本当に嬉しいです。 自分は開発(省略)',
        0, 1, 0, 1
    )

こんな感じです。コマンドラインツールでのSQLの発行はキツイし、phpMyAdminのような「クラックしてください」と言ってるようなツールは使いたくなかったので、このツールを使いました。SSHトンネルの設定もやってくれるので便利でした。

Sequel Pro

はてなキーワード持ってきてしまった件についてはSQLに正規表現書いて変換しようとしましたが、MySQLは正規表現を使った置換ができないそうなので、PHPなどの言語で外から変換するしかないようです。まだ出来ていませんので後日できたら報告します。

検索結果のindexとか「いいね」カウントとか

検索エンジンのインデックスについては、301リダイレクトで対処するのが王道ですが、これは、

はてなダイアリー → はてなブログ → 独自ドメイン(はてなブログPro)

を公式移行ツールで移行してきたのでシームレスにやってくれていました。なので、あとは、はてなブログProで使っていた独自ドメインのURLそのままで記事のURLを移行するだけです。

WordPressにはパーマリンク機能というのがあって、記事のURLを

http://www.example.jp/?p=123
のようにクエリーパラメータにするのではなく、
http://www.example.jp/2014/06/28/sample-post/
のような任意のURLにすることができます。

ここで、移行前のURLは次の形式になっていました。

はてなブログ時代

http://ドメイン/entry/yyyy/mm/dd/数字6桁
例:
http://www.susumuis.info/entry/2014/06/11/222935

はてなダイアリー時代

http://ドメイン/entry/yyyymmdd/p数字
http://ドメイン/entry/yyyymmdd/数字10桁
http://ドメイン/entry/yyyymmdd/任意の単語
例:
http://www.susumuis.info/entry/20110728/p1
http://www.susumuis.info/entry/20090822/1252377609

見事に分かれています。それなら、共通する、「/entry/2014」の部分 + 投稿名として「06/11/XXXXXX」を書くようにしようとしましたがこれはできません。

"/"という文字が投稿名に使用できなかったためです。

結局どうしたかというと、 Enhanced Custom Permalinksというプラグインのお世話になりました。これを使えば記事ごとにパーマリンクを設定できます。

さて、記事の数は90くらいありますので、全部手でやってたら大変ですから、こいつは、SQLで一括で設定してしまいました。

当時のクエリを残していなかったので、正確なものを紹介できませんが、wp_postmetaテーブルをinsertしていく形になります。

単なる301ではなく、URLを同一にしたため、はてなスター、Facebookいいねまでそのまま引き継ぐことが出来ました!

はてなブックマーク、はてブコメント

ところが、はてなブックマークについてはうまく行きませんでした。はてなブックマークもURLに紐づく情報なので、てっきりブログをそのまま移行すれば、独自ドメインでブックマークが引き継がれると思っていました。確かに移行直後はそうだったのですが、移行後数時間後、はてなブックマークカウントが0になっていました。

なんでかなあと思ってみたところ、はてなブログProの管理画面を見たら理由がわかりました。

独自ドメインは解除されている!

はてなブログは、定期的にドメインが有効かどうかクロールしているようです。ドメインがきちんとはてなのDNSに向いていることがわかった時点で、元のはてなブログのURLから独自ドメインのURLにリダイレクトしているようです。

ドメインが無効、または別のサーバーを向いていると判断されると、はてなブログのドメインから独自ドメインへの転送がストップします。それと同時に、はてなブックマークのデータも、元のはてなブログのドメインのものに変換され、独自ドメインのカウントは、0になります。はてなブログとして独自ドメインで受けたはてなブックマークカウントも、一緒にはてなブログドメインに持って行かれてしまいます。

はてなブックマークははてなのものだから仕方がないですね。

人気エントリー一覧

人気エントリーの一覧は、元のはてなブログドメインのものをはてなブックマークブログパーツを使用すれば作成できます。このままだとリンク先がはてなブログになってしまうので、リンク先をJavaScriptで強引に書き換えてしまいました。右サイドバーの「以前反響を頂いた記事」という部分です。具体的にはこんな感じです。

jQuery('div#hatena_hotentry').on('DOMNodeInserted', function() {
  $links = jQuery('div#hatena_hotentry .hatena-bookmark-entrytitle');
  $links.each(function() {
    jQuery(this).attr('href', jQuery(this).attr('href').replace('susumuis.hateblo.jp', 'www.susumuis.info'))
  });
});

こんなことして怒られたらやめます。wwもう、この段階で欲しいのは過去のはてなブックマークじゃなくて、この記事がオススメだよっていうことなので、僕の方で勝手にレコメンドしちゃえばいいんです。

ブックマークコメント

はてなブックマークコメントはどうしましょう。最近はブログのコメント機能を使ってのコメントより、はてなブックマークコメントで暑いコメントをもらったりします。

はてブコメントがないと、過去盛り上がった記事もなんか寂しい感じですね。ただ、個人的には、はてなブックマークに対しては歓迎的でない部分もあって、何かと炎上しやすいなど、攻撃的なこと書く人がたまにいます。

コメントなのか、個人のメモなのかわからないしろものですから、今後、ブログの雰囲気的を良くしていくためにはない方が良いかもしれません。

ということで、過去の記事まで追跡して、はてブコメントを画面に出すのはやめました。ただ、僕のブログのなかで、はてブ2桁頂いた記事が6件だけあったのでそれらについては記事の下に手動で旧ドメインでのブックマークリンクを記載しました。こんなかんじです。

この記事は以前多くのブックマーク・コメントを頂きました。
<a href="http://b.hatena.ne.jp/entry/http://susumuis.hateblo.jp/entry/20110728/p1" class="hatena-bookmark-button" data-hatena-bookmark-layout="simple-balloon" title="以前のURLでのブックマーク件数"></a>
これからブックマークされる方はこちら↓

Markdown記法を使えるようにする

WordPressにはMarkdownを使えるようにするプラグインが複数存在します。いろいろ試しましたが僕はこのプラグインが使いやすいと思いました。

WP Markdown Live

コードのインデントとシンタックスハイライト

はてなダイアリーやはてなブログから記事をインポートした結果、残念なこととして、ソースコードのインデントやシンタックスハイライトがガタガタになってしまったことがありました。

これについては、幸いWP Markdown LiveプラグインがGitHub風のプログラムコード記法を持っているので、テキスト化されたコードからもう一度自前でインデントしてMarkdownに貼り直すことにしました。全部だと大変だから一部だけです。

これだとシンタックスハイライトがつきませんがWP Markdown Liveで出力したコードは

<pre class=" language-css">
<code class=" language-css" data-language="css">

コード

</code>
</pre>

(*うまくコードをテキスト化してくれないので、最初のpだけ全角文字にしています)
のように出力されます。これはそのまま prism.jsが使用できます。

テーマのスタイルシートにダウンロードしてきたprism.cssとjsを配置するだけで、綺麗にシンタックスハイライトすることができました。

SEOとかOGPとかTwitter連携とか

まだまだやらなきゃいけないことはたくさんありますが、だんだん面倒くさくなってきてしまったので、これらはプラグインでお茶をにごしました。
余力があったらプラグインを使わずに自力で連携したいです。

使ったプラグイン
* Jetpack by WordPress.com
* WP Open Graph
* WP Social Bookmarking Light

Jetpack使ってるあたりが負けてる感がするので、早急に自力でなんとかしたいです。

SEOのメタタグの部分はしっくり来るプラグインが見つからなかったので自分でheader.phpにスクリプト書きました。

5年後の未来を予想すること

というつぶやきをしたら、結構反響がよかったので、ついつい「昔は〜」というおじいちゃん的発言繰り返してしまいました。

というわけで未来の話をします。

未来の話といえば、2009年の暮か2010年の年明け頃に、勤務先の上司に

君の視点で、5年後のWebの世界を語って欲しい

と言われたので、僕なりに考察し、長文メールをその上司に送りました。概要は次のとおりです。

  • AWSは既存のシステムとの互換性を捨てきれず、Googleのクラウド技術に潰される
  • 今みんなクラウドとか言ってるけど、Web技術の進化はこれで最後だ、この先はエンジニアが不要になる
  • GoogleはWebの世界を支配するが、WebエンジニアはWebを離れ、宇宙、ロボット、人工知能などに注目し始める。10年後にはWebはレガシーになる

結果、起きたことは

  • スマートフォン、タブレット、モバイル通信の普及
  • ソーシャルゲームブームとエンジニアの流動性の加速
  • Webの多様化、レスポンシブル
  • SPAなどのWebシステムのフロントの近代化
  • AWSは滅びるどころかクラウド業界のリーダー的存在、GoogleはGCEなどを出したが追う存在
  • Webエンジニア、Webデザイナー増える

おめでとう!大外しになります。

なんでこうなったかといえば、上流を見ていなかったからに尽きるわけですが、
+ Webは今の使われ方がゴールである
+ よって、この形を効率よく提供する仕組みを整える方向に技術は向かう
+ それはすぐに整う。その結果、技術的課題はなくなる
という短絡的発想ですね。

実際はどうだったのでしょう。経済産業省が出している、次の資料を見てみましょう。

電子商取引に関する市場調査の結果を取りまとめました(METI/経済産業省)

冒頭「EC化率」という数字があります。EC化率とは、小売の流通総額のうち、どれくらいの割合がECによって流通したのかを表すものだそうです。今のEC業界はわかりやすく言うと、下記の記事に書かれている世界なのだそうです。

EC化率 - 100個中3個のリンゴしかECで売れていない

マーケターは知っておきたい!今後のEC市場の市場規模と他産業との比較、今後の有望セクターについて | マーケティング・パートナーのコーポレートブログ

ざっくり言うと、日本のEC化率は世界と比べるとまだまだ低いし、日本の個人消費は300兆円規模なのだから、ものすごい大きな可能性があるということです。

ソシャゲみたいな一過性のものだけじゃなくて、生活必需品みたいなものもどんどんEC化すれば、もっともっと産業規模が大きくなる。そのためにはもっとエンジニアは必要だし、マーケターは必要だし、技術の進化が求められているというわけです。

そのためにはパソコンが昔のままでは困るわけです。もっと簡単で、もっと安くて、もっと性能が良くなければならない。通信も速くなければならない、肩がこる目にやさしくないUIとか、ウィルスやフィッシングの被害にあう脅威とかなくさなければなりません。だから、フロント技術やデバイスの進化は止まらないわけです。。。

僕自身はエンジニアとして、マーケティングに無頓着であったことを反省しました。

そんなわけで、今度未来を語る折には、視野を広げて時代の動きを見極めながら、それと技術とを関連付けて未来を考えていきたいと思います。