今回はGoogle Maps Platform の Places APIを使います。検索したらExcelファイルに施設の名前、住所、電話番号、開店時間などを保存します。
Places APIを使えるようにする方法はGoogle Maps API を使ってみた – Qiitaが画像もつかって説明してくれているのでわかりやすいです。Google Cloud Platformはどこをクリックしていいかわかりにくくて使いにくいです。
さてGoogle Cloud Platformでプロジェクトを作成したら(既存のプロジェクトがあるならそれを使ってもよいが…)、APIライブラリのPlaces APIを探してこれを有効化します。そしてAPIキーを取得しましょう。
Contents
キーワードから施設の名称と住所を取得する
“https://maps.googleapis.com/maps/api/place/textsearch/json?key={取得したAPI_KEY}&query={検索したいキーワード}&language=ja”にアクセスするとjson形式でレスポンスを取得することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
{ "html_attributions" : [], "next_page_token" : "Aap_uECQ12aC(本当はもっと長い文字列)", "results" : [ { "formatted_address" : "529 Kent St, Sydney NSW 2000 オーストラリア", "name" : "Tetsuya's Restaurant", "place_id" : "ChIJxXSgfDyuEmsR3X5VXGjBkFg", }, { "formatted_address" : "529 Kent St, Sydney NSW 2000 オーストラリア", "name" : "Tetsuya's Restaurant", "place_id" : "ChIJxXSgfDyuEmsR3X5VXGjBkFg", }, ], "status" : "OK" } |
取得されるjsonファイルはもっと長いのですが、取得したいのは施設の名称と住所、そして place_idだけなのでそれ以外の部分は省略しました。本当は営業時間や電話番号、webサイトがあれば取得したいのですが、これはplace_idを使ってもう一回検索をして取得します。
UIはテキストボックスにキーワードを入力してボタンを押せばExcelファイルに取得したデータが保存されるようにします。
まずExcelファイルをどこに保存するかを決めるための手段を用意します。これはこのかん毎度のように登場しているどこにファイルを保存するかをユーザーに決めさせるためのメソッドです。
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 |
public partial class Form1 : Form { string GetSaveExelFilePath() { string path = ""; SaveFileDialog dialog = new SaveFileDialog(); dialog.Filter = "Excelファイル(*.xlsx)|*.xlsx"; if (dialog.ShowDialog() == DialogResult.OK) path = dialog.FileName; dialog.Dispose(); return path; } private void button1_Click(object sender, EventArgs e) { string keyword = textBox1.Text; if (keyword == "") return; string excelFilePath = GetSaveExelFilePath(); if (excelFilePath == "") return; // Places APIをつかってデータを取得して保存する } } |
これまで簡単に使えるのでWindowsForms(.NET Framework)を使ってきましたが、jsonファイルを簡単に使えるようにしたいのでWinFormsアプリケーション(.NET 5.0)を使います。
URLエンコードするためにHttpUtilityクラスを使用するのですが、WindowsForms(.NET Framework)の場合、HttpUtilityクラスを使用するには、System.Web.dllを参照設定に追加しなければなりません。でもWinFormsアプリケーション(.NET 5.0)なら自分でやる必要はありません。
Places APIでデータを取得する
まずPlaces APIでデータを取得しましょう。これで検索した結果がjson形式で取得されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public partial class Form1 : Form { string GetJsonTextFromSearchWord(string word) { string query = System.Web.HttpUtility.UrlEncode(word); string url = String.Format("https://maps.googleapis.com/maps/api/place/textsearch/json?key={0}&query={1}&language=ja", API_KEY, query); System.Net.HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url); System.Net.HttpWebResponse res = (HttpWebResponse)req.GetResponse(); System.IO.Stream stream = res.GetResponseStream(); System.IO.StreamReader sr = new System.IO.StreamReader(stream); string jsonText = sr.ReadToEnd(); sr.Close(); stream.Close(); res.Close(); return jsonText; } } |
取得したjson形式のデータをクラスで扱えるようにする
次に取得したjson形式のデータをC#で扱いやすい形に変形します。取得したいのは施設の名称と住所、そして place_idだけなのでそれを取得できれば充分です。
そこでこのようなクラスを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 |
public class MapInfo { public string next_page_token { get; set; } public Result[] results { get; set; } } public class Result { public string formatted_address { get; set; } public string name { get; set; } public string place_id { get; set; } } |
そのあとGetJsonTextFromSearchWord(keyword)メソッドを実行して得られたjsonデータをJsonSerializer.Deserializeメソッドに渡せばMapInfoクラスのインスタンスが得られます。そのなかにはResultオブジェクトの配列があり、ここから施設の名称と住所、place_idを取得することができます。
1 2 |
// JsonTextを解析して結果を取得する MapInfo MapInfo = JsonSerializer.Deserialize<MapInfo>(jsonText1); |
place_idから施設に関するその他の情報も取得する
次にplace_idから施設の情報を取得します。取得したいのは電話番号とWebサイト、営業時間です。以下のメソッドを実行するとjson形式でレスポンスが返されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public partial class Form1 : Form { string GetJsonTextFromPlaceID(string place_id) { string language = "ja"; string url = "https://maps.googleapis.com/maps/api/place/details/json?"; url += "key=" + API_KEY; url += "&place_id=" + place_id; // 他のデータも取得できるが、ここでは施設名と電話番号と営業時間とWebサイトを取得する url += "&fields=name,formatted_phone_number,opening_hours,website"; url += "&language=" + language; System.Net.HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url); System.Net.HttpWebResponse res = (HttpWebResponse)req.GetResponse(); System.IO.Stream stream = res.GetResponseStream(); System.IO.StreamReader sr = new System.IO.StreamReader(stream); string jsonText = sr.ReadToEnd(); sr.Close(); stream.Close(); res.Close(); return jsonText; } } |
json形式で返されるレスポンスは以下のようなものです。実際はもっと長いですが、必要な部分以外は省略しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
{ "html_attributions" : [], "result" : { "formatted_phone_number" : "03-3433-XXXX", "name" : "ローソン ○○店", "opening_hours" : { "open_now" : true, "weekday_text" : [ "月曜日: 8時00分~20時00分", "火曜日: 8時00分~20時00分", "水曜日: 8時00分~20時00分", "木曜日: 8時00分~20時00分", "金曜日: 8時00分~20時00分", "土曜日: 定休日", "日曜日: 定休日" ] }, "website" : "https://www.e-map.ne.jp/p/lawson/dtl/209651/" }, "status" : "OK" } |
そこで以下のようなクラスを作成してJsonSerializer.Deserializeメソッドを実行します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public class PlaceDetails { public PlaceDetailsResult result { get; set; } } public class PlaceDetailsResult { public string formatted_phone_number { get; set; } public OpeningHours opening_hours { get; set; } public string website { get; set; } } public class OpeningHours { public string[] weekday_text { get; set; } } // あとはJsonSerializer.Deserializeメソッドで解決 string jsonText2 = GetJsonTextFromPlaceID(place_id); PlaceDetails placeDetails = JsonSerializer.Deserialize<PlaceDetails>(jsonText2); |
Excelファイルに保存する
ここまでできたらあとは取得したデータをExcelファイルに保存するだけです。DataクラスはAPIのレスポンスを解析して取得できたデータをまとめておくためのクラスです。
1 2 3 4 5 6 7 8 |
public class Data { public string Name = ""; public string Address = ""; public string Website = ""; public string PhoneNumber = ""; public string OpeningWeekdayText = ""; } |
それでは検索ボタンが押されたときの処理全体をみてみましょう。
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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
public partial class Form1 : Form { string API_KEY = "各自で取得してください"; private void button1_Click(object sender, EventArgs e) { string keyword = textBox1.Text; if (keyword == "") return; string excelFilePath = GetSaveExelFilePath(); if (excelFilePath == "") return; List<Data> datas = new List<Data>(); string jsonText1 = GetJsonTextFromSearchWord(keyword); MapInfo MapInfo = JsonSerializer.Deserialize<MapInfo>(jsonText1); foreach (Result result in MapInfo.results) { string name = result.name; string address = result.formatted_address; string place_id = result.place_id; string jsonText2 = GetJsonTextFromPlaceID(place_id); PlaceDetails placeDetails = JsonSerializer.Deserialize<PlaceDetails>(jsonText2); string phoneNumber = placeDetails.result.formatted_phone_number; string website = placeDetails.result.website; string openingWeekdayText = ""; OpeningHours openingHours = placeDetails.result.opening_hours; if (openingHours != null) { string[] vs = openingHours.weekday_text; openingWeekdayText = string.Join(" ", vs); } Data data = new Data() { Name = name, Address = address, PhoneNumber = phoneNumber, Website = website, OpeningWeekdayText = openingWeekdayText, }; datas.Add(data); } SaveExcel(excelFilePath, datas); } void SaveExcel(string excelPath, List<Data> datas) { using (var workbook = new XLWorkbook()) { var worksheet = workbook.Worksheets.Add("シート1"); worksheet.Cell(1, "A").Value = "名称"; worksheet.Cell(1, "B").Value = "住所"; worksheet.Cell(1, "C").Value = "電話番号"; worksheet.Cell(1, "D").Value = "Webサイト"; worksheet.Cell(1, "E").Value = "営業時間"; int i = 2; foreach (Data data in datas) { worksheet.Cell(i, "A").Value = data.Name; worksheet.Cell(i, "B").Value = data.Address; worksheet.Cell(i, "C").Value = data.PhoneNumber; worksheet.Cell(i, "D").Value = data.Website; worksheet.Cell(i, "E").Value = data.OpeningWeekdayText; i++; } workbook.SaveAs(excelPath); } } } |