'22/04/13更新:堅牢性のためにエラー処理などを追加
本記事では、下図のようにホテル情報を抽出する雛形コードを載せました。使用するライブラリは「requests」です。
はじめに、楽天IDが必要なので、登録してない場合は登録します。そして、次のリンク先にアクセスして、楽天にログインします。https://webservice.rakuten.co.jp/documentation
次に、APIを使うにはApplication IDを取得する必要があるため、下図右上の「New App」をクリックします。
すると、下図のような登録画面に切り替わります。ここではWeb APIと連携するアプリ名を聞かれます。アプリ名は「excel」や「自分のHPのリンク」など適当でも構わないようで、必要事項を記入して進みます。
最後に、下図のようにApplication IDが表示されます。web api利用時に使用します。
■本プログラム
下記、冒頭にある app_id = '' に上記で取得したIDを記入します。あとは実行するだけです。ホテル情報は、行き先の都道府県を乱数で決めて、抽出結果をcsvファイルに保存する仕様です。
ちなみに、これはJupyterLabで作成したコードをスクリプトファイルに出力しました。そのため、上から順番にIn[1]~In[20]をJupyterLabでインタラクティブに実行してゆくことも可能です。
#!/usr/bin/env python # coding: utf-8 # In[1]: import sys import requests import pandas as pd import numpy as np import random # 取得したAPIのID app_id = '' # 楽天トラベルの地区コードを取得するためのURL area_code_rquest_url = 'https://app.rakuten.co.jp/services/api/Travel/GetAreaClass/20131024' # プロキシ設定(明示的に不要な場合はNoneを指定) proxies = { 'http': None, 'https': None, } # リクエストするパラメータ area_code_params = { 'format': 'json', 'formatVersion': 2, 'applicationId': app_id, } # リクエストを実行する res_area_code = requests.get( area_code_rquest_url, proxies = proxies, params = area_code_params) print(res_area_code) if res_area_code.status_code == 200: print('success') print(type(res_area_code)) else: print('check app_id, and so on') sys.exit() # In[2]: # jsonへ変換 result_area_code_dict = res_area_code.json() print(type(result_area_code_dict)) # In[3]: # 都道府県データ prefectures = result_area_code_dict['areaClasses']['largeClasses'][0][1]['middleClasses'] print(len(prefectures)) #print(prefectures) # In[4]: # 地区コードを抽出する data_list = [] for i, data1 in enumerate(prefectures, start=1): #print(i, 'raw data') #print(data1['middleClass']) for j, data2 in enumerate(data1['middleClass']): if j == 0: # 都道府県名の抽出 my_middle_class_code = data2['middleClassCode'] my_middle_class_name = data2['middleClassName'] #print('middleClass') #print('middleClassCode', my_middle_class_code) #print('middleClassName', my_middle_class_name) else: # 市以下の抽出 for data3 in data2['smallClasses']: for key1, data4 in data3.items(): for data5 in data4: for key3, data6 in data5.items(): if key3 != 'detailClasses': # 市地区 #print('smallClasses') if key3 == 'smallClassCode': my_small_calss_code = data6 data_list.append(['ClassCode', my_middle_class_code, my_small_calss_code, np.nan]) else: my_small_calss_name = data6 data_list.append(['ClassName', my_middle_class_name, my_small_calss_name, np.nan]) else: # 詳細地区名 for data7 in data6: #print(data7['detailClass']) for key5, data7 in data7['detailClass'].items(): #print('detailClasses') if key5 == 'detailClassCode': data_list.append(['ClassCode', my_middle_class_code, \ my_small_calss_code, \ data7]) else: data_list.append(['ClassName', my_middle_class_name, \ my_small_calss_name, \ data7]) # pandasデータフレームへ格納 df = pd.DataFrame(data_list, columns = ['myclass', 'middle_name', 'small_name', 'detail_name']) df # In[5]: # カテゴリがClassCodeのみ抽出する df_class_code = df[df['myclass'] == 'ClassCode'] df_class_code.columns = ['mycode', 'middle_code', 'small_code', 'detail_code'] df_class_code.reset_index(drop = True, inplace = True) df_class_code # In[6]: # カテゴリがClassNameのみ抽出する df_class_name = df[df['myclass'] == 'ClassName'] df_class_name.reset_index(drop = True, inplace = True) df_class_name # In[7]: # 列方向へ結合する DF = pd.concat([df_class_code, df_class_name], axis=1) DF # In[8]: # detail_codeがAである行を抽出 DF_buf = DF[DF['detail_code'] == 'A'] DF_buf # In[9]: # detail_codeがAである行のmiddle_code と small_codeの値を抽出して、detail_codeがNaNの行番号を抽出 target_index_list = [] for index, row in DF_buf.iterrows(): df_buf1 = DF[ (DF['middle_code'] == row['middle_code']) & \ (DF['small_code'] == row['small_code']) ] df_buf2 = df_buf1[df_buf1['detail_code'].isnull()] print(df_buf2) target_index_list.append(df_buf2.index[0]) target_index_list # In[10]: # 行番号を指定して削除 DF2 = DF.drop(DF.index[target_index_list]) DF2.to_csv('01_area_list.csv', encoding='utf-8-sig') DF2 # In[11]: # # 地域を指定する場合 1/2 middle地域を指定 # DF3 = DF2[DF2['middle_name'] == '愛知県'] # DF3 # In[12]: # # 地域を指定する場合 2/2 small地域を指定 # DF3 = DF3[DF3['small_name'] == '南知多・日間賀島・篠島'] # index_no = DF3.index[0] # print(index_no) # DF3 # In[13]: # 地域を乱数で決定する場合 index_no = random.randint(0,len(DF2)) print(index_no) # In[14]: # インデックス番号を指定してデータを抽出 DF3 = DF.iloc[index_no] DF3 # In[15]: # データを変数へ格納 middle_name, small_name = DF3['middle_name'], DF3['small_name'] middle, small, detail = DF3['middle_code'], DF3['small_code'], DF3['detail_code'] print(middle_name, small_name, middle, small, detail) # In[16]: # 宿情報のリクエストURL inn_request_url = 'https://app.rakuten.co.jp/services/api/Travel/SimpleHotelSearch/20170426' df_hotel_list = [] i = 1 j = 0 while True: # リクエストするパラメータの設定 if pd.isna(detail): # detailClassCode がない場合 inn_params = { 'format': 'json', 'largeClassCode': 'japan', 'middleClassCode': middle, 'smallClassCode': small, 'page': i, 'applicationId': app_id, } else: inn_params = { 'format': 'json', 'largeClassCode': 'japan', 'middleClassCode': middle, 'smallClassCode': small, 'detailClassCode': detail, 'page': i, 'applicationId': app_id, } # リクエストを実行する res = requests.get( inn_request_url, proxies = proxies, params = inn_params) if res.status_code != 200: # もしデータ取得に成功しなかった場合にループを抜ける break # jsonへ変換 result = res.json() # ホテル情報をpandasデータフレームで取得する hotels = result["hotels"] for hotel in hotels: hotel_info = hotel["hotel"][0]["hotelBasicInfo"] df_buf = pd.DataFrame(hotel_info, index=[j]) df_hotel_list.append(df_buf) j += 1 if j > 50: # もし、検索したホテル数が50を超えたらループを抜ける break i += 1 #df_hotel_list # In[17]: # pandasデータフレームを結合する df_hotels = pd.concat(df_hotel_list) #df_hotels # In[18]: # カラム名一覧 df_hotels.columns # In[19]: # カラム名を指定して、データ抽出 df_hotels_simple = df_hotels[ [ 'hotelName', 'hotelInformationUrl', #'reviewUrl', 'hotelSpecial', 'hotelMinCharge', #'address2', 'telephoneNo', #'access', 'nearestStation', 'reviewCount', 'reviewAverage', #'userReview', ] ] # 「最安値の目安」列に対して、降順にソートする df_hotels_simple_s = df_hotels_simple.sort_values('hotelMinCharge', ascending=False) # ファイルへ保存 #df_hotels_simple_s.to_csv(f'02_{middle_name}_{small_name}_hotel_list.csv', encoding='utf-8-sig') # In[20]: # 「最安値の目安」列に対して、指定区間内の値にあるホテルを抽出する min_Charge = 6000 max_Charge = 10000 df_target_hotels = df_hotels_simple_s[(df_hotels_simple_s['hotelMinCharge'] >= min_Charge) & (df_hotels_simple_s['hotelMinCharge'] <= max_Charge)] print(len(df_target_hotels)) # ファイルへ保存 df_target_hotels.to_csv(f'02_{middle_name}_{small_name}_target_hotel_list.csv', encoding='utf-8-sig') df_target_hotels
以上
<広告>
リンク