Author Archive

    はてなブックマーク - PHPでのAmazonAPIの使い方
    このエントリーをはてなブックマークに追加

    3度目のアドベントカレンダーという、まさかの誕生日プレゼントをもらってしまいました・・・。
    小さいころの夢はお母さんを冥王星につれていくことだった、本日誕生日の萩原です。
    (bitshiftersの皆さん、昨日はありがとうございました。)

    アドベントカレンダーよりもっと別のプレゼントください。

    PHPでのAPI使い方の紹介

    さて、最近AmazonAPIを使って商品検索をする機会がありましたので、その使い方を簡単に紹介したいと思います。

    まずはじめにAmazonから自分のアクセスキーとシークレットキーを取得してきます。

    後は、実際にコードを。
    私はCakePHP使いなのでPHPを使って商品情報を取得します。
    前々回先頭のCを小文字にしてしまったら弊社小山から苦情が来ました・・・すみません・・・

    $access_key_id = 'アクセスキー';
    $secret_access_key = 'シークレットキー';
    // RFC3986 形式で URL エンコードする関数
    function urlencode_rfc3986($str) {
    return str_replace('%7E', '~', rawurlencode($str));
    }
    // 基本的なリクエストを作成します
    $baseurl = 'http://ecs.amazonaws.jp/onca/xml';
    $params = array();
    $params['Service'] = 'AWSECommerceService';
    $params['AWSAccessKeyId'] = $access_key_id;
    $params['Version'] = '2009-03-31'; //←バージョンを入れてください。
    $params['Operation'] = 'ItemSearch'; // ← ItemSearch オペレーションの例
    $params['SearchIndex'] = 'All';
    $params['Keywords'] = $word; // ← 検索ワード
    $params['ItemPage'] = $page;
    // Timestamp パラメータを追加します
    // - 時間の表記は ISO8601 形式、タイムゾーンは UTC(GMT)
    $params['Timestamp'] = gmdate('Y-m-d\TH:i:s\Z');
    // パラメータの順序を昇順に並び替えます
    ksort($params);
    // canonical string を作成します
    $canonical_string = '';
    foreach ($params as $k => $v) {
    $canonical_string .= '&'.urlencode_rfc3986($k).'='.urlencode_rfc3986($v);
    }
    $canonical_string = substr($canonical_string, 1);
    // 署名を作成します
    // - 規定の文字列フォーマットを作成
    // - HMAC-SHA256 を計算
    // - BASE64 エンコード
    $parsed_url = parse_url($baseurl);
    $string_to_sign = "GET\n{$parsed_url['host']}\n{$parsed_url['path']}\n{$canonical_string}";
    $signature = base64_encode(hash_hmac('sha256', $string_to_sign, $secret_access_key, true));
    // URL を作成します
    // - リクエストの末尾に署名を追加
    $url = $baseurl.'?'.$canonical_string.'&Signature='.urlencode_rfc3986($signature);
    //XMLで情報を取得。
    $xml = @simplexml_load_file($url);

     

    注意する点

    まず、一度に取得できる商品の件数は10件固定です。
    一度に飛ばせるリクエストの数は2件までなのでまとめて20件は表示することが可能です。

    私は今回5件ずつ取得したかったので、10件取得して前後5件ずつに分けることで対応しました。
    ちょっと無駄にデータを取ってきてしまうのが気にはなりましたけどね。

    次に、開発は基本皆さん仮想環境で開発を行っていると思います。
    その際、時間がずれていることがよくあるかと思いますが、時間がずれすぎているとAmazonからアクセスを拒否されます。
    多分10~15分くらいずれていると検索できません。
    私は取りあえずの対応で、cronで5分ごとに時間を合わせることで対応しました。(正確に合わせる必要はなかったので)

    後は、xmlを取得する際、エラー回避することを忘れないようにしましょう。
    エラーが出てしまうと、XMLの取得に使用するURLがそのまま出てしまうのですが、上記を見てもらえたらわかるとおりURLにはそのままアクセスキーとシークレットキーが書いてあります。ですので、エラーが出たら即情報が漏れてしまいます。

    今回は、デモでやっているのでとりあえず”@”をつけています。

    まとめ

    今回、こういったAPIを利用することは初めてだったので色々苦労しました。
    よくあることとは思いますが、Amazonに条件を投げて帰ってくるパターンは変えられないので、そのなかで自分がほしい情報に編集するのが少々面倒でした。
    また、XMLをいじることも初めてでしたし、javascriptでも苦労したことがあったのですが、これに関してはまた機会があれば。

    毎度おなじみどうでもいい化学豆知識

    炭素原子が三重結合までしかできないのは皆さん(多分)ご存知かと思いますが、タングステンやクロムなどは四重結合をすることがあります。
    まぁ、だからなんだと言われても困るんですけど。

    それでは、また。

      はてなブックマーク - PHPExcelとReviserの比較(後編)
      このエントリーをはてなブックマークに追加

      まさかの1日明けでアドベントカレンダーの順番が回ってきました。
      生まれ変わって元素になるなら、アルミニウムになりたい
      ・・・という設定らしい1年目の新人、萩原です。

      さて、前回はPHPExcelとReviserの機能について比較を行いました。
      機能としてReviserも十分な機能を持ち合わせていますが、PHPExcelの方が優れているという結論でした。

      スピードの比較

      さて、実際に運用していく上でスピードは重要なポイントだと思います。
      ファイルダウンロードに時間がかかってしまってはストレスもたまりますしね。
      というわけで、今日は、スピードについて検証していくことにします。

      今回、クリックしてからダウンロードを開始する直前までの時間を測定しています。
      ソースにmicrotime(‘now’)を埋め込んでいる&virtualBox上のCentOSなので時間自体は正確ではない(というか倍くらい時間がかかっている)ですが、相対的な値としては問題ないです。

      20回ずつ測定をして平均を取っているので比較としては十分かと思われます。

      まずは、何も書きこまれていないテンプレートに何も入力せずそのまま出力した結果です。
      参考までにPHPExcelでのExcel5形式出力も一緒に載せています。

      Reviser
      平均値:0.033(s)
      標準偏差:0.016

      PHPExcel(.xlsx)
      平均値:0.123(s)
      標準偏差:0.011

      PHPExcel(.xls)
      平均値:0.223(s)
      標準偏差:0.039

      かなり差がでましたね。
      ただ、Reviserと比べてPHPExcelの方が標準偏差が小さく安定はしているのかなという印象です。

      続いてテンプレートに横15、縦600すべてのセルに’test’と入力した状態で何も入力せずにそのまま出力した結果です。

      Reviser
      平均値:0.911(s)
      標準偏差:0.113

      PHPExcel(.xlsx)
      平均値:2.508(s)
      標準偏差:0.080

      PHPExcel(.xls)
      平均値:2.483(s)
      標準偏差:0.027

      こちらも差がでましたね。

      次に何も入力されていない空のテンプレートに横10、縦1000すべてのセルに’test’と入力して出力した結果です。
      ここからはPHPExcelのExcel5形式での出力は行っていません。

      Reviser
      平均値:0.871(s)
      標準偏差:0.026

      PHPExcel(.xlsx)
      平均値:2.798(s)
      標準偏差:0.034

      こちらも時間はPHPExcelの方が時間がかかっています。
      この辺りで20回測定するのが面倒になってきてちょっと後悔を始めました・・・。

      最後に上の条件にさらに該当セル全てに色と左右上下の罫線を引いてみました。

      Reviser
      平均値:0.873(s)
      標準偏差:0.049

      PHPExcel
      平均値:73.269(s)

      ・・・タイプミスじゃないですよ。。。100倍くらい差が出ましたよ。
      CentOS内部で73秒平均なのですが、多分3,4分くらいかかってる気がしないでもない・・・
      因みにPHPExcelは20回やる気力が流石になかったので(無駄だし)5回しか測定してません。

      罫線と色のどちらに時間がかかっているかと思って色をつけずに出力させてみたところ40.981(s)かかりました。

      どっちもどっちといったところですかね。

      まとめ

      というわけで2回にわたってReviserとPHPExcelの比較を行ってきました。
      ReviserとPHPExcel、どちらも長所短所あると思います。

      色や罫線がある場合ちょっと使用に耐えられないレベルだという結果に見えますが、そうではないと思います。
      例えば色をつけることについても全てのセルに色や罫線をつけるわけではないし、PHPExcelは個別に指定できますが、Reviserはテンプレートを準備しないといけません。
      極端な話セルのパターンが100パターンあればReviserならあらかじめ100パターンのテンプレートセルを準備する必要があるという問題点があります。
      また、xlsx形式はPHPExcelしか使えません。

      機能的な面で見ればやはり、PHPExcelの方が優れていると思います。

      まぁ一方で流石に何分もダウンロードに時間がかかってしまっては困るという面もあります。
      Excelの出力はPHPExcelにしてもReviserにしてもかなりメモリを食いますので他の作業を並行して行うことが難しいです。
      (両者ともini_set(“memory_limit” , -1);をつけている理由ですね。これを記述していないとまともに動かせません。)

      現に私がPHPExcelで作ったもの(社内システムですが)は長いものは出力に5分ほどかかりますし、使いどころが難しいですね。

      個人的には基本的にはReviserだと思いますが、xlsx形式を使いたい場合、Excel2007関数をどうしても使いたい場合など、PHPExcelでないと機能が実現できない場合も出てくると思います。

      最後に役に立たない化学豆知識を

      空気中に2番目に多く存在している、酸素
      実は常磁性、つまり磁石に引っ付くってこと、ご存知でしたか?
      実際、液体酸素を流しているところに磁石を近づけると流れの向きが変わります。

      それでは。

        はてなブックマーク - PHPExcelとReviserの比較(前編)
        このエントリーをはてなブックマークに追加

        好きな元素はイッテルビウム(元素記号:Yb)
        ・・・という設定になっているらしい1年目の新人、萩原です。よろしくお願いします。
        大学院では化学を専攻しておりました。

        今回アドベントカレンダーということで順番が回ってきましたのでExcelについて触れていこうと思います。

        普段、CakePHPを使って仕事をしているのですが、その中でPHPでエクセルを出力すると言う場面によく出くわします。

        弊社ではExcelの出力には、基本的にReviserを使用しているのですが、たまたまPHPexcelを使う機会もありましたので、今回、これら二つのPHP用のExcel出力機能について比較を行っていきたいと思います。

        両者ともに、基本的にPHP5.2以上対応となっています。

        PHP5.1でも使用することは可能ですが、PHPExcelの場合はExcel2007形式(.xlsx)の出力ができません。(体験済)
        Reviserに至っては現在最新の0.33は動きません。(体験済)
        私の開発環境(PHP5.1.6、CentOS5.5)では0.24であれば動くことを確認しています。

        まぁそういった制限された環境で比較をしても仕方ないので、今回、勉強という意味も含めてPHP5.3.3を使用して比較を行いました。

        機能の比較

        機能において、PHPExcelとReviserの両者の一番大きな差は扱えるExcelの種類です。
        PHPExcelはExcel2007(.xlsx)形式に対応しています。Excel5形式(.xls)形式も扱うことは可能ですが、こちらの方は色などに少々バグがあります。(体験済)
        Reviserは.xlsx形式を扱うことはできません。.xlsのみの対応となっています。

        数式については現在両方とも扱うことが可能です。
        しかし、古いReviserを使用すると数式が扱えないものがあるので注意が必要です。
        (上記に示した0.24は数式に対応していません。)

        色や罫線も両方とも使用が可能ですが、使い方は大きく異なります。
        PHPExcelは直接指定のセルに色や罫線を引くことが可能です。
        一方、Reviserですが、直接指定をすることはできません。
        かわりに指定したセルから情報をコピーして使用します。
        指定したセル部分は後で削除することができるので、PHPExcelと出来ることは同等ということになります。

        その他の特徴はPHPExcelはテンプレートのファイルがなくても出力をすることが可能ですが、Reviserはテンプレートファイルがないと出力することができません。

        両者ともできないことはマクロの作成、出力です。
        テンプレートファイルにマクロが含まれていた場合、私が見た限りだと、PHPExcelはマクロの後らしきものが一応出力されますが、クリック等しても反応しません。

        Reviserの場合はマクロ自体が完全に削除される形になります。

        ソースの書き方はPHPExcelよりReviserの方が簡単に書くことができます。

        書き方の一例

        PHPexcel

        ini_set("memory_limit" , -1);
        set_time_limit(0);
        $this->layout = false;
        Configure::write('debug', 0);
        // 必要なクラスをインクルードする
        set_include_path(get_include_path() . PATH_SEPARATOR . "./Classes/");
        include APP . "vendors/phpexcel/Classes/PHPExcel.php";
        include APP . "vendors/phpexcel/Classes/PHPExcel/IOFactory.php";
        // PHPExcelオブジェクトを生成する
        $objReader = PHPExcel_IOFactory::createReader("Excel2007");
        $objPHPExcel = $objReader->load(APP . "vendors/templates/templete.xlsx");
        $objPHPExcel->setActiveSheetIndex(0);
        $sheet = $objPHPExcel->getActiveSheet();
        //シート名
        $sheet->setTitle('sheet_name');
        //セルA2に文章入力
        $sheet->setCellValueByColumnAndRow(0, 1, 'PHPExcel');
        //セルに罫線を引く
        $sheet->getStyleByColumnAndRow(0, 1)->getBorders()->getTop()->setBorderStyle(
        PHPExcel_Style_Border::BORDER_THIN);
        $sheet->getStyleByColumnAndRow(1, 1)->getBorders()->getLeft()->setBorderStyle(
        PHPExcel_Style_Border::BORDER_MEDIUM);
        //背景色の指定
        $sheet->getStyleByColumnAndRow(0, 1)->getFill()->setFillType(PHPExcel_Style_Fill::FILL_SOLID);
        $sheet->getStyleByColumnAndRow(0, 1)->getFill()->getStartColor()->setRGB('336699');
        $target_filepath = TMP . "PHPExcel.xlsx"; //ファイル名生成
        $file_name = "PHPExcel.xlsx";
        $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, "Excel2007");
        //ファイルの保存
        $objWriter->save($target_filepath);
        $media_id = basename($file_name);
        //保存したファイルの出力
        $file = TMP . $media_id;
        $file_length = filesize($file);
        header("Content-Disposition: attachment; filename=$media_id");
        header("Content-Length:$file_length");
        header("Content-Type: application/octet-stream");
        readfile ($file);

        Reviser

        Configure::write('debug', 0);
        $this->layout = false;
        ini_set("memory_limit" , -1);
        set_time_limit(0);
        App::import('Vendor', 'reviser/reviser');
        $reviser = new Excel_Reviser();
        $reviser->setInternalCharset('utf-8');
        //1枚目のA1のセルデータを読み込んで1枚目のB1に文字を入力
        //引数7つは前から順にシート番号、縦(数字)、横(英語),入力文字,コピーするセルの縦(数字)、横(英語),シート番号
        $reviser->addString(0,0,1,'reviser',0,0,0);
        //1枚目のA1のセルデータを読み込んで1枚目のB3に数字を入力
        $reviser->addNumber(0,0,2,3,0,0,0);
        //1枚目のB4に数式を入力
        $reviser->addFormula(0,0,3,'A2+A3');
        $readfile = APP . 'vendors/templates/templete.xls';
        $outFile = 'reviser.xls';
        // 出力
        $reviser->reviseFile($readfile, $outFile);

        まぁ実際のところ、PHPExcelはそのままでは書くのが煩わしくなってくるので私はコンポーネントにして使用しました。
        reviserはそのままでも十分簡潔に書くことができると思います。

        ここまで機能について簡単にまとめてきました。
        機能についてみるとReviserも十分使用に耐えうるものはもっていますが、ReviserにできてPHPExcelにできないことはおそらくほとんどないと思われます。
        単純にExcel2007が使えるかどうかだけでも使用可能な関数などに差があります。

        長くなってきたので続きは次回に。

        最後に役に立たない化学豆知識を。

        今年正式に名前が発表されたコペルニシウム(Cn)という元素。
        原子番号は112番なのですが、この金属、実は常温で液体だと言われています。
        他に常温で液体の金属は水銀のみです。
        また、原子番号が100を超えるような元素は基本的に半減期が数秒程度のものがほとんどなのですが、Cnは半減期が数分程度という実験結果も出ています。

        それでは