【PHP】WebサービスのAPIを使ってCSVファイルを作ってみた!
2015/12/30
久々にPHPのネタでも書こうかと。 PHPとってもここ最近いろんなWebサービスから提供されているAPIというものがあります。
このAPIを利用すると自分のサイトやブログにそのWebサービスの一部を利用できたりします。今回はPHPでもWebサービスを利用してみました。
下記に今回説明する為のサンプルを作成しました。
目次
利用するWebサービスは?
さて、まずそんなWebサービスのAPIを使うか選択しないといけないのですが今回はリクルートWEBサービスから提供されているエイビーロードのAPIを利用して各国のツアーの情報を自分のサイトに表示させつつ、CSVファイルをダウンロードできるようにしてみました。
注意点として、リクルートWEBサービスを利用するにはAPIを利用するために必要なAPIキーを取得する必要があるので、新規登録をしてAPIキーを取得しておきましょう。
また今回はエイビーロードのAPIの中で「海外旅行検索API」を使って掲載中のツアー情報を取得することにします。
APIでどんなデータが見れるか試してみる
ツアー情報を取得するデータを取得するには
するとXML形式でツアー情報のデータが見れると思います。大抵のWebサービスはこういったリクエストURLというのが必要になってきます。
ただこのままでは使えないので、そのXMLを表示しているアドレスバーを見ると下記のように表示されているはずです。
1 |
http://webservice.recruit.co.jp/ab-road/tour/v1/?key=sample&area=EUR |
注目していただきたいのは「key=sample」の部分に取得したAPIキーを記入して「area=EUR」の箇所に取得したいエリアを入力します。サンプルだと「EUR」なのでヨーロッパになります。
APIにリクエストURLを渡してJSONデータを取得する
サンプルのXMLのデータを見れたら今度は自分の欲しいデータを準備するのですが、今回は国ごとのツアーの情報を最大20件までjSON形式のファイルを取得するという流れにします。
JSON形式で取得するには?
JSON形式のデータを取得するには、リクエストURLに「&format=json」を追加します。
1 |
http://webservice.recruit.co.jp/ab-road/tour/v1/?key=自分のAPIキー&format=json |
国ごとのツアーデータを取得するには!?
JSON形式のデータを取得するには、リクエストURLに「&country=国コード」を追加します。たとえばインドの場合、国コードは「IN」になるのでリスエスとURLは下記になります。
1 |
http://webservice.recruit.co.jp/ab-road/tour/v1/?key=自分のAPIキー&format=json&country=IN |
取得するデータの数を指定するには?
欲しいデータが20件だけでいいという場合もあると思います。その場合は「&count=20」という項目を追加してください。
1 |
http://webservice.recruit.co.jp/ab-road/tour/v1/?key=自分のAPIキー&format=json&country=IN&count=20 |
国コードはどうやって知るの?
国コードですが、海外旅行検索APIのXMLファイルに「country」という項目があります。その中の「code」という項目が国コードになります。
1 2 3 4 5 |
<country> GB <name>イギリス</name> <name_en>UNITED KINGDOM</name_en> </country> |
ただエリア名やツアーの情報など見づらいと思うので、その場合は「国マスタAPI」という項目でエリアごとの国一覧取得や、国名での検索も可能なのでデータがスッキリしています。
ただあくまでサンプルですので、表示されてる国コードが少ないです。その場合は、実際に取得したAPIキーを入力することでたくさん国コードを取得できます。
1 |
http://webservice.recruit.co.jp/ab-road/country/v1/?key=自分のAPIキー |
上記のURLに自分のAPIを入力すればたくさん取得できるので、知りたい国コードを調べてください。
実際にPHPでの流れ
リクエストURLでデータを取得する流れを書きましたが、今度は実際にPHPでWebサービスを利用していく流れを説明します。全体の流れとしては下記のようにしました。
- タイ、シンガポール、インドでデータが欲しい国にチェックを入れて「ツアーデータを取得」ボタンを押す
- ボタンをクリックしたらその国のリクエストURLを作成してJSONファイルを取得する
- 準備しておいたCSVを開く。今回はリクエストを投げることにCSVファイルを上書きするのでファイルサイズを0にしてファイルポインタを先頭に戻す
- JSONファイルからCSVデータを作成して書き込んで保存する
- 保存したCSVファイルを読み込んで一覧表示させる
ダウンロードボタンもつけましたが今回に内容とは関係ないので省略します。
html側のファイルの説明をします
htmlのファイルの内容を載せます。PHPで処理する部分は後で説明するので省きます。ファイル名は「api_test.php」とします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<h1>チェックボックスから欲しいデータ</h1> <form action="api_test.php" method="post"> <input type="radio" name="country" value="IN">インド <input type="radio" name="country" value="SG">シンガポール <input type="radio" name="country" value="TH">タイ <p> <input type="submit" value="ツアーデータを取得"> </p> </form> <div class="container"> <h2>マップエリアを標示させるAPIデモ</h2> <p>エリアのジャンル一覧を表示する。</p> <p> <a href="download.php">CSVファイルをダウンロードする</a> </p> <!-- ここにCSVファイルを読み込む為のPHPを書きます。 --> <table class="deco"> <tr> <td width="25%">タイトル</td> <td width="25%">サマリー</td> <td width="25%">エリア</td> <td width="25%">国</td> <td width="25%">写真</td> </tr> <!-- ここにCSVファイルから取り出したデータをfor文で表示させる処理を記載します。 --> </table> </div> |
ラジオボタンによる国コードの設定
今回は、インドとシンガポールとタイの3国のツアーを取得したいのでvalueの値にそれぞれの国コードを設定しておきます。もちろんラジオボタンなので一つしかチェックできません。
フォームの送信先は同じファイルなのでapi_test.phpをactionに指定します。methodはPOSTです。
APIからデータを取得してCSV作成までのPHPの処理
まずはAPIを利用してデータを取得してCSVを作成して書き込むまでの処理を記載します。PHPでプログラムを書く場所はDOCTYPEより上に書きました。作成したCSVを一覧表示するPHPの処理は後述します。
リクエストURLやCSVファイルを変数に入れておく
まず変数を見てください。
1 2 3 4 |
$base_url='http://webservice.recruit.co.jp/ab-road/tour/v1/?key=自分のAPIキー&'; $count='&count=20'; $format='&format=json'; $csv_file="sample.csv"; |
ベースとなる海外旅行検索APIで提供されているリクエストURLに自分のAPIキーを設定して最後に「&」を追加しておきます.
後の変数countは取得する総数を20、変数formatはJSONファイルで取得する為、URLの構成を変数に分割しました。もちろんわざわざ変数に分割する必要もありません。ただ再利用や他の箇所で使われていたら変更するのもめんどくさいの変数にしたほうが分かりやすいかなと(笑)
変数csv_fileは書き込んだり読み込んだりするためのCSVファイルを設定します。
フォーム送信での処理
1 2 3 4 5 6 7 8 9 10 |
// postなら処理を実行する if ($_SERVER['REQUEST_METHOD'] === 'POST') { //国コードを取得 $getarea = $_POST["country"]; //空かどうかチェック。データが存在する場合は処理 if (!empty($getarea)) { } |
ラジオボタンにチェックを入れてボタンをクリックした後の処理の流れとしては
- まず$_SERVER[‘REQUEST_METHOD’]リクエストがPOSTかどうかチェックする
- POSTだった場合は、ラジオボタンでチェックした国コードを$_POSTから変数に入れる
- もしラジオボタンにチェックをしないまま送信ボタンをクリックしてしまった場合を想定して、!empty()関数でチェックする
*ただしラジオボタンに初期値に「checked=”checked”」と入れておけばこの処理は必要ない
といった流れでPHPの処理をしました。以降の作業は!empty関数のif文内での処理になります。
データを取得してJSONデータを加工する
1 2 3 4 5 6 7 |
$country = "country=".$getarea; //APIにリクエストするURLを作成する $url = $base_url.$country.$count.$format; //JSONデータを加工する $json = json_decode(file_get_contents($url)); |
file_get_contents()でデータを取得する
APIにリクエストするURLを作成します。
国コードを取得して最初に設定したベースとなるURLと「.(ドット)」でつなげて作成します。上記の例だと「ベースURL.国コード.取得数.フォーマット」とつなげています。
作成したリクエストURLをfile_get_contents()関数でデータを取得します。
JSONデータを加工する
今回JSONでデータを取得しましたがPHPの場合、JSONはそのままでは扱えないのでjson_decode()という関数を利用して「配列型(Array)」に変換します。
PHPでJSONファイルを扱う処理については「PHPでJSONのデータを処理する方法」がすごく詳しく書いてあります。
取得したデータをCSVに書き込み作成する
いよいよCSVの作成になります。JSONファイルを配列に変換した後は用意していたCSVを読み込んで書き込むという作業です。
CSVファイルを「読み込む・ロックする・書き込む・ロックを外す・CSVを閉じる」という記述は基本なので今回この部分の説明は省きます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// csvファイルを読み込み・書き込みでオープンする $fp = fopen($csv_file,"a"); flock($fp,LOCK_EX); // CSVファイルの中身を空にする // 既存の内容に追記していく場合は不要 ftruncate($fp,0); fseek($fp,0); // 取得したデータをCSVに書き込む foreach($json->results->tour as $genre) { $title = str_replace(",", "",$genre->title); $csv.=strftime("%Y/%m/%d %H:%M:%S").","; //取得時間 $csv.=$title.","; //ツアータイトル $csv.=$genre->dest->area->name.","; //エリア $csv.=$thumbnail.","; //サムネイル画像 $csv.=$genre->dest->country->name.","; //国の名前 $csv.=$genre->urls->pc.","; //ツアーのリンク先 $csv.=$genre->dest->name.","; //国の主要都市 $csv.=$genre->dest->lat.","; //Google mapの緯度 $csv.=$genre->dest->lng.","; //Google mapの経度 $csv.="\n"; //改行コード } // CSVデータ$csvの内容をファイルに書き込む fwrite($fp, $csv); // CSVファイルを閉じる flock($fp, LOCK_UN); fclose($fp); |
CSVファイルを上書きする処理
今回は国ごとのツアー情報をCSVに書き込みたいので、前のデータを削除したいと思います。その方法はCSVファイルの中身を空にする必要があるのでftrancate()関数でファイルサイズを0にします。そうするとファイルサイズが0になります。下記の記事も参考にしてみてください。
ファイルポインタを先頭に戻す
ftruncateでファイルを空にして上書きしたい場合はファイルポインタを先頭に戻す必要があるので、fseek()関数で0を指定して先頭に戻しておきます。
foreach文でCSVを作成する
foreach文でJSONファイルから配列に変換したデータのtourごとに$genre変数として処理しています。$genre変数からタイトルなどのデータを指定するには提供されているAPIの検索クエリのパラメータを指定します。例えばとあるツアーのタイトルとツアーの画像とツアーのリンク先が欲しい場合は、XMLで分かりやすく説明すると
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<tour> <title>ツアーの名前</title> <img> <l>大きい画像のパス</l> <m>普通の画像のパス</m> <s>小さい画像のパス</s> </img> <img> <l>大きい画像のパス</l> <m>普通の画像のパス</m> <s>小さい画像のパス</s> </img> <urls> <pc>PC用のツアーのリンク先</pc> <mobile>モバイル用のツアーのリンク先</mobile> </urls> </tour> |
となっているので、
1 2 3 |
$genre->title //ツアータイトル $genre->img[0]->l //サムネイル画像の大きいサイズ $csv.=$genre->urls->pc //ツアーのリンク先 |
となります。また、CSVファイルは,(コンマ)区切りで作成するので、取得時間・タイトル・エリアごとに取得する最後に「.”,”」を追加しています。
CSVには、一行ごとに一つのツアー情報を記述していくので、最後に\n(改行コード)を追加します。これでfwrite()関数で書き込めばCSVファイルの完成です。
文字列内の,(コンマ)には注意する
この処理はツアータイトルを最初取得した時にツアータイトルに半角の,(コンマ)が入っていた為にCSVファイル作成時に新しい「列」が作られてしまうことがありました。
それを防ぐ為にstr_replace()関数で半角の,(コンマ)を空白にしています。もし必要が無ければこの作業は必要ないでしょう。
PHPでCSVを一覧表示する処理
一応、ここまでの作業でAPIからCSVファイルを作成する作業は終わってますが、せっかくなのでどんなデータを取得したか一覧表示したいと思います。タイトル・エリア・国・街・写真の5つのデータをツアーごとに表示させます。
まず最初の方で記載したhtml側のファイルの中の記述します。
文字化け防止為に配列の文字コードを一気に変換する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<p>エリアのジャンル一覧を表示する。</p> <p><a href="download.php">CSVファイルをダウンロードする</a></p> <?php $data=file_get_contents("kankouti_sample.csv"); $buff=mb_convert_encoding($data,"utf-8","sjis"); //一時ファイルを作成して文字コードを変換したデータを書き込む。 $temp=tmpfile(); fwrite($temp,$data); rewind($temp); //一時ファイルのデータを新しい配列に再度CSVとして読み込む $csv=array(); while(($data=fgetcsv($temp,0,","))!==false){ $csv[]=$data; } fclose($temp); ?> |
CSVファイルって大抵エクセルで操作する事が多いのでCSVはShift_JISで保存されてる事がほとんです。けどPHPの内部文字エンコーディングはUTF-8だったりするのでfgetcsv()で読み込むとどうも文字化けがします。それを防ぐ為に下記のような方法で対処します。
- file_get_contents()でCSVファイルを一度読み込む
- mb_convert_encoding()で配列のデータの文字コードをUTF-8へコンバートする
- テンポラリファイル(一時ファイル)を作成してコンバートしたデータを書き込み、ファイルポインタを先頭に戻す
- fgetcsv()で読み込み新しい配列にデータを入れなおし、テンポラリファイルはfclose()で閉じる
一応、以前にもCSVの読み込み時の文字化けについて記事にした内容があるので下記を参照ください。
取得したデータを表示させる
配列の文字コードを変換したら後はfor文でhtml上に出力する処理をするだけです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<table class="deco"> <tr><td width="25%">タイトル</td><td width="10%">エリア</td><td width="10%">国</td><td width="10%">街</td><td width="40%">写真</td></tr> <?php for($i=0; $i<=count($csv)-1; $i++){ echo "<tr>"; echo "<td>".$csv[$i][1]."</td>"; echo "<td>".$csv[$i][2]."</td>"; echo "<td>".$csv[$i][4]."</td>"; echo "<td>".$csv[$i][6]."</td>"; echo "<td><img src='".$csv[$i][3]."' width='300' /></td>"; echo "</tr>"; } ?> </table> |
for文で一行ずつ[$i]取り出して該当する情報の列の番号を指定する・・たとえばタイトルなら1番目[1]、画像なら3番目[3]にという感じです。
またfor文で配列の総数から-1をしておりますが、これは最初にCSV作成した時に最後の行に改行コードが入っているので、表示させると空白行が表示されてしまう為に指定しています。
まとめ
かなり長くなってしまいました(笑) 今回はPHPでリクルートWEBサービスのエイビロードのAPIを使ってみましたが、他のWEBサービスから提供されているAPIも似たような処理になると思います。もちろん今回説明した内容やプログラムはあくまで説明用に作成したのでもっと効率のよいPHPの書き方もあると思います。
他にもぐるなび Web ServiceやYahoo!デベロッパーネットワークなどいろんなWebサービスがあるので、ぜひ試してみてください。
関連記事
-
-
【PHP】ftruncateでファイルの中身を上書きするには?
たまたま、ファイルの中身を別のファイルに書き換えるというか上書きするようなことを …
-
-
【PHP】preg_replaceで最初と最後の/を取り除いてみた!
文字列置換というとereg_replaceとかpreg_replaceで正規表現 …
-
-
【PHP】CSV ファイルをダウンロードするプログラムは?
phpでCSVをダウンロードする時って割と見ると思うんですが、そういえばphpで …
-
-
【PHP】ページ送り機能|連番で振っていくバージョン
phpの案件でデータを10件ずつ表示されて次のデータを表示するときに「次」「前」 …
-
-
【PHP】unlinkを利用したフォルダ内のファイルを削除する
まぁ、久々に投稿。てことでそのままになっていた、よくファイルをアップロードする仕 …
-
-
【PHP】PHPでリロード対策をして二重投稿を防止しよう
phpでフォームとか作ってデータを送信できた!!!って喜んでるのもつかの間(笑い …
-
-
【PHP】mb_send_mailでメールを送信してみる
お問い合わせなどのメールフォーム。今となっては当たり前の技術ですが仕組みを知って …
-
-
【wordpress】個別記事ページでアイキャッチ画像に元画像へのリンク張るには?
まぁwordpress最近全く弄ってません。なぜなら最近は、すばらしいテーマがあ …
-
-
【PHP】画像をダウンロードして特定のディレクトリに保存する方法
よくブラウザで画像を右クリック名前をつけて保存。なんていうのやることあるけど、p …
-
-
【PHP】Cookie(クッキー)にデータを保存するには!?
PHPでプログラムする上でやっぱCookie(クッキー)について勉強することもあ …