Skip to main content

ferdamalastofa

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

معلومات المصدر

المستودع
jokull/icelandic-data
آخر نشاط في المصدر
١٠ سبتمبر ٢٠٢٦ في ١٥:٠٢
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٥٤
التفرعات
٤

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
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%
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub