skyblues のすべての投稿

iTunes Search API を利用しアプリのカスタマーレビューを表示する

iTunes Store Web Service Search API

  • iTunes Store Web Service Search API という API が Apple から公開されています。これを使うと、iTunes Store で取り扱われているすべてのアイテム(ミュージック、映画、Podcast、アプリ)を検索することができます。またドキュメント化されていない隠しAPIとして、カスタマーレビューを取得するインターフェースも存在します。

    先日 Nike+ Running アプリが改悪になった記事で、このアプリのカスタマーレビューを表示したく調査してみました。
    このiTunes カスタマーレビューのインターフェースですが、RSSフィードとして取得できます。ただし最大取得件数が50件までという制約がありますが、通常は新着50件を表示できれば問題はないですよね!

    [cc] XML形式
    https://itunes.apple.com/jp/rss/customerreviews/id=/xml

    JSON形式
    https://itunes.apple.com/jp/rss/customerreviews/id=/json
    [/cc]

iTunes Search API と Google Feed API のカスタマーレビュー取得方式

  • ご存じのようにJavaScriptのクロスドメイン制約上、JavaScriptのみで他のサイトのWebサービスから情報を取得する場合、XmlHttpRequestオブジェクトはクロスドメインを許可しないため、JSON形式であればJSONPを使用するのが基本ですね。XML形式(RSS)の場合は、Googleが提供するGoogle Feed APIを使用するか、別途XMLを取得するサーバサイドスクリプトやプロキシサーバが必要になるかと思います。取得形式を含め、たすき掛けしますと全部で4パターンになります!
  • No. 取得方式 形式 処理
    1 iTunes Search API JSON JSONPを使用し、JSON形式のデータを直接取得し表示できる。ただしデータに登録日時(updated)項目が含まれていない。
    2 iTunes Search API XML XML形式はiTunes Search APIが提供する全項目データが取得できる。ただしクロスドメインの制約上、XmlHttpRequestだけではXML形式のデータは取得できない。別途XMLファイルを取得するサーバサイドスクリプトが必要となる。JavaScriptは取得したXMLファイルを表示する処理のみとなる。またプロキシサーバという方法もある。
    3 iTunes Search API + Google Feed API JSON Google Feed APIを使用しiTunes Search APIへはXML形式でロード後、JSON形式のデータを取得できる。ただしJSON形式の場合、Google Feed APIのJSONフォーマットに丸められるため、星5段階評価(im:rating)項目が削られてしまい取得できない。
    4 iTunes Search API + Google Feed API XML Google Feed APIを使用しXML形式(RSS)のデータを取得できる。iTunes Search APIが提供する全項目データを取得できる。

取得方式別データ抜粋

  • ○No.1 iTunes Search API – JSON形式
    [cc] “entry”:[
    {
    “author”:{
    “uri”:{
    “label”:”https://itunes.apple.com/jp/reviews/id123456789″
    },
    “name”:{
    “label”:”内木 蘭”
    },
    “label”:””
    },
    “im:version”:{
    “label”:”4.6.2″
    },
    “im:rating”:{
    “label”:”1″
    },
    “id”:{
    “label”:”1234567890″
    },
    “title”:{
    “label”:”アップデートで改悪”
    },
    “content”:{
    “label”:”音楽停止でワークアウトが停止しません。”,
    “attributes”:{
    “type”:”text”
    }
    },
    “link”:{
    “attributes”:{
    “rel”:”related”,
    “href”:”https://itunes.apple.com/jp/review?id=387771637&type=Purple%20Software”
    }
    },
    “im:voteSum”:{
    “label”:”0″
    },
    “im:contentType”:{
    “attributes”:{
    “term”:”Application”,
    “label”:”アプリケーション”
    }
    },
    “im:voteCount”:{
    “label”:”0″
    }
    },
    [/cc]
  • ○No.2 iTunes Search API – XML形式
    [cc]
    2014-11-11T11:11:00-07:00
    1234567890
    アップデートで改悪
    音楽停止でワークアウトが停止しません。

    0
    0
    1
    4.6.2
    内木 蘭https://itunes.apple.com/jp/reviews/id123456789
    <table border="0" width="100%">
    <tr>
    <td>
    <table border="0" width="100%" cellspacing="0" cellpadding="0">
    <tr valign="top" align="left">
    <td width="100%">
    <b><a href="https://itunes.apple.com/jp/app/nike+-running/id387771637?mt=8&uo=2">アップデートで改悪</a></b><br/>
    <font size="2" face="Helvetica,Arial,Geneva,Swiss,SunSans-Regular">
    </font>
    </td>
    </tr>
    </table>
    </td>
    </tr>
    <tr>
    <td>
    <font size="2" face="Helvetica,Arial,Geneva,Swiss,SunSans-Regular"><br/>音楽停止でワークアウトが停止しません。</font><br/>
    </td>
    </tr>
    </table>


    [/cc]
  • ○No.3 iTunes Search API + Google Feed API – JSON形式
    [cc] “entries”: [
    {
    “author”: “内木 蘭”,
    “categories”: [],
    “content”: ”

    アップデートで改悪

    音楽停止でワークアウトが停止しません。

    “,
    “contentSnippet”: ”
    …”,
    “link”: “”,
    “publishedDate”: “Tue, 11 Nov 2014 11:11:00 -0800”,
    “title”: “アップデートで改悪”
    },
    [/cc]

  • ○No.4 iTunes Search API + Google Feed API – XML形式
    [cc]
    アップデートで改悪
    内木 蘭
    https://itunes.apple.com/jp/reviews/id123456789
    内木 蘭

    1234567890

    <table border=”0″ width=”100%”>
    <tr>
    <td>
    <table border=”0″ width=”100%” cellspacing=”0″ cellpadding=”0″>
    <tr valign=”top” align=”left”>
    <td width=”100%”>
    <b><a href=”https://itunes.apple.com/jp/app/nike+-running/id387771637?mt=8&uo=2″>アップデートで改悪</a></b><br/>
    <font size=”2″ face=”Helvetica,Arial,Geneva,Swiss,SunSans-Regular”>
    </font>
    </td>
    </tr>
    </table>
    </td>
    </tr>
    <tr>
    <td>
    <font size=”2″ face=”Helvetica,Arial,Geneva,Swiss,SunSans-Regular”><br/>音楽停止でワークアウトが停止しません。</font><br/>
    </td>
    </tr>
    </table>


    0
    0
    1
    4.6.2
    内木 蘭
    2014-11-11T11:11:00-07:00

    [/cc]

No.4 iTunes Search API + Google Feed API XML形式

  • 方式No.1, 3は実装中にJSONデータの項目が足りないことに気づき断念。結局、No.4での実装となりました。WordPressで本文中にPHPが書けるなら、No.2のPHPでXMLを取得してきて、どこかにXMLファイルを置くでもよいのですが、ファイルを置くというのも美しくないので、No.4となりました。
    本当はGoogle Feed APIを噛ませないで直接取得できるほうが、速度的にもベターなのですが、iTunes Search APIのJSON形式ですと、なぜか登録日時(updated)項目が削られてしまうんですよね。この項目さえ入ってくればJSONPで取得でき、方式的にも実装的にも美しいのですが。「登録日時ぐらい削ってしまえっ!」という乱暴な選択肢もあるのですが、技術屋的にそれはちょっと・・・ですね(笑)

  • WordPressの仕様上、jQueryの$()省略構文は書けないため、jQueryとしています。
    また23,24行目も、記事本文にblock系のHTMLタグを記述すると自動改行されてしまうため、JavaScriptが正常に動作しません。そのため、エスケープしたHTMLを戻す処理を加えていますが、WordPressでなければそのままHTMLタグを記述してよいと思います。まあそのうち自動改行や改行が<p>タグに変換されない施策も考えたいですね。

No.2 iTunes Search API XML形式

  • しばらく運用していますと、iTunes Search API カスタマーレビューサービス(RSS)がよく落ちることが判明。落ちると言ってもサーバが落ちるわけではなく、応答はするのですが、正常にデータが送信されてこないiTunes側のサービス中断です。RSSだけに主に10:00、12:00頃の中断が多く中断時間も数十分にのぼり、このままですとお詫びのエラーメッセージの出現頻度が過多になりそうでしたので、方式を再検討することにしました。
    iTunesカスタマーサービス中断中は、直前まで正常に受信できていたデータを提供するようにする。すなわち、No.2のPHPでXMLを取得してきて、WordPressの適当なディレクトリにXMLファイルを保存し、そのXMLファイルでカスタマーサービスを表示するというものです。この方式であればサービス中断中は、その直前まで保存していたXMLファイルもといカスタマーレビューが表示され、エラーメッセージはまず表示されません。ファイルを保存するというあまり美しくない方式ですが、カスタマーレビューが表示されないほうが、100倍まずいですので、ここは基本のサービス提供を優先しました。どこかのアプリと違って(笑)当然ですね。
    逆にGoogle Feed APIを噛ませず、iTunes Search APIから直接取得できるので、Google Feed APIのオーバーヘッド分、カスタマーレビューの表示は速くなると思います。但しPHPでXMLファイルを取得しますので、その分オーバーヘッドは若干増えますが、トータルでは改善されると思います。

    • PHPにてXMLファイル取得し適当なディレクトリに保存します。これにはWordPress記事内でPHPコードが動作するようにしておく必要があります。
    • 取得したXMLファイルをAjaxで取得し表示します。表示処理はNo.4と変わりません。

このところ野球やサッカーの海外観戦記事ばかりでしたが、たまにはIT技術屋的な記事もですかね(笑)
でもメイン言語はPHPでもjQuery(JavaScript)でもなくJavaなんですよね。

関連記事を表示する WordPress プラグインを比較

投稿記事に関連する記事へのリンクが自動で表示されるプラグインはいくつかあるのですが、関連スコアによる紐づけとかアルゴリズムがいまいちなのか、なかなか意図した関連記事が表示されませんでした。
すでに記事数が数千件とか膨大なサイトですと自動もやむなしとは思いますが、普通は関連記事は手動で設定するものではないかと思ってます。ブロガーにしてもユーザにしても、関連記事というラベルで意図しないリンクが自動で表示されてもうれしくないですよね。人気記事とかレコメンド(おすすめ)とか関連のないラベルにしておけば問題はないですが、自動の場合はその精度ですね。

ということで、投稿記事に関連する記事へのリンク自動・手動で表示するプラグインをいくつか調査してみました。主に「手動で設定できる」という観点から調査しています。詳細まで深くは触れていませんので、もしかしたら誤認識があるかもしれません。その際はご指摘くださいませ。

  • ■WordPress関連記事プラグイン

    「相互リンク」機能を簡単に説明しますと、記事元に関連記事を登録するとリンク先記事にもリンク記事元が自動で登録され、相互リンクとなります。
    例えばA記事、B記事があるとします。A記事からB記事へ関連記事をリンク登録したとします。するとB記事には自動でA記事への関連記事が登録されます。
    サイト外(他人)へのリンクであれば拒否られてしまい一方通行ということもありますが、サイト内の記事であれば普通は相互リンクでよいはずですよね。

  • ■WordPress関連記事系プラグインの表示例
    記事:「なぜシンガポールチャンギ空港は搭乗ゲートで手荷物検査をするのか?」の関連記事の表示例。
    「WordPress Related Posts」と「Yet Another Related Posts」は自動で抽出された関連記事。
    「Related Posts for WordPress」「BAW Manual Related Posts」「Microkid’s related posts」「Custom Post Types Relationships (CPTR)」は手動で2件の関連記事を登録。
    (デザインはいかようにもできるので比較対象外)
  • ■総評
    各プラグインを調査した結果、すべてのブラグインが独自テーブル(データベース)を作成し、関連記事情報を保存していました。わざわざテーブルに保存しているのなら、相互リンク機能ぐらいは必須のように思います。その点ではMicrokid’s related postsですかね。私は相互リンクが欲しいのでこのプラグインを常用します。

    しかしここで、1つの疑問が。結局のところ手動の場合、リンクですので記事下段にリンクを記述すればよいだけなのではないか、果たしてテーブル(データベース)にまで関連を保存する必要があるのかという、話の骨を根本から折るような疑問が(汗)。

    例えば以下のようなショートコードを記述すれば、タイトルと組み合わせてリンクを自動作成するようなシンプルなプラグインでよいのではないかと思います。実際このようなプラグインが存在するかは不明ですが、相互リンクなしの手動設定ならこの程度で十分な気がします。私は記事投稿では「テキスト」を使用しますが、「ビジュアル」の使用あれば、ツールバーに「関連記事」を追加できる項目ができる程度でよい気がします。

関連記事を手動で設定できる Custom Post Types Relationships (CPTR) WordPress プラグイン

関連記事を手動で設定できるWordPressプラグインを調べているのですが、Microkid’s related postsに続き「Custom Post Types Relationships (CPTR)」プラグインをインストールしてみました。バージョンはV.2.4.1。


Custom Post Types Relationships (CPTR)のインストール

  1. プラグインのインストール
  2. 設定画面
  3. 関連記事登録画面
    こちらも、関連記事を記事編集画面から設定できます。UIは非常によくできていてそれほど戸惑うことはありません。
  4. 関連記事の表示
    このプラグインは関連記事を登録しても記事末尾にはリンク表示されません。関連記事を表示するには、記事に以下のショートコードを記述する必要があります。記事のどの箇所にも関連記事を表示できますが、関連記事は通常記事末尾でよいですし、手動で記述するのは二度手間ですね。またこちらは関連記事の相互リンク機能もありませんでした。
    ショートコードのオプション詳細はこちら
    [cc] [cptr excerpt=0] [/cc] 抜粋を表示するオプション「excerpt=1」にしますと、設定した最大文字数以上に出力されてしまうようです。(v2.4.1)
    [cc] [cptr excerpt=1 words=10] [/cc]


  5. しばらく使用してみますと、こちらもMicrokid’s related postsと同様で、関連記事登録画面での検索「Filter」が正しく動作していないことがわかりました(v.2.4.1)。またまたソースを斜め読みすることに。
    こちらは「Filter」の検索ボックスが存在するのに「Filter」機能自体が実装されていませんでした。
    「Filter」機能を有効にするには以下の「cptr.php」、「cptr.js」の2ファイルに手を入れる必要があります。

    ソースコードは以下です。

    • ■cptr.php の cptr_cats() 関数
      • function cptr_cats() {
        	$post_type   = $_POST['cptr_post_type'];
        	$postID  = $_POST['postID'];
        	$howMany = $_POST['howMany'];
        	$orderBy = $_POST['orderBy'];
        	$orderIn = $_POST['orderIn'];
        
         		$args = array(
         			'post_type' => $post_type,
         			'numberposts' => $howMany,
         			'post_status' => 'publish',
         			'orderby' => $orderBy,
         			'order' => $orderIn,
         			'post__not_in' => array($postID)
         		);
        
      • ↓↓↓ 162,170行目を追加 ↓↓↓
        function cptr_cats() {
        	$post_type   = $_POST['cptr_post_type'];
        	$postID  = $_POST['postID'];
        	$howMany = $_POST['howMany'];
        	$orderBy = $_POST['orderBy'];
        	$orderIn = $_POST['orderIn'];
        	$filtered = $_POST['filtered'];
        
         		$args = array(
         			'post_type' => $post_type,
         			'numberposts' => $howMany,
         			'post_status' => 'publish',
         			'orderby' => $orderBy,
         			'order' => $orderIn,
         			's' => $filtered,
         			'post__not_in' => array($postID)
         		);
        
      • diff確認
        % diff -u cptr.php.org cptr.php
        --- cptr.php.org        2014-08-04 21:49:22.000000000 +0900
        +++ cptr.php    2014-11-15 13:31:14.000000000 +0900
        @@ -159,6 +159,7 @@
                $howMany = $_POST['howMany'];
                $orderBy = $_POST['orderBy'];
                $orderIn = $_POST['orderIn'];
        +       $filtered = $_POST['filtered'];
        
                        $args = array(
                                'post_type' => $post_type,
        @@ -166,6 +167,7 @@
                                'post_status' => 'publish',
                                'orderby' => $orderBy,
                                'order' => $orderIn,
        +                       's' => $filtered,
                                'post__not_in' => array($postID)
                        );
        
    • ■cptr.js
      • 		$.ajax({
        			type: "post",
        			url: AjaxHandler.ajaxurl,
        			data: { action: 'cptr-cats', cptr_post_type: $('#posttype').val(), postID: $('#h_pid').val(), howMany: $('#howmany').val(), orderBy: $('#orderby').val(), orderIn: $('#orderin').val()  },
        
      • ↓↓↓ 28行目に以下を追加 ↓↓↓
        [cc width=”300px” highlight=”1″] , filtered: $(‘#filtered’).val()
        [/cc]
        		$.ajax({
        			type: "post",
        			url: AjaxHandler.ajaxurl,
        			data: { action: 'cptr-cats', cptr_post_type: $('#posttype').val(), postID: $('#h_pid').val(), howMany: $('#howmany').val(), orderBy: $('#orderby').val(), orderIn: $('#orderin').val(), filtered: $('#filtered').val()  },
        
      • diff確認
        % diff -u cptr.js.org cptr.js
        --- cptr.js.org 2014-08-04 21:49:22.000000000 +0900
        +++ cptr.js     2014-11-15 13:33:11.000000000 +0900
        @@ -25,7 +25,7 @@
                        $.ajax({
                                type: "post",
                                url: AjaxHandler.ajaxurl,
        -                       data: { action: 'cptr-cats', cptr_post_type: $('#posttype').val(), postID: $('#h_pid').val(), howMany: $('#howmany').val(), orderBy: $('#orderby').val(), orderIn: $('#orderin').val()  },
        +                       data: { action: 'cptr-cats', cptr_post_type: $('#posttype').val(), postID: $('#h_pid').val(), howMany: $('#howmany').val(), orderBy: $('#orderby').val(), orderIn: $('#orderin').val(), filtered: $('#filtered').val()  },
                                beforeSend: function() {$("#available-posts").html('Loading...');},
                                success: function(response){
                                        //dump the list with post from the category selected
        

日米野球 MLB v 侍ジャパン 第2戦@東京ドーム 観戦

今日は 日米野球 MLB v 侍ジャパン 第2戦を観戦のため東京ドームまで行ってきました。東京ドームはブラジルW杯から帰国翌週に行った以来ですから4カ月ぶりですかね!

今日の席は実質\1,000円で侍ジャパンの新ユニフォームが付いてくる特典付きチケット。\4,000円席+ユニ\1,000円なら若干ショボくても許せますね(笑)今日はアウェイなので濃紺(サムライネイビーと呼ぶらしい)ユニ。しかしベンチは一塁側なんですよね。

今日のコスプレはヤンキースJETERユニか、WBC2013侍ユニか迷いましたが、結局侍ジャパンユニでいざ出陣!

東京ドームに到着し、22ゲート前で新ユニフォーム(濃紺)を引き換えましたが、やっぱりショボい。ってかなりショボい。胸元のJAPANマーキングが印刷です(涙)。パチユニよりショボいんじゃ!?と思っていたら、新ユニからレプリカも昇華プリンタによる印刷になったんですね。内タグもミズノ株式会社になってます。ということはこれって本当にレプリカなのか!?もし同一品ならレプリカがショボいし高すぎ(\7,800円)ってことになるのですが、MIZUNO公式サイトの画像を見ますとレプリカのマーキングは刺繍っぽく見えるんですよね。
昔から胸元のマーキングは刺繍がいいと思っているオヤジ世代なので、印刷ですとなにかショボく感じてしまう。しかし選手からすればあのごわつき感がなくなるわけで、機能性からしたらよいのでしょうね!

4,000円席なので3塁側2階パノラマシート席。でも最前列なので非常に見やすかったです。

試合は先発MLBが岩隈、侍Jが金子、二人とも器用な投手対戦でプレーボール!今日はR・カノの球回しを見たかったのですが、あいにくのDH。試合は日本が小刻みにヒットを連ね、結局8-4で快勝!けがから復活の和田投手の登板時にはドーム全体が拍手喝さい。松田のホームランにも驚きましたが、次打席でまさかの敬遠で場内どよめき。メジャー側が敬遠とは(左左優先)。投手交代を見てもそれなりにMLBベンチの本気度が伝わってきました。それにしても個人的に松田はなにか長嶋さんを彷彿させるんですよね!あの空振りにしても(笑)魅せますから!入場者数42,277人。超満員ではないですが見る限りほぼ満員でした。

これで日米野球、侍J2連勝。やはり生観戦はいいね!このところ、ブラジルからサッカーにしても野球にしても全く勝ててなかったので久々の美酒となりました。

ヒーローインタビューは柳田。この人のバッティングフォームを生で見ましたがイチロー派ですね。前方に20cmもスウェーし、前の壁でボールを捉える非常に高度な打撃フォーム。ズバ抜けた動体視力とスイングスピードがないとなかなか真似できないフォームです。それだけに一歩歯車が狂うとスランプが長引く傾向にあるのですが、今日はリラックスして振れてましたね!

ヒーローインタビュー後になぜか小久保監督へ1,000万円贈呈セレモニー。どーなってんだ!?ってドームもドヨドヨ。チームへじゃないのかよって。これって小久保監督個人にですから税金も本人にかかるんですかね!?

って画像を見たら「勝利チーム賞」になってましたね!アナウンスの言いまわしに問題アリでした。

サッカーもホンジュラス戦は6-0で爆勝のようで。東京ドームでイニング間にスマホで速報を追ってました。6-0なら今日はレイトで録画見なくてもいいかなと(笑)

やはり、遠藤、長谷部、今野の大御所の参加は大きかったってことですかね!?まあブラジルショックを払拭できてよかったです!

21Uワールドカップも韓国に1-0で辛勝!ここまできたらぜひ初代栄冠をつかんでほしいです。

日米野球 侍ジャパン v MLB 第1戦 初勝利 侍J投手の品評会!!

日米野球、まずは開幕戦2-0で初勝利!小久保監督の表情も引き締まっていて非常によかったと思います。スポンサーのSUZUKIに感謝ですね!

まあ今大会って、MLBファレル監督の言う通り、さながら日本人投手の品評会ですね!前建、大谷はほぼ当確か!?

しかし、ファレル監督とフランコナ・コーチのやり取り、いろいろなんとなく面白いですね!トーリとマッティングリーみたいな!

WBC2013 AT&Tパークで、準決・決勝のドミニカ、R.カノのイニング間の球回しを見た時、改めてMLBの凄さを知った次第です。あのスローイングはマジで凄い。日本人にはマネできないですね。あのゆるいサイドスローの投げ方で、なんであそこまで投げられるのか!しばらく理解できませんでした。

私は、日本人選手がMLBに挑戦するのは、非常に良いことだと思ってます。張本さんには悪いですが。
選手である以上、最高峰のベースボールを見たい欲求はどの選手にもあるはずです。ここは野球もサッカーと同じでですね。投手だろうが、野手だろうがもっともっと海外に出て挑戦してほしい。力がなければ通用しない世界ですから。

台湾、タイ、韓国もよいと思いますね!オランダ、イタリアいいと思います。オランダはEUではなくキュラソーかな!
自分を必要としてくれている国に積極的に行くべきです。それが日本野球の良さを知らしめるわけですから。”野球”はもっともっとグローバル化すべきですね!