{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Mit Binder oder Colab kann das Jupyter-Notebook interaktiv im Browser gestartet werden:\n", "\n", "[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/opendatazurich/opendatazurich.github.io/master?filepath=zt-api/ZuerichTourismusAPI-Beispiele.ipynb)\n", "\n", "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/opendatazurich/opendatazurich.github.io/blob/master/zt-api/ZuerichTourismusAPI-Beispiele.ipynb)\n", "\n", "\n", "\n", "# Python-Beispiele für das Zürich Tourismus API\n", "\n", "## Inhaltsverzeichnis\n", "\n", "1. [Restaurants vom Zürich Tourismus API auf einer Karte darstellen](#Restaurants-vom-Zürich-Tourismus-API-auf-einer-Karte-darstellen)\n", "1. [CSV Download](#CSV-Download)\n", "1. [Bilder zu einem Thema](#Bilder-zu-einem-Thema)\n", "1. [Kategorien der Elemente im API](#Kategorien-der-Elemente-im-API)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%pip install requests pandas folium branca anytree" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import requests\n", "import pandas as pd\n", "import folium\n", "import branca\n", "import anytree" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "SSL_VERIFY = False\n", "# evtl. SSL_VERIFY auf False setzen wenn die Verbindung zu https://www.zuerich.com nicht klappt (z.B. wegen Proxy)\n", "# Um die SSL Verifikation auszustellen, bitte die nächste Zeile einkommentieren (\"#\" entfernen)\n", "# SSL_VERIFY = False\n", "if not SSL_VERIFY:\n", " import urllib3\n", " urllib3.disable_warnings()\n", " \n", "def get_de(field):\n", " try:\n", " return field['de']\n", " except (KeyError, TypeError):\n", " try:\n", " return field['en']\n", " except (KeyError, TypeError):\n", " return field" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Restaurants vom Zürich Tourismus API auf einer Karte darstellen" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Daten von der API laden\n", "\n", "**Alle Elemente mit dem Tag \"gastronomy\" vom API abrufen**:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "headers = {'Accept': 'application/json'}\n", "r = requests.get('https://www.zuerich.com/en/api/v2/data?id=101', headers=headers, verify=SSL_VERIFY)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Die JSON Daten vom API in ein Python dictionary umwandeln:**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "data = r.json()\n", "data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Die Daten haben viele mehrsprachige Felder, der folgende Code holt sich jeweils die deutschen Inhalte:**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "de_data = [{k: get_de(v) for (k,v) in f.items()} for f in data]\n", "de_data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Die Daten in einem pandas DataFrame ablegen:**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df = pd.DataFrame(de_data)\n", "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Daten zur Karte hinzufügen\n", "\n", "`folium` ist ein Python Wrapper für OpenLayers. Der nachfolgende Code erstellt eine neue Karte und verwendet den Übersichtsplan als Hintergrund (eingebunden als WMS)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m = folium.Map(location=[47.36, 8.53], zoom_start=13, tiles=None)\n", "folium.raster_layers.WmsTileLayer(\n", " url='https://www.ogd.stadt-zuerich.ch/wms/geoportal/Basiskarte_Zuerich_Raster',\n", " layers='Basiskarte Zürich Raster',\n", " name='Zürich - Basiskarte',\n", " fmt='image/png',\n", " overlay=False,\n", " control=False,\n", " autoZindex=False,\n", ").add_to(m)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Nun iterieren wir über das pandas DataFrame und erstellen einen Marker für jedes Restaurant. Falls vorhanden wird ein Photo in den Beschreibungstext eingefügt." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "gastro = folium.FeatureGroup(\"Restaurants\")\n", "isna = df.isna()\n", "for i, row in df.iterrows():\n", " print(row['geoCoordinates'])\n", " print(row['name'])\n", " geo = row['geoCoordinates']\n", " if not isna.geoCoordinates[i]:\n", " print(\"%s, %s, %s\" % (float(geo['latitude']), float(geo['longitude']), row['name']))\n", " \n", " try:\n", " photo = row['photo'][0]['url']\n", " photo_html = f''\n", " except (IndexError, KeyError, TypeError):\n", " photo_html = ''\n", " html = (\n", " f'
{row[\"disambiguatingDescription\"]}
'\n", " )\n", " #popup = folium.Popup(branca.element.IFrame(html=html, width=420))\n", " gastro.add_child(folium.Marker(location=[float(geo['latitude']), float(geo['longitude'])], popup=html)) \n", "m.add_child(gastro)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Hier ist die fertige Karte:**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "folium.LayerControl().add_to(m)\n", "m" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## CSV Download\n", "\n", "Für die weitere Verarbeitung kann es nützlich sein, die Daten aus dem API in tabellarischer Form zu haben.\n", "Der nachfolgende Code wandelt das JSON vom API in ein CSV um (ohne jedoch alle Attribute zu _flatten_)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# download CSV\n", "import base64\n", "from IPython.display import HTML\n", "\n", "def create_download_link( df, title = \"Download CSV file\", filename = \"data.csv\"): \n", " csv = df.to_csv(None, index=False)\n", " b64 = base64.b64encode(csv.encode())\n", " payload = b64.decode()\n", " html = '