Skip to content

Instantly share code, notes, and snippets.

@iSWORD
Last active February 13, 2024 09:36
Show Gist options
  • Save iSWORD/727084395fc194782c795f6125e3eaf5 to your computer and use it in GitHub Desktop.
Save iSWORD/727084395fc194782c795f6125e3eaf5 to your computer and use it in GitHub Desktop.
GGD Reisvaccinaties Afspraak
import requests
import re
import time
import datetime
def get_page():
url = 'https://www.ggdreisvaccinaties.nl/afspraak-maken'
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:121.0) Gecko/20100101 Firefox/121.0',
'Accept': '*/*',
'Accept-Language': 'en-US,en;q=0.5',
'Connection': 'keep-alive',
'Referer': 'https://www.ggdreisvaccinaties.nl',
}
return requests.get(url, headers=headers)
def parse_centers(page_contents):
regex = r"https:\/\/(\w+).vaccinatieregister\.nl\/onlineagenda\/([\w-]+)"
matches = re.finditer(regex, page_contents, re.MULTILINE)
for matchNum, match in enumerate(matches, start=1):
yield match.groups()
def get_location_postcode(loc_prefix, loc_uuid):
url = f'https://{loc_prefix}.vaccinatieregister.nl/onlineagenda/{loc_uuid}'
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:121.0) Gecko/20100101 Firefox/121.0',
'Accept': '*/*',
'Accept-Language': 'en-US,en;q=0.5',
'Connection': 'keep-alive',
}
regex = r"\"send-postcode\">(\w+)<"
response = requests.get(url, headers=headers)
matches = re.finditer(regex, response.text, re.MULTILINE)
return next(matches).group(1)
def get_appointments(loc_prefix, loc_uuid, consult_type, persons, countries, days, start, end, country):
start = int(time.mktime(datetime.datetime.strptime(start, '%d/%m/%Y').timetuple()))
end = int(time.mktime(datetime.datetime.strptime(end, '%d/%m/%Y').timetuple()))
url = f'https://{loc_prefix}.vaccinatieregister.nl/afspraken/api/v1/voorstellen'
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:121.0) Gecko/20100101 Firefox/121.0',
'Accept': '*/*',
'Accept-Language': 'en-US,en;q=0.5',
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
'Connection': 'keep-alive',
'Referer': f'https://{loc_prefix}.vaccinatieregister.nl/onlineagenda/{loc_uuid}',
}
params = {
'loc_uuid': loc_uuid,
'consulttype': consult_type,
'aantal': persons,
'aantal_landen': countries,
'reisdagen': days,
'start': start,
'einde': end,
'land': country,
'_': '1705651286889',
}
return requests.get(url, params=params, headers=headers)
consult_type_map = {
'57cf6d8e-4d55-f397-8f2b-14ca425405e4': 1101, # travel less than 2.5 months
'ecd6faed-99b3-26bf-db9b-c4ecc610c81f': 1101, # travel less than 2.5 months
'2ca286b2-b749-b027-7f6e-80c4706152b7': 3, # travelling, may need a vaccination
}
countries_map = {
'Abu Dhabi (Verenigde Arabische Emiraten)': 253,
'Afghanistan': 1,
'Åland': 2,
'Albanië': 3,
'Algerije': 4,
'Amerikaanse Maagdeneilanden': 5,
'Amerikaans-Samoa': 6,
'Andorra': 7,
'Angola': 8,
'Anguilla': 9,
'Antarctica': 10,
'Antigua en Barbuda': 11,
'Antillen (voormalige Nederlands)': 506,
'Argentinië': 12,
'Armenië': 13,
'Aruba': 14,
'Australië': 15,
'Azerbeidzjan': 16,
'Azoren': 507,
'Bahama\'s': 17,
'Bahrein': 18,
'Bangladesh': 19,
'Barbados': 20,
'Barbuda': 254,
'België': 21,
'Belize': 22,
'Benin': 23,
'Bermuda': 24,
'Bhutan': 25,
'Bolivia': 26,
'Bonaire, Sint Eustatius en Saba': 27,
'Bosnië en Herzegovina': 28,
'Botswana': 29,
'Bouveteiland': 30,
'Brazilië': 31,
'Britse Maagdeneilanden': 32,
'Brits Indische Oceaanterritorium': 33,
'Brunei': 34,
'Bulgarije': 35,
'Burkina Faso': 36,
'Burundi': 37,
'Cambodja': 38,
'Canada': 39,
'Canarische eilanden': 508,
'Centraal-Afrikaanse Republiek': 40,
'Chagos Archipel (Brits territorium in de Indische oceaan)': 509,
'Chili': 41,
'China': 42,
'China-Hongkong': 510,
'China-Macau': 511,
'Christmaseiland': 43,
'Cocoseilanden': 44,
'Colombia': 45,
'Comoren': 46,
'Congo-Brazzaville': 47,
'Congo-Kinshasa': 48,
'Cookeilanden': 49,
'Coral Sea eilanden': 512,
'Costa Rica': 50,
'Cuba': 51,
'Curaçao': 52,
'Cyprus': 53,
'Denemarken': 54,
'Djibouti': 55,
'Dominica': 56,
'Dominicaanse Republiek': 57,
'Dubai (Verenigde Arabische Emiraten)': 513,
'Duitsland': 58,
'Ecuador': 59,
'Egypte': 60,
'El Salvador': 61,
'Equatoriaal-Guinea': 62,
'Eritrea': 63,
'Estland': 64,
'Ethiopië': 65,
'Faeröer': 66,
'Falklandeilanden': 67,
'Fiji': 68,
'Filipijnen': 69,
'Finland': 70,
'Frankrijk': 71,
'Franse Antillen': 514,
'Franse Zuidelijke en Antarctische Gebieden': 72,
'Frans-Guyana': 73,
'Frans-Polynesië': 74,
'Fujairah (Verenigde Arabische Emiraten)': 515,
'Gabon': 75,
'Galapagos eilanden': 516,
'Gambia': 76,
'Georgië': 77,
'Ghana': 78,
'Gibraltar': 79,
'Grenada': 80,
'Griekenland': 81,
'Groenland': 82,
'Guadeloupe': 83,
'Guam': 84,
'Guatemala': 85,
'Guernsey': 86,
'Guinee': 87,
'Guinee-Bissau': 88,
'Guinee Equatoriaal': 517,
'Guyana': 89,
'Guyana Frans': 518,
'Haïti': 90,
'Hawaii': 519,
'Heard en McDonaldeilanden': 91,
'Honduras': 92,
'Hongarije': 93,
'Hongkong': 94,
'Ierland': 95,
'IJsland': 96,
'India': 97,
'Indonesië': 98,
'Irak': 99,
'Iran': 100,
'Israël': 101,
'Italië': 102,
'Ivoorkust': 103,
'Jamaica': 104,
'Japan': 105,
'Jemen': 106,
'Jersey': 107,
'Jordanië': 108,
'Kaaimaneilanden': 109,
'Kaapverdië': 110,
'Kameroen': 111,
'Kazachstan': 112,
'Kenia': 113,
'Kirgizië': 114,
'Kirgizstan (Kirgizië)': 520,
'Kiribati': 115,
'Kleine Pacifische eilanden van de V.S.': 116,
'Koeweit': 117,
'Kosovo': 541,
'Kroatië': 118,
'Laos': 119,
'Lesotho': 120,
'Letland': 121,
'Libanon': 122,
'Liberia': 123,
'Libië': 124,
'Liechtenstein': 125,
'Litouwen': 126,
'Luxemburg': 127,
'Macau': 128,
'Madagaskar': 130,
'Madeira (Portugal)': 521,
'Malawi': 131,
'Maldiven': 132,
'Maleisië': 133,
'Mali': 134,
'Malta': 135,
'Man': 136,
'Marokko': 137,
'Marshalleilanden': 138,
'Martinique': 139,
'Mauritanië': 140,
'Mauritius': 141,
'Mayotte': 142,
'Mexico': 143,
'Micronesia': 144,
'Moldavië': 145,
'Monaco': 146,
'Mongolië': 147,
'Montenegro': 148,
'Montserrat': 149,
'Mozambique': 150,
'Myanmar': 151,
'Namibië': 152,
'Nauru': 153,
'Nederland': 154,
'Nederlandse Antillen (voormalig)': 522,
'Nepal': 155,
'Nicaragua': 156,
'Nieuw-Caledonië': 157,
'Nieuw-Zeeland': 158,
'Niger': 159,
'Nigeria': 160,
'Niue': 161,
'Noordelijke Marianen': 162,
'Noord-Korea': 163,
'Noord-Macedonië': 129,
'Noorwegen': 164,
'Norfolk': 165,
'Oeganda': 166,
'Oekraïne': 167,
'Oezbekistan': 168,
'Oman': 169,
'Onbekend': 255,
'Onbekend': 251,
'Oostenrijk': 170,
'Oost-Timor': 171,
'Paaseiland': 523,
'Pakistan': 172,
'Palau': 173,
'Palestina': 174,
'Panama': 175,
'Papoea-Nieuw-Guinea': 176,
'Paraguay': 177,
'Peru': 178,
'Pitcairneilanden': 179,
'Polen': 180,
'Portugal': 181,
'Principe': 524,
'Puerto Rico': 182,
'Qatar': 183,
'Ras al Khaimah (Verenigde Arabische Emiraten)': 525,
'Réunion': 184,
'Roemenië': 185,
'Rusland': 186,
'Rwanda': 187,
'Saint-Barthélemy': 188,
'Saint Kitts en Nevis': 189,
'Saint Lucia': 190,
'Saint-Pierre en Miquelon': 191,
'Saint Vincent en de Grenadines': 192,
'Salomonseilanden': 193,
'Samoa': 194,
'Samoa amerikaans': 526,
'San Marino': 195,
'Saoedi-Arabië': 527,
'Saoedi-Arabië': 196,
'Sao Tomé en Principe': 197,
'Senegal': 198,
'Servië': 199,
'Seychellen': 200,
'Sharjah (Verenigde Arabische Emiraten)': 528,
'Sierra Leone': 201,
'Singapore': 202,
'Sint-Helena, Ascension en Tristan da Cunha': 203,
'Sint Maarten': 205,
'Sint-Maarten': 204,
'Slovenië': 206,
'Slowakije': 207,
'Soedan': 208,
'Solomons-eilanden (Brits overzees gebied)': 529,
'Somalië': 209,
'Spanje': 210,
'Spitsbergen en Jan Mayen': 211,
'Sri Lanka': 212,
'St Barthelemy (Franse Antillen)': 530,
'St Eustatius (voormalige Nederlandse Antillen)': 531,
'St Martin (Franse Antillen)': 532,
'Suriname': 213,
'Swaziland': 214,
'Syrië': 215,
'Tadzjikistan': 216,
'Tahiti (FransPolynesië)': 533,
'Taiwan': 217,
'Tanzania': 218,
'Thailand': 219,
'Togo': 220,
'Tokelau': 221,
'Tonga': 222,
'Trinidad en Tobago': 223,
'Trucial Staten (Verenigde Arabische Emiraten)': 534,
'Tsjaad': 224,
'Tsjechië': 225,
'Tunesië': 226,
'Turkije': 227,
'Turkmenistan': 228,
'Turks- en Caicoseilanden': 229,
'Tuvalu': 230,
'Umm al Qawain (Verenigde Arabische Emiraten)': 535,
'Uruguay': 231,
'Vanuatu': 232,
'Vaticaanstad': 233,
'Venezuela': 234,
'Verenigde Arabische Emiraten': 235,
'Verenigde Staten': 236,
'Verenigd Koninkrijk': 237,
'Vietnam': 238,
'Virgin eilanden (Britse)': 536,
'Wake Island': 537,
'Wallis en Futuna': 239,
'Westelijke Sahara': 240,
'Wit-Rusland': 241,
'Zambia': 242,
'Zimbabwe': 243,
'Zuid-Afrika': 244,
'Zuid-Georgia en de Zuidelijke Sandwicheilanden': 245,
'Zuid-Korea': 246,
'Zuid-Soedan': 247,
'Zweden': 248,
'Zwitserland': 249,
}
# page = get_page() # FIXME: there's actually more centers than this. i need to parse ajax responses too.
"""
travel vaccination: 85
travel vaccination (only option): 6
travel less than 2.5 months: 1101
travelling, may need a vaccination: 3
"""
centers_map = [
('gzhz', '7b5bf83a-084b-4f14-8994-8a8b2ad3994f', 85),
('gbzo', '57cf6d8e-4d55-f397-8f2b-14ca425405e4', 1101),
('gbzo', 'ecd6faed-99b3-26bf-db9b-c4ecc610c81f', 1101),
('ggdd', '2ca286b2-b749-b027-7f6e-80c4706152b7', 3),
('gfle', 'e24e4076-504d-1a1a-6eba-866bf3f25cdd', 3),
('gfle', 'd74ea6ca-4fc1-4ef7-d060-e941e8790dcd', 3),
('gfle', '8860a2aa-2d4d-0e45-27d8-f9905aa3f543', 3),
('ggdf', '2addd92c-bab9-0633-aecd-fbbf3fad9260', 3),
('ggdf', 'fcf40683-ab28-ea23-3bf6-f10ca6d1f9bf', 3),
('ggdf', '796b92f7-5674-2207-5ffc-02e367d36861', 3),
('gelm', 'c1b16326-c2d9-ded3-77de-428865943746', 3),
('gelm', '2ca286b2-b749-b027-7f6e-80c4706152b7', 3),
('gelz', '9b672bf3-a2f3-d2da-bc6d-415d7fe65529', 3),
('gelz', '1c54ab6f-65fc-4b98-9711-03f51b1668b9', 3),
('gelz', 'ecc6be49-00b8-0c5b-e3f9-2419210a6c9b', 3),
('gelz', 'dd1165f4-de7f-0f41-17ae-b4181a3d01d1', 3),
('gelz', '42f331ae-315f-592a-004d-e1ebc72391a6', 3),
('ggdg', 'fc2cc32e-69a5-86aa-fc56-1891faa74914', 3),
('ggdh', '08202b63-81e2-4263-8718-c62b5489cad2', 3),
('ghvb', '6e2f12a4-c3cb-fa8a-e9d4-762f6eea377e', 3),
('ghvb', 'a0ecc120-dedc-b3f4-463a-8fa9baa406d5', 3),
('ghvb', 'e5a32abe-afd4-ac78-cd46-b254a7c41780', 3),
('ghvb', '2f544590-81ca-48aa-4ccf-fcb1020eaf78', 3),
('ghvb', 'eca67851-fe95-4847-a785-cfb99f793d85', 3),
('ghlm', '2e9fa10c-c202-4126-878a-bc8f75c77399', 6),
('ghlm', 'ce224400-4848-423b-b1a9-701a4676b530', 6),
('ghlm', 'ebecf0df-b6e0-49dd-99bd-67373facfbf6', 6),
('ghln', 'db5e6c68-d744-08b1-c066-4d473a83d71b', 6),
('ghln', '1c072eff-472d-0c19-c339-d3cdf82c3e1c', 6),
('ghln', '0802034a-bc84-3633-01b1-eaad39bf5c00', 6),
('ghln', '2647f2f2-d13f-a0eb-11b4-5f4a51001e5e', 6),
('rijs', 'a479c8f3-ed5e-d317-53e8-f9f17a611aaf', 3),
('rijs', '9abe75fa-a4ba-388b-b2fd-0eac33c2ecef', 3),
('ggdk', 'db5e6c68-d744-08b1-c066-4d473a83d71b', 3),
('ggdk', 'b8f5d82c-4f94-9385-66cc-ec7c523ce534', 3),
('ggdk', '396ccea3-56bd-08e0-2803-3eaee7e86704', 3),
('vrln', '279ec0fa-cb61-1e0a-cb6c-8816233e4990', 3),
('vrln', '8d1725eb-2480-dafc-c137-0e62f86a6bf3', 3),
('vrln', '834ee37f-2c65-7f57-be0c-a6f538b20cb2', 3),
('gnog', 'a5e14bc0-fb3d-5d7c-574a-09291db098c9', 3),
('gnog', 'ab7ad536-6131-aa4b-4aa3-b231793b9704', 3),
('gnog', '1aef9c19-ed03-2ba0-31dd-ed60c5a3fe0b', 3),
('gnog', 'db5e6c68-d744-08b1-c066-4d473a83d71b', 3),
('ggdu', 'cef22931-8c67-4b02-98ce-ee7705d96cf8', 3),
('ggdu', '370ab926-d0bc-4e40-8489-61a4a9273587', 3),
('ggdr', '9c1a5702-145b-267f-4b5d-a0aaf6cd9bc0', 3),
('gwbr', 'db5e6c68-d744-08b1-c066-4d473a83d71b', 3),
('gwbr', '9a8344cf-2f72-5e60-56c9-4da8330a5e68', 3),
('gwbr', 'b1b92e6a-29a4-45a0-aee1-1efb03d2f75c', 3),
('gzwl', 'db5e6c68-d744-08b1-c066-4d473a83d71b', 3),
('ggdz', 'db5e6c68-d744-08b1-c066-4d473a83d71b', 3),
('ggdz', 'a138fb3f-a067-8815-60d8-2095a55c3697', 3),
('ggdz', 'f0646cba-1f40-395c-d5f1-95ab6741b49e', 3),
]
persons = input('Number of people travelling: ')
countries = input('Number of countries being visited: ')
days = input('Number of days on vacation: ')
range_start = input('Start date for appointment lookup (format DD/MM/YYYY): ')
range_end = input('End date for appointment lookup (format DD/MM/YYYY): ')
country_name = input('Country name (in Dutch): ')
# for loc_prefix, loc_uuid in parse_centers(page.text):
for loc_prefix, loc_uuid, consult_type in centers_map:
appointments = get_appointments(
loc_prefix,
loc_uuid,
consult_type=consult_type,
persons=persons,
countries=countries,
days=days,
start=range_start,
end=range_end,
country=countries_map[country_name]
)
slots = appointments.json()['slots']
if slots:
print(f'Found {len(slots)} appointment(s) at:')
print(f'https://{loc_prefix}.vaccinatieregister.nl/onlineagenda/{loc_uuid}')
print(f'Postcode: ', get_location_postcode(loc_prefix, loc_uuid))
print("\n".join([f"- {slot['weekdag']} on {slot['datum']} at {slot['tijdstip']}" for slot in slots]))
print()
@iSWORD
Copy link
Author

iSWORD commented Jan 30, 2024

this could:

  • use a nice cli framework to also validate inputs
  • accept inputs from cli args using argparse
  • include a dockerfile to run anywhere
  • dynamically get centers, and if consult type not found in list, try from a list of common types

@iSWORD
Copy link
Author

iSWORD commented Jan 30, 2024

i made this before traveling to find an appointment in a GGD vaccination center. i thought i would publish it here for everyone else to use. i hope someone will find it useful!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment