前回のブログでは、楽天APIで好きなお宿の空き室検索をするPythonプログラムを作った。
popololo-nyanya.hatenablog.com
今回はそれを発展させ、
3か月先まで、土日の空き室を自動検索できるようにしたい。
日付の抽出
datetimeモジュールのtimedeltaオブジェクトを使って、日付の差を表すことができる。
例えば、72時間、3週間を引数にして実行してみると、それぞれ3日、21日という計算結果が出る。
<code>
day_A = datetime.timedelta(hours=72).days
print(day_A)
day_B = datetime.timedelta(weeks=3).days
print(day_B)
<結果>
3
21
これを使って、3か月先までの日付を出してみる。
timedeltaオブジェクトの引数にmonthはないので、1か月4.5週間として3か月を13週間として計算。
<code>
today = datetime.date.today() #今日の日付
days = datetime.timedelta(weeks=13).days #3か月先までの日数
for i in range(0, days): # 13週先まで、1日ずつカウントアップ
print(today + datetime.timedelta(i))
<結果>
2023-06-16
2023-06-17
2023-06-18
.....
.....(中略)
.....
2023-09-12
2023-09-13
2023-09-14
次に、チェックイン日である土曜日だけを抽出してみる。
weekdayメソッドは、月曜日を 0、日曜日を 6 として、曜日を整数で返す。
<code>
day_C = datetime.date(2023, 11, 11).weekday()
print(day_C)
<結果>
5
今年のいい夫婦の日(11月11日)は水曜日だそうです。
これを利用して、土曜日だけを抽出。
<code>
today = datetime.date.today() #今日の日付
days = datetime.timedelta(weeks=13).days #3か月先までの日数
for i in range(0, days): # 13週先まで、1日ずつカウントアップ
if (today + datetime.timedelta(i)).weekday() == 5:
print(today + datetime.timedelta(i))
<結果>
2023-06-17
2023-06-24
2023-07-01
2023-07-08
2023-07-15
2023-07-22
2023-07-29
2023-08-05
2023-08-12
2023-08-19
2023-08-26
2023-09-02
2023-09-09
楽天トラベルAPIで空き室検索
あとは前回のブログのソースコードと合体させるだけ。
<code>
import requests
import json
import time
import datetime
def search():
# 13週(約3か月)先までの日数を数える
today = datetime.date.today()
days = datetime.timedelta(weeks=13).days
# スクレイピングで空き室検索
for i in range(0, days): # 13週先まで、1日ずつカウントアップ
if (today + datetime.timedelta(i)).weekday() == 5: #土曜日だったら宿検索する
checkinDate = str(today + datetime.timedelta(i)) #チェックイン日
checkoutDate = str(today + datetime.timedelta(i) + datetime.timedelta(1)) #チェックアウト日
REQUEST_URL = "https://app.rakuten.co.jp/services/api/Travel/VacantHotelSearch/20170426"
APP_ID = "自分のアプリID"
hotelNum="178403"
condition="kinen,breakfast"
params = {
"format":"json",
"applicationId":APP_ID,
"hotelNo":hotelNum,
"checkinDate":checkinDate,
"checkoutDate":checkoutDate,
"adultNum":2,
"squeezeCondition":condition,
"sort":"+roomCharge"
}
response = requests.get(REQUEST_URL, params)
time.sleep(1)
res = json.loads(response.text)
hotelName=res["hotels"][0]["hotel"][0]["hotelBasicInfo"]["hotelName"]
roomName=res["hotels"][0]["hotel"][1]["roomInfo"][0]["roomBasicInfo"]["roomName"]
planName=res["hotels"][0]["hotel"][1]["roomInfo"][0]["roomBasicInfo"]["planName"]
stayDate=res["hotels"][0]["hotel"][1]["roomInfo"][1]["dailyCharge"]["stayDate"]
totalCrg=res["hotels"][0]["hotel"][1]["roomInfo"][1]["dailyCharge"]["total"]
planUrl=res["hotels"][0]["hotel"][1]["roomInfo"][0]["roomBasicInfo"]["reserveUrl"]
allplanUrl=res["hotels"][0]["hotel"][0]["hotelBasicInfo"]["planListUrl"]
txt=""
txt = txt + '\r\n' \
+ "宿名: " + hotelName + '\r\n' \
+ "部屋名: " + roomName + '\r\n' \
+ "プラン名: " + planName + '\r\n' \
+ "宿泊日: " + stayDate + '\r\n' \
+ "価格: " + str(totalCrg) + "円" + '\r\n' \
+ "予約ページURL: " + planUrl + '\r\n' \
+ "プラン一覧URL: " + allplanUrl
print(txt)
time.sleep(2)
if __name__=='__main__':
search()
<結果>
35 res = json.loads(response.text)
36
---> 37 hotelName=res["hotels"][0]["hotel"][0]["hotelBasicInfo"]["hotelName"]
38 roomName=res["hotels"][0]["hotel"][1]["roomInfo"][0]["roomBasicInfo"]["roomName"]
39 planName=res["hotels"][0]["hotel"][1]["roomInfo"][0]["roomBasicInfo"]["planName"]
KeyError: 'hotels'
途中まで検索できていたのですが、エラー発生。
どうやら、空き室がないときに以下のJSONデータが返ってくるので、"hotels"なんてどこにも無いよ!と怒られている様子。
{
"error_description": "Data Not Found",
"error": "not_found"
}
空き室が無かった場合を考えてif文を追加。
<code>
import requests
import json
import time
import datetime
def search():
# 13週(約3か月)先までの日数を数える
today = datetime.date.today()
days = datetime.timedelta(weeks=13).days
# スクレイピングで空き室検索
for i in range(0, days): # 13週先まで、1日ずつカウントアップ
if (today + datetime.timedelta(i)).weekday() == 5: #土曜日だったら宿検索する
checkinDate = str(today + datetime.timedelta(i)) #チェックイン日
checkoutDate = str(today + datetime.timedelta(i) + datetime.timedelta(1)) #チェックアウト日
REQUEST_URL = "https://app.rakuten.co.jp/services/api/Travel/VacantHotelSearch/20170426"
APP_ID = "自分のアプリID"
hotelNum="178403"
condition="kinen,breakfast"
params = {
"format":"json",
"applicationId":APP_ID,
"hotelNo":hotelNum,
"checkinDate":checkinDate,
"checkoutDate":checkoutDate,
"adultNum":2,
"squeezeCondition":condition,
"sort":"+roomCharge"
}
response = requests.get(REQUEST_URL, params)
time.sleep(1)
res = json.loads(response.text)
if "error_description" in res.keys(): # 空き室がないとき
pass
else:
hotelName=res["hotels"][0]["hotel"][0]["hotelBasicInfo"]["hotelName"]
roomName=res["hotels"][0]["hotel"][1]["roomInfo"][0]["roomBasicInfo"]["roomName"]
planName=res["hotels"][0]["hotel"][1]["roomInfo"][0]["roomBasicInfo"]["planName"]
stayDate=res["hotels"][0]["hotel"][1]["roomInfo"][1]["dailyCharge"]["stayDate"]
totalCrg=res["hotels"][0]["hotel"][1]["roomInfo"][1]["dailyCharge"]["total"]
planUrl=res["hotels"][0]["hotel"][1]["roomInfo"][0]["roomBasicInfo"]["reserveUrl"]
allplanUrl=res["hotels"][0]["hotel"][0]["hotelBasicInfo"]["planListUrl"]
txt=""
txt = txt + '\r\n' \
+ "宿名: " + hotelName + '\r\n' \
+ "部屋名: " + roomName + '\r\n' \
+ "プラン名: " + planName + '\r\n' \
+ "宿泊日: " + stayDate + '\r\n' \
+ "価格: " + str(totalCrg) + "円" + '\r\n' \
+ "予約ページURL: " + planUrl + '\r\n' \
+ "プラン一覧URL: " + allplanUrl
print(txt)
time.sleep(2)
if __name__=='__main__':
search()
<結果>
宿名: 星野リゾート リゾナーレ小浜島<小浜島>
部屋名: スーペリアスイート
プラン名: 特別優待プラン<朝食付>
宿泊日: 2023-06-17
価格: 78300円
予約ページURL: https://img.travel.rakuten.co.jp/image/tr/api/re/IdsCY/?f_no=178403&f_syu=ss4&f_hi1=2023-06-17&f_hi2=2023-06-18&f_heya_su=1&f_otona_su=2&f_s1=0&f_s2=0&f_y1=0&f_y2=0&f_y3=0&f_y4=0&f_camp_id=5566607
プラン一覧URL: https://img.travel.rakuten.co.jp/image/tr/api/re/vFumt/?f_no=178403&f_flg=PLAN
.....
.....(中略)
.....
宿名: 星野リゾート リゾナーレ小浜島<小浜島>
部屋名: スーペリアスイート
プラン名: 特別優待プラン<朝食付>
宿泊日: 2023-09-09
価格: 69300円
予約ページURL: https://img.travel.rakuten.co.jp/image/tr/api/re/IdsCY/?f_no=178403&f_syu=ss4&f_hi1=2023-09-09&f_hi2=2023-09-10&f_heya_su=1&f_otona_su=2&f_s1=0&f_s2=0&f_y1=0&f_y2=0&f_y3=0&f_y4=0&f_camp_id=5566607
プラン一覧URL: https://img.travel.rakuten.co.jp/image/tr/api/re/vFumt/?f_no=178403&f_flg=PLAN
3か月先までの空き室情報が取得できました(^▽^)
リンク