From 17d203575c5888c2259c85a503487c241634f8bc Mon Sep 17 00:00:00 2001 From: Lea Date: Tue, 10 Sep 2024 21:02:23 +0200 Subject: [PATCH] implement basic caching mechanism --- .gitignore | 3 +- app.py | 3 +- arztapi/APIHandler.py | 85 ++++++++++++++++++++++++++++++------------- 3 files changed, 62 insertions(+), 29 deletions(-) diff --git a/.gitignore b/.gitignore index a903597..7a07c64 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ __pycache__ app-2.2.0.js package-lock.json -node_modules \ No newline at end of file +node_modules +_therapydb.cache \ No newline at end of file diff --git a/app.py b/app.py index 854913e..c78faa9 100644 --- a/app.py +++ b/app.py @@ -60,8 +60,7 @@ def search_for_doctors_with_params(): # Calculate the required base64 value why so ever base64_value = api_handler.calculate_req_value_base64(float(location_match["lat"]), float(location_match["lon"])) # Get the general list of doctors - api_handler.get_list_of_doctors(float(location_match["lat"]), float(location_match["lon"]), base64_value, - therapy_types, therapy_age_range, therapy_setting) + api_handler.get_list_of_doctors(float(location_match["lat"]), float(location_match["lon"]), base64_value, therapy_types, therapy_age_range, therapy_setting, amount_of_weeks) # Get their information api_handler.get_general_doctor_information() # Filter for the distance diff --git a/arztapi/APIHandler.py b/arztapi/APIHandler.py index 0796921..c567c79 100644 --- a/arztapi/APIHandler.py +++ b/arztapi/APIHandler.py @@ -3,6 +3,7 @@ from typing import List import requests from requests import JSONDecodeError import base64 +import shelve from datetime import datetime, timedelta from arztapi.ArztPraxisDatas import ArztPraxisDatas from arztapi.DoctorInformation import DoctorInformation, PhoneTime @@ -17,10 +18,12 @@ class APIHandler: def __init__(self): # Base URL as given by the base website self.base_api_url = "https://arztsuche.116117.de/api/" + self.json_data = {} # Containers for phone times, general doctor information and processed phone times of doctors self.phone_times = [] self.general_information = [] self.processed_doctor_phone_times = [] + self._cache = shelve.open("_therapydb.cache") def get_lat_lon_location_list(self, location): """ @@ -57,34 +60,12 @@ class APIHandler: except JSONDecodeError: return None - def get_list_of_doctors(self, lat, lon, req_val_base64, therapy_types, therapy_age, - therapy_setting) -> ArztPraxisDatas: - """ - - :param lat: Latitude as given by location API - :param lon: Longitude as given by location API - :param req_val_base64: base64 value required for API access (is this a token?) - :param therapy_types: Therapy types of interest - :param therapy_age: Therapy age range of interest - :param therapy_setting: Therapy setting of interest - :return: Relevant doctor/therapist data - """ - - # API path for doctor data - api_path = self.base_api_url + "data" - headers = { - "Accept": "application/json", - "Accept-Language": "de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7", - # Authorization header gathered by initial cURLing - "Authorization": "Basic YmRwczpma3I0OTNtdmdfZg==", - "Connection": "keep-alive", - # Calculated base64 value based on latitude and longitude - "req-val": req_val_base64, - } + def get_list_of_doctors(self, lat, lon, req_val_base64, therapy_types, therapy_age, therapy_setting, + amount_of_weeks) -> ArztPraxisDatas: # Data object as built by the original website, some fields might not be plausible or known (since there is no # API documentation itself available - json_data = { + self.json_data = { # TODO: Find out what r means "r": 900, "lat": lat, @@ -122,7 +103,46 @@ class APIHandler: "viaDeeplink": False, } - response = requests.post(api_path, headers=headers, json=json_data) + amount_of_days = amount_of_weeks * 7 + cache_data = self.get_current_doctor_information_data_in_cache_with_time_check(amount_of_days) + + if cache_data: + print("using cached data") + self.phone_times = cache_data + + else: + print("call api") + self.get_list_of_doctors_from_api(lat, lon, req_val_base64, therapy_types, therapy_age, therapy_setting) + self.set_current_doctor_information_data_in_cache() + + def get_list_of_doctors_from_api(self, lat, lon, req_val_base64, therapy_types, therapy_age, + therapy_setting) -> ArztPraxisDatas: + """ + + :param lat: Latitude as given by location API + :param lon: Longitude as given by location API + :param req_val_base64: base64 value required for API access (is this a token?) + :param therapy_types: Therapy types of interest + :param therapy_age: Therapy age range of interest + :param therapy_setting: Therapy setting of interest + :return: Relevant doctor/therapist data + """ + + # API path for doctor data + api_path = self.base_api_url + "data" + headers = { + "Accept": "application/json", + "Accept-Language": "de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7", + # Authorization header gathered by initial cURLing + "Authorization": "Basic YmRwczpma3I0OTNtdmdfZg==", + "Connection": "keep-alive", + # Calculated base64 value based on latitude and longitude + "req-val": req_val_base64, + } + + + + response = requests.post(api_path, headers=headers, json=self.json_data) # Check for HTTP errors response.raise_for_status() # Convert phone times to data format as input validation, save as class variable for further processing @@ -130,6 +150,19 @@ class APIHandler: # Return result for processing by caller return self.phone_times + def get_current_doctor_information_data_in_cache_with_time_check(self, amount_of_days): + cached_data = self._cache.get(str(self.json_data)) + if cached_data: + cache_timestamp = cached_data["timestamp"] + current_date = datetime.now() + time_difference = current_date - cache_timestamp + if time_difference.days <= amount_of_days: + return cached_data["data"] + + def set_current_doctor_information_data_in_cache(self): + current_date = datetime.now() + self._cache[str(self.json_data)] = {"timestamp": current_date, "data": self.phone_times} + def get_general_doctor_information(self) -> List[DoctorInformation]: """ Transform and filter data to more usable format: Check for phone times and collect general doctor information