Skip to main content

ferdamalastofa

Icelandic Tourist Board — Keflavík passenger counts by nationality and month, flights, accommodation, tourism stats via Power BI.

Datos de origen

Repositorio
jokull/icelandic-data
Última actividad en el origen
10 de septiembre de 2026 a las 15:02
Idioma detectado de SKILL.md
inglés
Estrellas
54
Forks
4

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
ferdamalastofa
description
Icelandic Tourist Board — Keflavík passenger counts by nationality and month, flights, accommodation, tourism stats via Power BI.
# Ferðamálastofa (Icelandic Tourist Board) **Requires:** Tier 2 (browser) — Power BI capture needs Chromium: `uv run playwright install chromium`. Inbound tourism statistics via Power BI dashboard scraping. Passenger counts through Keflavík airport by nationality, month, and year. ## Data Source **Dashboard URL:** `https://www.maelabordferdathjonustunnar.is/` **Embed backend:** `ferdapbi.azurewebsites.net` (Azure web app generating Power BI embed tokens) The dashboard embeds Power BI reports via `ferdapbi.azurewebsites.net/embed/{reportId}`. Data must be extracted by intercepting Power BI API calls within the iframe. ### Power BI Report IDs | Report ID | Page | Description | |-----------|------|-------------| | `1fa56a04-3340-46c5-a36b-f9dde4ce0b92` | `/fjoldi-farthega-um-keflavik` | Passenger counts by nationality | | `34af65b4-b68d-4309-a17a-5e9d4632b55c` | `/hotel` | Hotel guest nights and occupancy | | `7cf5f866-459c-4873-947c-082d8a216ea9` | `/allir-gististadir` | All accommodation types | | `ae74ab2c-4b1a-4a5c-bf4f-a8ffdda1801f` | `/dvalarlengd-og-gistimati` | Length of stay and accommodation type | ## Available Dashboards ### Samgöngur (Transport) | Page | URL path | Description | |------|----------|-------------| | Þjóðernaskipting og fjöldi um Keflavík | `/fjoldi-farthega-um-keflavik` | **Primary** — passenger counts by nationality | | Framboð á flugi frá Keflavík | `/frambod-a-flugi-fra-keflavik` | Flight supply from Keflavík | | Verð á flugi | `/verd-a-flugi` | Flight prices | | Tölfræðivísar norrænna flugfélaga | `/tolfraedivisar-norraenna-flugfelaga` | Nordic airline statistics | | Skemmtiferðaskip | `/skemmtiferdaskip` | Cruise ships | | Norróna | `/norrona` | Norröna ferry | ### Ferðamenn (Tourists) | Page | URL path | Description | |------|----------|-------------| | Aldur, kyn og fleiri bakgrunnsbreytur | `/aldur-kyn-og-fleiri-bakgrunnsbreytur` | Age, gender, demographics | | Tilgangur ferðar og heimsóttir landshlutar | `/tilgangur-ferdar-og-heimsottir-landshlutar` | Purpose of travel, regions visited | | Ánægja og upplifun | `/anaegja-og-upplifun` | Satisfaction and experience | | Fjöldi gesta á áfangastöðum | `/fjoldi-gesta-a-afangastodum` | Visitors at destinations | | Umferðarslys erlendra ferðamanna | `/umferdarslys-erlendra-ferdamanna` | Tourist traffic accidents | | Spá um fjölda erlendra farþega | `/spa-um-fjolda-erlendra-farthega` | Forecast of foreign passengers | ### Gisting (Accommodation) | Page | URL path | Description | |------|----------|-------------| | Hótel | `/hotel` | Hotel statistics | | Verð á hótelgistingu | `/verd-a-hotelgistingu` | Hotel prices | | Allir gististaðir | `/allir-gististadir` | All accommodation types | | Dvalarlengd og gistimáti | `/dvalarlengd-og-gistimati` | Length of stay and accommodation type | ### Rekstur & efnahagur (Operations & Economy) (Available but not yet explored) ## Key Data: Passenger Numbers (fjoldi-farthega-um-keflavik) ### Metrics | Metric | Icelandic | Description | |--------|-----------|-------------| | Heildarfjöldi | Total passengers | All passengers through Keflavík in period | | Fjöldi erlendra farþega | Foreign passengers | Non-Icelandic passengers (count + %) | | Fjöldi Íslendinga | Icelandic passengers | Icelandic passengers (count + %) | | Uppsafnaður heildarfjöldi | Cumulative YTD | Year-to-date total | ### Filters/Slicers | Filter | Icelandic | Values | |--------|-----------|--------| | Markaðssvæði | Market area | All, Europe, North America, Asia, etc. | | Ár | Year | 2016–2026+ | | Mánuður | Month | janúar–desember | ### Report Tabs | Tab | Description | |-----|-------------| | Fjöldi í [mánuður] | Monthly breakdown by nationality with YoY comparison | | Yfirlit | Overview/summary | | Árstíðardreifing | Seasonal distribution | ### Nationality Breakdown Data includes passenger counts by nationality with flags. Top nationalities (Jan 2026 sample): Ísland, Bandaríkin, Bretland, Kína, Ítalía, Þýskaland, Frakkland, Pólland, Suður-Kórea, Ástralía/Nýja-Sjáland, Japan, Spánn, Suður-Ameríka, Kanada, etc. ## Key Data: Stays (dvalarlengd-og-gistimati) Report ID: `ae74ab2c-4b1a-4a5c-bf4f-a8ffdda1801f` Tourist length of stay and accommodation type from Ferðamálastofa's border survey (landamærarannsókn). ### Metrics | Metric | Icelandic | Description | |--------|-----------|-------------| | Meðalfjöldi gistinátta | Average guest nights | Monthly average nights stayed, 2024–2026 | | Sundurliðun eftir bakgrunni | Breakdown by demographics | Average nights by age group (15–24, 25–34, ..., 65+) | | Dvalarlengd | Length of stay distribution | % of tourists by stay duration (0, 1, 2–3, 4–5, 6–8, 9–12, 13+ days) | | Sundurliðun eftir tegund gistingar | By accommodation type | Usage % and median stay by type | ### Accommodation Types (tegund gistingar) | Icelandic | English | Category | |-----------|---------|----------| | Vinir/ættingjar, möbilhúsi… | Friends/family, motorhome | Ekki greitt fyrir náttuvöl | | Tjaldstæði, ekki greitt f… | Campsite (unpaid) | Ekki greitt fyrir náttuvöl | | Önnur gisting | Other accommodation | Ekki greitt fyrir náttuvöl | | Hótel, gistiheimili | Hotel, guesthouse | Greitt fyrir náttuvöl | | Ibúðagisting | Apartment rental (Airbnb etc.) | Greitt fyrir náttuvöl | | Hostel | Hostel | Greitt fyrir náttuvöl | | Tjald greitt fyri… | Campsite (paid) | Greitt fyrir náttuvöl | | Húsbíll/tjaldv… | Campervan/motorhome | Greitt fyrir náttuvöl | | Sumarhús eða skálar | Summer houses or huts | Greitt fyrir náttuvöl | | Húsbíll greitt fyri… | Campervan (paid) | Greitt fyrir náttuvöl | ### Filters/Slicers | Filter | Icelandic | Values | |--------|-----------|--------| | Bakgrunnsbreytur | Background variable | Aldur (age), Kyn (gender), etc. | | Ár | Year | Multiple selections (2024, 2025, 2026) | | Mánuður | Month | All, or specific months | ### Sample Output ``` age_group,avg_nights 15-24 ára,6.8 25-34 ára,7.0 35-44 ára,6.7 45-54 ára,6.8 55-64 ára,6.9 65 ára og eldri,7.2 stay_duration,pct Gisti ekki,0.6% 1 dagur,2.7% 2-3 dagar,16.8% 4-5 dagar,25.2% 6-8 dagar,30.6% 9-12 dagar,16.0% 13 dagar eða meira,8.2% ``` ## Extraction Method Use Playwright to load the parent page and intercept Power BI `executeQueries` API calls: ```python import asyncio import json from playwright.async_api import async_playwright BASE_URL = "https://www.maelabordferdathjonustunnar.is" async def scrape_passenger_data(page_path="/fjoldi-farthega-um-keflavik"): async with async_playwright() as p: browser = await p.chromium.launch(headless=True) page = await browser.new_page() query_results = [] async def handle_response(response): url = response.url # Power BI data queries go through these endpoints if 'querydata' in url.lower() or 'public/reports' in url.lower(): try: if response.status == 200: content_type = response.headers.get('content-type', '') if 'json' in content_type: body = await response.json() query_results.append({ 'url': url, 'data': body }) except Exception: pass page.on('response', handle_response) await page.goto( f"{BASE_URL}{page_path}", wait_until='networkidle', timeout=60000 ) # Power BI reports load async — wait for data queries await asyncio.sleep(10) await browser.close() return query_results ``` ## Parsing Power BI Response Power BI embedded reports use a compressed DSR (DataShapeResult) format: ```python def parse_powerbi_results(results): """Extract tabular data from Power BI query results.""" rows = [] for result in results: data = result.get('data', {}) if 'results' not in data: continue for res in data['results']: dsr = res.get('result', {}).get('data', {}).get('dsr', {}) for ds in dsr.get('DS', []): for ph in ds.get('PH', []): dm = ph.get('DM0', []) # Value dictionaries for compressed references value_dicts = dsr.get('ValueDicts', {}) for row in dm: # G0, G1, ... = dimension values (nationality, month, etc.) # C = compressed reference indices into ValueDicts # X[n].M0 = measure values # R = repeat flags (inherit from previous row) rows.append(row) return rows def decompress_dsr(dsr_data): """Decompress Power BI DSR format with ValueDicts and repeat flags. Power BI compresses data by: 1. ValueDicts: shared string arrays referenced by index (C field) 2. R (repeat): bitmask indicating which G values repeat from previous row 3. Ø (null): marks null/missing values """ value_dicts = dsr_data.get('ValueDicts', {}) all_rows = [] for ds in dsr_data.get('DS', []): for ph in ds.get('PH', []): dm = ph.get('DM0', []) prev_values = {} for row in dm: current = {} repeat_mask = row.get('R', 0) # Resolve G (group/dimension) values for i in range(10): # G0..G9 key = f'G{i}' if key in row: current[key] = row[key] prev_values[key] = row[key] elif repeat_mask & (1 << i) and key in prev_values: current[key] = prev_values[key] # Resolve C (compressed dict reference) values if 'C' in row: for idx, val in enumerate(row['C']): dict_key = f'D{idx}' if dict_key in value_dicts and isinstance(val, int): current[f'C{idx}'] = value_dicts[dict_key][val] else: current[f'C{idx}'] = val # Extract X (measure) values x_data = row.get('X', []) for xi, x in enumerate(x_data): if isinstance(x, dict): for mk, mv in x.items(): current[f'X{xi}_{mk}'] = mv all_rows.append(current) return all_rows ``` ## Switching Report Tabs via Interaction The dashboard has multiple tabs (Fjöldi, Yfirlit, Árstíðardreifing). To load data from different tabs, click the tab buttons: ```python async def click_tab(page, tab_name): """Click a Power BI report tab within the iframe.""" # Find the Power BI iframe iframe_element = await page.query_selector('iframe[src*="ferdapbi"]') if not iframe_element: return frame = await iframe_element.content_frame() if not frame: return # Click the tab button by text button = await frame.query_selector(f'button:has-text("{tab_name}")') if button: await button.click() await asyncio.sleep(5) # Wait for new data to load ``` ## Changing Filters (Year/Month) To scrape different time periods, interact with the Power BI slicers: ```python async def set_year_filter(frame, year): """Change the Ár (year) slicer in the Power BI report.""" # Find and click the year dropdown year_slicer = await frame.query_selector('[aria-label*="Ár"]') if year_slicer: await year_slicer.click() await asyncio.sleep(1) option = await frame.query_selector(f'[title="{year}"]') if option: await option.click() await asyncio.sleep(3) ``` ## Sample Output ``` month,year,nationality,passengers,yoy_change,yoy_pct 2026-01,2026,Ísland,43809,-3611,-8% 2026-01,2026,Bandaríkin,24069,-9066,-27% 2026-01,2026,Bretland,20973,+2244,+12% 2026-01,2026,Kína,8908,-764,-8% 2026-01,2026,Ítalía,7555,+5262,+229%
Ver en GitHub
Este SKILL.md es muy grande, por eso SkillsMP muestra aqui solo la primera seccion. Ver en GitHub