implement basic caching mechanism

This commit is contained in:
Lea 2024-09-10 21:02:23 +02:00
parent 955bb572a3
commit 17d203575c
3 changed files with 62 additions and 29 deletions

3
.gitignore vendored
View File

@ -4,4 +4,5 @@
__pycache__ __pycache__
app-2.2.0.js app-2.2.0.js
package-lock.json package-lock.json
node_modules node_modules
_therapydb.cache

3
app.py
View File

@ -60,8 +60,7 @@ def search_for_doctors_with_params():
# Calculate the required base64 value why so ever # Calculate the required base64 value why so ever
base64_value = api_handler.calculate_req_value_base64(float(location_match["lat"]), float(location_match["lon"])) base64_value = api_handler.calculate_req_value_base64(float(location_match["lat"]), float(location_match["lon"]))
# Get the general list of doctors # Get the general list of doctors
api_handler.get_list_of_doctors(float(location_match["lat"]), float(location_match["lon"]), base64_value, 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)
therapy_types, therapy_age_range, therapy_setting)
# Get their information # Get their information
api_handler.get_general_doctor_information() api_handler.get_general_doctor_information()
# Filter for the distance # Filter for the distance

View File

@ -3,6 +3,7 @@ from typing import List
import requests import requests
from requests import JSONDecodeError from requests import JSONDecodeError
import base64 import base64
import shelve
from datetime import datetime, timedelta from datetime import datetime, timedelta
from arztapi.ArztPraxisDatas import ArztPraxisDatas from arztapi.ArztPraxisDatas import ArztPraxisDatas
from arztapi.DoctorInformation import DoctorInformation, PhoneTime from arztapi.DoctorInformation import DoctorInformation, PhoneTime
@ -17,10 +18,12 @@ class APIHandler:
def __init__(self): def __init__(self):
# Base URL as given by the base website # Base URL as given by the base website
self.base_api_url = "https://arztsuche.116117.de/api/" 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 # Containers for phone times, general doctor information and processed phone times of doctors
self.phone_times = [] self.phone_times = []
self.general_information = [] self.general_information = []
self.processed_doctor_phone_times = [] self.processed_doctor_phone_times = []
self._cache = shelve.open("_therapydb.cache")
def get_lat_lon_location_list(self, location): def get_lat_lon_location_list(self, location):
""" """
@ -57,34 +60,12 @@ class APIHandler:
except JSONDecodeError: except JSONDecodeError:
return None return None
def get_list_of_doctors(self, lat, lon, req_val_base64, therapy_types, therapy_age, def get_list_of_doctors(self, lat, lon, req_val_base64, therapy_types, therapy_age, therapy_setting,
therapy_setting) -> ArztPraxisDatas: amount_of_weeks) -> 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,
}
# Data object as built by the original website, some fields might not be plausible or known (since there is no # Data object as built by the original website, some fields might not be plausible or known (since there is no
# API documentation itself available # API documentation itself available
json_data = { self.json_data = {
# TODO: Find out what r means # TODO: Find out what r means
"r": 900, "r": 900,
"lat": lat, "lat": lat,
@ -122,7 +103,46 @@ class APIHandler:
"viaDeeplink": False, "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 # Check for HTTP errors
response.raise_for_status() response.raise_for_status()
# Convert phone times to data format as input validation, save as class variable for further processing # 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 result for processing by caller
return self.phone_times 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]: 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 Transform and filter data to more usable format: Check for phone times and collect general doctor information