※2017/02/14コード修正しました。
以前、はてなブログのメール投稿機能をつかってWordPressとはてなブログを連携する記事を書きました。
www.wegirls.tech
これを使っているうちに、
「画像ちゃんと入れたい」
「編集したい」
とかの不満がたまってきたので模索していたときに、はてなブログAtomPubの存在を知ったので、使い方をメモ。
実装してみたけど、短時間でめちゃめちゃ便利なものになったので、最初からこっちを使っておけばよかったーー。
- はてなブログAtomPubとは?
- メール投稿ではなくて、はてなブログAtomPubを使うメリット
- AtomPubで、WordPress投稿時にはてなブログに同時投稿する(サンプルコード)
- 500エラーの対処法:PEAR::HTTP_Requestが使えなかった!
- できない!というときはXML Parse Error(パースエラー)かも
- はてなブログへ連携するときの注意点
- 連携先のはてなブログが1つの人は、こちらのコードをどうぞ
- 感想+WordPressおすすめ本
はてなブログAtomPubとは?
公式はこちら。
はてなブログAtomPub - Hatena Developer Center
- 記事の一覧を取得
- 記事を投稿
- 記事の編集、削除
などができる、便利なはてなブログのAPIです。ブログによってはxmlrpcをつかっているけど、はてなはAtomPubというタイプのAPIをつかっているので「はてなブログAtomPub」です。
メール投稿ではなくて、はてなブログAtomPubを使うメリット
(はよサンプルコード見たいんじゃ、という人は飛ばしてください。)
メリットその1:画像が何枚でも、指定した位置に入る
メール投稿と比べて、画像が(WordPressで)指定した通りの位置に、何枚でも入る!
メール投稿だと、本文中にimg
タグで画像を入れても、添付扱いになってしまい、
(画像を添付したときと同様)文頭にぽーんと入れておわり、となってしまうんです。
せっかく意識して選んだ画像がっ。
と悲しく思っていたのですが、AtomPubならそんなことありません。送信した内容そのまま反映されたので、文中に入れた画像も無事です。
(通常のはてなブログ投稿みたいに、はてなフォトにアップロードされるわけではないので、自サーバー削除してしまって画像が非表示になってしまった・・・とならないように注意してください。)
メリットその2:編集もできる
一度送信したものを編集・削除できる!!
(この記事では行っていませんが、同じAPIで可能です。)
メール投稿だと、一方的にはてなブログに送るのみで、追記したいときも編集ができません。
一度はてなブログに移動して、WordPressと同じようにちまちま直す・・・という手間がかかってしまっていました。
でも、このAPIなら編集・削除ができるものもあるので、記事投稿と組み合わせることでさらに便利になりそうです。
メリットその3:カテゴリもつけられる
WordPressでつけたカテゴリを、そのまま同じようにはてなブログにもつけられる!
これは嬉しいですね。カテゴリがあることで、SEO的にも良いことがありそうな気がします。
AtomPubで、WordPress投稿時にはてなブログに同時投稿する(サンプルコード)
はてなブログで、API keyを確認
はてなブログにログインし、投稿したいブログのAPI keyなどを確認します。
「設定」>「詳細設定」にある、API keyと、hatena_id、blog_idを使います。
WordPressに、連携用のコードを書く
/wp-content/themes/テーマ名/functions.php
の中身に以下を追記する。
ちなみに今回は、カテゴリで連携先を判別することで、複数のはてなブログに連携する、というようにしています。
※連携先のはてなブログを判別しなくてよい、1ブログだけしかない!というためのコードは、記事の最後にあります。
function send_hatena_api($post_id){ // WordPressの投稿内容を取得 $post = get_post($post_id); //カテゴリ取得して連携先を判別 $cats = get_the_category($post_id); $category = ""; // デフォルトは雑記用ブログへ $target = "life"; if(!empty($cats)){ foreach($cats as $cat){ $cat_name = $cat->cat_name; // 投稿用XMLを作成しておく $category .= '<category term="'.$cat_name.'" />'; // プログラミング のカテゴリがあれば、エンジニア用ブログへ if($cat_name == "プログラミング"){ $target = "engineer"; }elseif($cat_name == "アフィリエイト"){ // アフィリエイト のカテゴリがあれば、アフィリエイト用ブログへ $target = "affiliate"; } } } if($target == "life"){ $hatena_id = "bombomprin"; $blog_id = "wegirls.hatenablog.com"; //サブドメ以下までちゃんと書く $api_key = "APIキーをここに書きます"; $author = "らっこ"; //ブログ表示には反映されていない }elseif($target == "engineer"){ $hatena_id = "bombomprin"; $blog_id = "wegirls.hatenablog.com"; $api_key = "APIキーをここに書きます"; $author = "あじゃ"; }elseif($target == "affiliate"){ $hatena_id = "bombomprin"; $blog_id = "affirakko.hatenablog.com"; $api_key = "APIキーをここに書きます"; $author = "あふぃりさん"; } $subject = $post->post_title; // タイトルタグを変換 $search = array('<h7','/h7>','<h6','/h6>','<h5','/h5>','<h4','/h4>','<h3','/h3>','<h2','/h2>','/p>'); $replace = array('<h8','/h8>','<h7','/h7>','<h6','/h6>','<h5','/h5>','<h4','/h4>','<h3','/h3>','/p>'); $entrybody = mb_convert_encoding(htmlspecialchars(nl2br(str_replace($search,$replace,$post->post_content)),"UTF-8",auto)); //PEAR::HTTP_Requestを使う require_once("HTTP/Request.php"); $posturl = "https://blog.hatena.ne.jp/".$hatena_id."/".$blog_id."/atom/entry"; $created = date("Y-m-d\TH:i:s\Z"); //WSSE認証データをセット $nonce = pack('H*', sha1(md5(time()))); $pass = base64_encode(pack('H*', sha1($nonce.$created.$api_key))); $wsse = 'UsernameToken Username="'.$hatena_id.'", PasswordDigest="'.$pass.'", Created="'.$created.'", Nonce="'.base64_encode($nonce).'"'; // XMLデータを生成 // 下書きにしたい場合は <app:draft>の中身をyesにする $postdata = <<<EOF <?xml version="1.0" encoding="utf-8"?> <entry xmlns="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app"> <title>{$subject}</title> <author><name>{$author}</name></author> <content type="text/plain">{$body}</content> <updated>{$created}</updated> {$category} <app:control> <app:draft>no</app:draft> </app:control> </entry> EOF; //HTTP_Requestで投稿する $req = new HTTP_Request(); $req->addHeader('Accept','application/x.atom+xml, application/xml, text/xml, */*'); $req->addHeader('Authorization', 'WSSE profile="UsernameToken"'); $req->addHeader('X-WSSE',$wsse ); $req->addHeader('Content-Type', 'application/x.atom+xml'); $req->setMethod(HTTP_REQUEST_METHOD_POST); $req->setURL($posturl); $req->addRawPostData($postdata); $req->sendRequest(); return $req->getResponseBody(); //うまくいかない場合は、return...の行をコメントアウトして、 $req->getResponseBody(); の中身を見てみる } add_action( 'pending_to_private', 'send_hatena_api', 1 ,6);
*上記コードは、WordPressの記事ステータスが「レビュー待ち」から「非公開」になるときに自動連携されるようになっています。
変更したい場合は、こちらの記事を参考にしてください↓
WordPressの記事をはてなブログに自動で連携【メール投稿を使う】 - 女子WEBエンジニアのTechメモ
500エラーの対処法:PEAR::HTTP_Requestが使えなかった!
上記を実行したときに、500エラーになりました。。
原因は、HTTP_Requestをサーバーにインストールしていなかったから・・・
そりゃそうだーーー。゚(゚^ω^゚)゚。
というわけで、インストールしました。
CentOSにHTTP_Requestを(コマンドで)インストールする。
下記をコマンドラインに入力。
pear install HTTP_Request
実行結果はこんな感じでした。
[dev@myapp ~]# pear install HTTP_Request WARNING: "pear/HTTP_Request" is deprecated in favor of "pear/HTTP_Request2" WARNING: "pear/Net_URL" is deprecated in favor of "pear/Net_URL2" downloading HTTP_Request-1.4.4.tgz ... Starting to download HTTP_Request-1.4.4.tgz (17,233 bytes) ......done: 17,233 bytes downloading Net_URL-1.0.15.tgz ... Starting to download Net_URL-1.0.15.tgz (6,393 bytes) ...done: 6,393 bytes downloading Net_Socket-1.0.14.tgz ... Starting to download Net_Socket-1.0.14.tgz (5,655 bytes) ...done: 5,655 bytes install ok: channel://pear.php.net/Net_URL-1.0.15 install ok: channel://pear.php.net/Net_Socket-1.0.14 install ok: channel://pear.php.net/HTTP_Request-1.4.4
インストール後に再度実行すると・・・
動いたーー!!!
できない!というときはXML Parse Error(パースエラー)かも
そのほか、WordPressの投稿は問題なく動作しているのに、はてなブログに投稿されていない、というときは、XMLのパースエラーになっているかもしれません。
一番最後の行の、$req->getResponseBody();
の中身を見てみましょう。
var_dumpでもなんでもOKです。
わたしはここで、400 - XML Parse Errorとなってしまっていました。
投稿内容を「ほげほげ」とかに変えると正常に連携できるので、おそらくこれは文字の問題・・・。
HTMLタグが変換されているか再度確認
というわけで、HTMLタグを変換するhtmlspecialchars()
を追加しました。(サンプルコード内にはすでに入れています。)
文字コードはUTF-8になっている?
また、サンプルコード内に書いてはいますが、mb_convert_encoding()
で文字コードをUTF-8にしておきます。
はてなブログのAtomPubはUTF-8しか受け付けていないそうなのですが、
WordPressからの投稿だと、文字コードがShift-Jisになっていることがあるので要注意です。
はてなブログへ連携するときの注意点
タイトルタグの変換が必要
わたしは、WordPressで記事をかくとき、「見出し2」以降を使うようにしています。これは、htmlタグのH2に相当します。(テーマによって違うかも)
でも、はてなブログの大見出しは、H3なんですよね。
このように、記事内で使用されているタイトルタグが違うので、そのままWordPressの記事をはてなブログに送ってしまうと、はてなブログでデザインが崩れて表示されます。
それを避けるために、下記の部分で変換をしています。
// タイトルタグを変換 $search = array('<h7','/h7>','<h6','/h6>','<h5','/h5>','<h4','/h4>','<h3','/h3>','<h2','/h2>','/p>','><br />'); $replace = array('<h8','/h8>','<h7','/h7>','<h6','/h6>','<h5','/h5>','<h4','/h4>','<h3','/h3>','/p>','>'); $entrybody = mb_convert_encoding(htmlspecialchars(str_replace($search,$replace,nl2br($post->post_content)),"UTF-8",auto));
改行の変換が必要(nl2br)
WordPressの記事をそのまま反映すると、改行がはいらず、みっちりした見た目になってしまいます。
さっきの↑の部分で、ついでにnl2br()
をいれているのは、WordPressのビジュアルエディタで挿入した改行を、はてなブログにも反映させるためです。
連携先のはてなブログが1つの人は、こちらのコードをどうぞ
function send_hatena_api($post_id){ // WordPressの投稿内容を取得 $post = get_post($post_id); $hatena_id = "bombomprin"; $blog_id = "affirakko.hatenablog.com"; $api_key = "APIキーをここに書きます"; $author = "あふぃりさん"; $subject = $post->post_title; // タイトルタグを変換 $search = array('<h7','/h7>','<h6','/h6>','<h5','/h5>','<h4','/h4>','<h3','/h3>','<h2','/h2>','/p>','><br />'); $replace = array('<h8','/h8>','<h7','/h7>','<h6','/h6>','<h5','/h5>','<h4','/h4>','<h3','/h3>','/p>','>'); $body = htmlspecialchars("[:contents]<br>".str_replace($search,$replace,nl2br($post->post_content))); //PEAR::HTTP_Requestを使う require_once("HTTP/Request.php"); $posturl = "https://blog.hatena.ne.jp/".$hatena_id."/".$blog_id."/atom/entry"; $created = date("Y-m-d\TH:i:s\Z"); //WSSE認証データをセット $nonce = pack('H*', sha1(md5(time()))); $pass = base64_encode(pack('H*', sha1($nonce.$created.$api_key))); $wsse = 'UsernameToken Username="'.$hatena_id.'", PasswordDigest="'.$pass.'", Created="'.$created.'", Nonce="'.base64_encode($nonce).'"'; // XMLデータを生成 // 下書きにしたい場合は <app:draft>の中身をyesにする $postdata = <<<EOF <?xml version="1.0" encoding="utf-8"?> <entry xmlns="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app"> <title>{$subject}</title> <author><name>{$author}</name></author> <content type="text/plain">{$body}</content> <updated>{$created}</updated> {$category} <app:control> <app:draft>no</app:draft> </app:control> </entry> EOF; //HTTP_Requestで投稿する $req = new HTTP_Request(); $req->addHeader('Accept','application/x.atom+xml, application/xml, text/xml, */*'); $req->addHeader('Authorization', 'WSSE profile="UsernameToken"'); $req->addHeader('X-WSSE',$wsse ); $req->addHeader('Content-Type', 'application/x.atom+xml'); $req->setMethod(HTTP_REQUEST_METHOD_POST); $req->setURL($posturl); $req->addRawPostData($postdata); $req->sendRequest(); return $req->getResponseBody(); } add_action( 'pending_to_private', 'send_hatena_api', 1 ,6);
感想+WordPressおすすめ本
次は編集もできるようにバージョンアップしたい。
主要なブログサービスはなにかしら更新・投稿のためのAPIが用意されてるみたいなので、触ってみたいなー。
エンジニアだと意外と馴染みがうすいWordPressですが、改修とか構築とか結構要望のあるものなので、触ったことない人はこのあたりの本がおすすめです。↓

エンジニアのためのWordPress開発入門 (Engineer's Library)
- 作者: 野島祐慈,菱川拓郎,杉田知至,細谷崇,枢木くっくる
- 出版社/メーカー: 技術評論社
- 発売日: 2017/01/26
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る

- 作者: 相原知栄子,大曲仁,プライム・ストラテジー株式会社
- 出版社/メーカー: 翔泳社
- 発売日: 2016/04/09
- メディア: 大型本
- この商品を含むブログを見る