Web Scraping mit Azure Functions und Python

Seite 2: Konfigurieren einer Umgebung

Inhaltsverzeichnis

Eine Azure Function in der Cloud testen zu können, setzt eine Registrierung im Azure Cloud Portal sowie ein aktives Abonnement (Subscription) voraus. Die Registrierung ist grundsätzlich kostenlos, das komplette Angebot steht jedoch nur für einen Testzeitraum von 30 Tagen frei zur Verfügung. Dauerhaft kostenfrei bleiben nur einige Komponenten – für die Azure Functions und Cosmos DB fallen zugriffsabhängige Kosten an.

Zur Vorbereitung auf die Arbeit mit den Serverless-Funktionen gilt es, die lokale Entwicklungsumgebung zu konfigurieren und die folgenden Tools beziehungsweise Erweiterungen zu installieren:

  • Visual Studio Code
  • Azure Functions Core Tools, Version 3.x
  • die von Azure Functions unterstützte Python-Version (Im vorliegenden Beispiel Python 3.8)
  • Python- und Azure-Functions-Erweiterungen für Visual Studio Code

Unterstützt durch den Azure Function Wizard lässt sich in der vorkonfigurierten lokalen Entwicklungsumgebung ein neues Projekt mit dem Function HTTP Trigger anlegen. Der Trigger lässt sich über einen HTTP-Request auslösen, sodass sich auch die Ergebnisse der Azure Function schneller überprüfen und gegebenenfalls anpassen beziehungsweise ändern lassen.

Die wichtigsten Komponenten einer Azure Function sind die Datei mit dem Code in einer der unterstützten Programmiersprachen – im vorliegenden Python-Beispiel mit dem Default-Namen __init__.py – und die Datei mit den Konfigurationsinformationen function.json. Letztere definiert den Namen der Code-Datei (sogenannter Einstiegspunkt), den Trigger, die Abhängigkeiten sowie weitere Konfigurationseinstellungen der Function.

Jede Function verfügt nur über einen einzigen Trigger. Anhand der Konfigurationsdatei ermittelt die Azure-Runtime-Engine, welche Ereignisse es zu überwachen gilt und wie die Daten in die Funktionsausführung zu übergeben beziehungsweise aus dieser zurückzugeben sind. Im Beispiel ist der Trigger ein HTTP-Request und die Ausgabe erfolgt via HTTP-Protokoll direkt im Browser:

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "get",
        "post"
      ]
    },    
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
  ]
}

Wichtig für die Python Function ist darüber hinaus die Datei requirenments.txt, die eine manuell zu pflegende Liste der für das Deployment notwendigen Python-Pakete enthält:

# DO NOT include azure-functions-worker in this file
# The Python Worker is managed by Azure Functions platform
# Manually managing azure-functions-worker may cause unexpected issues

azure-functions
pandas
lxml

Ein praxisnahes Beispiel ist das tägliche Ermitteln von Information aus dem Internet, die sich nicht oft ändern: Die deutsche Wikipedia-Seite zu COVID-19 sammelt Daten und Entwicklungen der COVID-19-Infektionen in den einzelnen Bundesländern sowie in ganz Deutschland (s. Abb. 2).

COVID-19: 7-Tage-Inzidenz der Bundesländer laut wikipedia.de.

Für das Parsen der HTML-Seiten beim Web Scraping bieten sich verschiedene Vorgehensweisen und Methoden an, von regulären Ausdrücken bis zum Einsatz der Beautiful-Soup-Bibliothek. Im Beispiel kommt ein Web Scraper auf Basis der Python-Bibliothek pandas zum Einsatz. Das Parsen der HTML-Seite erfolgt direkt in der Datei __init__.py (s. Zeilen 20 und 21 in Listing 3).

import logging
import time
import datetime as dt
import pandas as pd
import json

import azure.functions as func

def main(req: func.HttpRequest, doc: func.Out[func.Document]) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    ###########################
    # Custom code BEGIN       #
    ###########################

    # just get the currently server time
    ctime = time.ctime()
    
    # get info from web site
    df_COVID_Wiki = pd.read_html('https://de.wikipedia.org/wiki/COVID-19-Pandemie_in_Deutschland', decimal=',', thousands='.')    
    df_COVID_BUND = df_COVID_Wiki[3]

    ###########################
    # Custom code END         #
    ###########################

    name = req.params.get('name')
    if not name:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            name = req_body.get('name')

    if name:
        
        # make formatted string
        response = (
            #f"Hello, <b>{name}</b>. The currently server time is {ctime}. This HTTP triggered function executed successfully.\n\n"
            f"Hello, {name}. The currently server time is {ctime}. This HTTP triggered function executed successfully.\n\n"
            f"COVID-19 7-Tage-Inzidenz der Bundesländer:\n"
            f"{df_COVID_BUND}"            
        )
        #return func.HttpResponse(f"Hello, {name}. The currently server time is {ctime}. This HTTP triggered function executed successfully.\n\n {df_COVID_BUND}")
        #return func.HttpResponse(f"{response}", mimetype="text/html")
        return func.HttpResponse(f"{response}")
    else:
        return func.HttpResponse(
             "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.",
             status_code=200
        )

Damit sind die beiden wesentlichen Anpassungen der Azure Function für das Web Scraping konfiguriert. Da sich die Azure-Plattform automatisch um die Infrastruktur kümmert, steht vor der Ausführung bei Azure lediglich ein lokaler Test an.

In Visual Studio Code lässt sich dazu die Applikation im Terminal mit F5 starten. Der lokal ausgeführte URL-Endpunkt ihrer über HTTP ausgelösten Funktion wird daraufhin im Terminal angezeigt (s. Abb. 3). Die URL lässt sich direkt im Browser oder in Postman ausführen, einer Collaboration-Plattform für die API-Entwicklung. Ist der Test erfolgreich abgeschlossen, lässt sich die Azure Function aus Visual Studio Code heraus in der Cloud bereitstellen.

URL zum Testen der Azure Function in Visual Studio Code.