目次
サンプル・プログラム
searchcafewin.msi | インストーラ |
bin/searchcafewin.exe | 実行プログラム本体 |
bin/cwebpage.dll bin/libcurl.dll | 実行時に必要になるDLL |
bin/etc/help.chm | ヘルプ・ファイル |
sour/searchcafewin.cpp | ソース・プログラム |
sour/resource.h | リソース・ヘッダ |
sour/resource.rc | リソース・ファイル |
sour/application.ico | アプリケーション・アイコン |
sour/mystrings.cpp | 汎用文字列処理関数など(ソース) |
sour/mystrings.h | 汎用文字列処理関数など(ヘッダ) |
sour/pahooGeocode.cpp | 住所・緯度・経度に関わるクラス(ソース) |
sour/pahooGeocode.hpp | 住所・緯度・経度に関わるクラス(ヘッダ) |
sour/apikey.cpp | APIキーの管理(ソース) |
sour/apikey.hpp | APIキーの管理(ヘッダ) |
sour/WebView2.h | WebView2に関わるヘッダ |
sour/event.h | WebView2用インターフェース(ヘッダ) |
sour/event.cpp | WebView2用インターフェース(ソース) |
sour/pahooWebView2.cpp | WebView2に関わる関数(ソース) |
sour/pahooWebView2.hpp | WebView2に関わる関数(ヘッダ) |
sour/makefile | ビルド |
バージョン | 更新日 | 内容 |
---|---|---|
1.0.0 | 2024/04/29 | 初版 |
バージョン | 更新日 | 内容 |
---|---|---|
1.8.0 | 2024/05/03 | getMyPath()をapikey.appのgetMyPath()関数に変更 |
1.7.0 | 2024/04/27 | Edge対応に伴いデバッグ用コードを廃棄 |
1.6.0 | 2023/07/02 | getPointsGSI()メソッド追加 |
1.5 | 2022/09/03 | デバッグコード埋め込み |
1.4 | 2021/05/01 | makeMapLeaflet() 引数追加 |
バージョン | 更新日 | 内容 |
---|---|---|
1.2.0 | 2024/05/06 | getModulePath() 追加 |
1.12 | 2021/01/31 | readWebContents() 引数post追加 |
1.11 | 2020/10/17 | htmlspecialchars() 追加 |
1.1 | 2020/10/17 | GetVersion2()追加,readWebContents() 引数ua追加 |
1.01 | 2020/10/03 | setClipboardData() bug-fix |
バージョン | 更新日 | 内容 |
---|---|---|
1.0.0 | 2024/04/27 | 初版 |
バージョン | 更新日 | 内容 |
---|---|---|
2.0.0 | 2024/04/29 | createSetAPIkey, processSetAPIkey に統合 |
1.0 | 2020/09/30 | 初版 |
使用ライブラリ
WebAPIにアクセスするために、オープンソースのライブラリ Boost C++ライブラリ、cURL および OpenSSL が必要になる。導入方法等については、「C++ 開発環境の準備」をご覧いただきたい。
また、地図表示にWebブラウザ・コントロールを利用するため "WebView2Loader.dll" を利用する。jchv / webview2-in-mingw からダウンロードできる。
また、地図表示にWebブラウザ・コントロールを利用するため "WebView2Loader.dll" を利用する。jchv / webview2-in-mingw からダウンロードできる。
リソースの準備
64ビット版の開発環境を用いる。
Eclipse を起動し、新規プロジェクト searchcafewin を用意する。
ResEdit を起動し、resource.rc を用意する。
Eclipse に戻り、ソース・プログラム "searchcafewin.cpp" を追加する。
リンカー・フラグを -Wl,--enable-stdcall-fixup -mwindows -lgdiplus -static -lstdc++ -lgcc -lwinpthread -lcurl -lssl "C:\(libcurl-x64.dllのフォルダ)\libcurl-x64.dll" "C:\(WebView2Loader.dllのフォルダ)\WebView2Loader.dll" に設定する。
また、コマンド行パターンを ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS} -lole32 -loleaut32 -luuid にすること。
MSYS2 コマンドラインからビルドするのであれば、"makefile" を利用してほしい。
Eclipse を起動し、新規プロジェクト searchcafewin を用意する。
ResEdit を起動し、resource.rc を用意する。
Eclipse に戻り、ソース・プログラム "searchcafewin.cpp" を追加する。
リンカー・フラグを -Wl,--enable-stdcall-fixup -mwindows -lgdiplus -static -lstdc++ -lgcc -lwinpthread -lcurl -lssl "C:\(libcurl-x64.dllのフォルダ)\libcurl-x64.dll" "C:\(WebView2Loader.dllのフォルダ)\WebView2Loader.dll" に設定する。
また、コマンド行パターンを ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS} -lole32 -loleaut32 -luuid にすること。
MSYS2 コマンドラインからビルドするのであれば、"makefile" を利用してほしい。
解説:定数など
// 定数など ==================================================================
#define MAKER "pahoo.org" //作成者
#define APPNAME "searchcafewin" //アプリケーション名
#define APPNAMEJP "喫茶店を検索" //アプリケーション名(日本語)
#define APPVERSION "1.0.0" //バージョン
#define APPYEAR "2024" //作成年
#define REFERENCE "/e-soul/webtech/cpp01/cpp01-17-01.shtm" //参考サイト
//ListViewItemの最大文字長:変更不可
#define MAX_LISTVIEWITEM 259
//ヘルプ・ファイル
#define HELPFILE ".\\etc\\help.chm"
//デフォルト保存ファイル名
#define SAVEFILE "stationsearchwin.csv"
//ホットペッパーグルメWebサービス APIキー名称
#define LABEL_HOTPEPPER_API "ホットペッパーAPIキー"
//ホットペッパーグルメWebサービス APIキー保存ファイル名
#define FNAME_HOTPEPPER_API "HotpepperAPIkey"
//ホットペッパーグルメWebサービス APIキー取得ページ
#define URL_HOTPEPPER_API "https://webservice.recruit.co.jp/register"
//ホットペッパーグルメWebサービス 検索ジャンルID:カフェ・スイーツ
#define HOTPEPPER_GENRE "G014"
//マップID
#define MAP_ID "map_id"
//地図の大きさ
#define MAP_WIDTH 550 //地図の幅(ピクセル)
#define MAP_HEIGHT 320 //地図の高さ(ピクセル)
//経度・緯度(初期値)
#define DEF_LONGITUDE 139.766667
double Longitude = DEF_LONGITUDE;
#define DEF_LATITUDE 35.681111
double Latitude = DEF_LATITUDE;
//地図拡大率(初期値)
#define DEF_ZOOM 13
int Zoom = DEF_ZOOM;
//地図の種類(初期値)
#define DEF_MAPTYPE "GSISTD"
string Maptype = DEF_MAPTYPE;
とくに注意記載が無い限り、定数は自由に変更できる。
ホットペッパー グルメサーチAPI
ホットペッパー グルメサーチAPIは、入力パラメータ(IN)として GET方式を、出力結果(OUT)がXMLまたはJSONで戻るというAPIである。
URL |
---|
https://webservice.recruit.co.jp/hotpepper/gourmet/v1/ |
フィールド名 | 要否 | 内 容 |
---|---|---|
key | 必須 | APIキー |
lat | 必須 | 緯度 |
lng | 必須 | 経度 |
range | 必須 | 検索範囲 1: 300m 2: 500m 3: 1000m (初期値) 4: 2000m 5: 3000m |
datum | 任意 | world: 世界測地系、tokyo: 旧日本測地系。初期値は world。 |
genre | 任意 | お店ジャンルコード。本プログラムでは定数HOTPEPPER_GENREで指定。 |
count | 任意 | 検索結果の最大出力データ数を指定します。初期値:10、宰相:1、最大100。 |
format | 任意 | レスポンス形式。初期値:xml。xml または json または jsonp。 |
解説:ホットペッパーグルメWebサービスの呼び出し
/**
* ホットペッパー グルメサーチAPI から必要な情報を配列に格納する
* @param double latitude 緯度(世界測地系)
* @param double longitude 経度(世界測地系)
* @param int range 検索範囲(1:300m,2:500m,3:1000m,4:2000m,5:3000m)
* @param string genre ジャンルID
* @return int ヒット数/(-1):エラー発生
*/
int pahooHotpepper::getResults_Hotpepper(double latitude, double longitude, int range, string genre) {
//ホットペッパー グルメサーチAPI呼び出し
char lat[SIZE_BUFF + 1], lng[SIZE_BUFF + 1], rng[SIZE_BUFF + 1];;
if (range <= 0 || range > 5) {
setError(_SW("検索範囲が間違っています"));
return (-1);
}
snprintf(lat, SIZE_BUFF, "%.5f", latitude);
snprintf(lng, SIZE_BUFF, "%.5f", longitude);
snprintf(rng, SIZE_BUFF, "%d", range);
this->webapi = "http://webservice.recruit.co.jp/hotpepper/gourmet/v1/?key=" + HotpepperAPIkey + "&lat=" + (string)lat + "&lng=" + (string)lng + "&range=" + (string)rng + "&genre=" + (string)genre;
//ホットペッパー グルメサーチAPI 応答
string contents = "";
bool res = readWebContents(this->webapi, UserAgent, &contents);
if (res == FALSE) {
setError(_SW("ホットペッパー グルメサーチAPI の接続エラーが発生しました"));
return (-1);
}
//配列の初期化
for (int i = 0; i < __SIZE_PPOINTS; i++) {
this->Cafes[i].id = 0;
this->Cafes[i].name = this->Cafes[i].address = L"";
this->Cafes[i].latitude = this->Cafes[i].longitude = 0.0;
this->Cafes[i].url = this->Cafes[i].photo = "";
this->Cafes[i].open = this->Cafes[i].close = L"";
this->Cafes[i].wifi = this->Cafes[i].budget = L"";
}
//XML読み込み
int cnt = 0;
try {
std::stringstream ss;
ss.str("");
ss << contents;
ptree pt;
xml_parser::read_xml(ss, pt);
//応答チェック
if (optionalstr = pt.get_optional("results.results_returned")) {
int n = stoi(str.get());
if (n <= 0) {
return 0;
}
} else {
setError(_SW("ホットペッパー グルメサーチAPI の応答エラーが発生しました"));
return (-1);
}
//XML解釈
try {
for (auto it : pt.get_child("results")) {
if (cnt >= __SIZE_PPOINTS) {
break;
}
//読み飛ばし
if (it.first != "shop") {
continue;
}
//識別子
this->Cafes[cnt].id = cnt + 1;
//店名
if (optionalname = it.second.get_optional("name")) {
this->Cafes[cnt].name = _UW(name.value());
}
//住所
if (optionaladdress = it.second.get_optional("address")) {
this->Cafes[cnt].address = _UW(address.value());
}
//緯度
if (optionallat = it.second.get_optional("lat")) {
this->Cafes[cnt].latitude = stod(lat.value());
}
//経度
if (optionallng = it.second.get_optional("lng")) {
this->Cafes[cnt].longitude = stod(lng.value());
}
//営業時間
if (optionalopen = it.second.get_optional("open")) {
this->Cafes[cnt].open = _UW(open.value());
}
//定休日
if (optionalclose = it.second.get_optional("close")) {
this->Cafes[cnt].close = _UW(close.value());
}
//PC向けURL
if (optionalurl = it.second.get_optional("urls.pc")) {
this->Cafes[cnt].url = url.value();
}
//写真URL
if (optionalphoto = it.second.get_optional("photo.pc.s")) {
this->Cafes[cnt].photo = photo.value();
}
//ディナー予算
if (optionalbudget = it.second.get_optional("budget.average")) {
this->Cafes[cnt].budget = _UW(budget.value());
}
//Wi-Fi有無
if (optionalwifi = it.second.get_optional("wifi")) {
this->Cafes[cnt].wifi = _UW(wifi.value());
}
cnt++;
}
//XML解釈エラー
} catch(ptree_bad_path& e) {
setError(_SW("ホットペッパー グルメサーチAPI の検索エラーが発生しました"));
return (-1);
}
//読み込みエラー
} catch(xml_parser_error& e) {
setError(_SW("ホットペッパー グルメサーチAPI の接続エラーが発生しました"));
return (-1);
}
contents.clear();
/** debug
cout << "cnt = " << cnt << endl;
for (int i = 0; i < cnt; i++) {
cout << _WS(this->Cafes[cnt].name) << endl;
}
**/
return cnt;
}
応答は XML形式である。
Boost C++ライブラリ の property_tree にある xml_parser を利用する。
今回も、cURL を使って応答情報を変数に代入し、ストリーミングを使ってxmlパーサーに流し込んでやる。
Boost C++ライブラリ の property_tree にある xml_parser を利用する。
今回も、cURL を使って応答情報を変数に代入し、ストリーミングを使ってxmlパーサーに流し込んでやる。
共通手順、モジュールなど
その他の関数、ヘルプファイルやインストーラー作成方法については、これまでの連載で説明してきたとおりである。
- C++ 開発環境の準備:ぱふぅ家のホームページ
- C++ 開発環境の準備 -MSYS2編-
- WiX によるWindowsインストーラー作成:ぱふぅ家のホームページ
- C++ でダイアログボックスを使う
- C++ でイベント駆動型アプリを作る
- 解説:ニュース一覧作成
C++ で Googleニュース検索 - 解説:検索結果をCSVファイルに保存
C++ で Googleニュース検索 - 解説:クリップボード
C++ でパスワード生成機を作る - 解説:APIキーの管理
C++ で直近の地震情報を取得する - 解説:WebView2
C++ で直近の地震情報を取得する - 解説:解説:マップ表示用HTML生成
C++ で直近の地震情報を取得する 参考サイト
- グルメサーチAPI:ホットペッパー
- PHPでホットペッパーを利用して喫茶店を検索する
(この項おわり)
「PHPでホットペッパーを利用して喫茶店を検索する」で作ったPHPプログラムをC++に移植したものである。