Einführung zu Web Scraping#

Das Web Scraping einer Online-Ressource sollte gut geplant werden - auch, um unnötige wiederholte Anfragen an die Website und den daraus resultierenden Traffic auf dem Server möglichst gering zu halten. Die Planung sollte dabei die folgenden Schritte umfassen:

  1. Mit der Struktur und den Elementen der Website und dem HTML-Code vertraut machen (Browser-Tools, etc)

  2. Elemente identifizieren, die extrahiert werden sollen (HTML-Elemente, Identifier, Attribute, etc)

  3. Testweises lokales parsen des HTML-Codes und Extrahieren der gewünschten Infos (z.b. mit parsel und requests)

  4. Planen des automatisierten Web Scraping Vorgangs mit scrapy

  5. Erstellen und Testen der benötigten Python-Module für scrapy

  6. Durchlauf des automatisierten Web Scraping und Auswerten der Daten

Grundlagen zum Parsen von HTML mit parsel#

Für das testweise lokale parsen einer Website bietet sich die Bibliothek parsel an. Scrapy nutzt parsel, daher verhalten sich die Selektoren zur Auswahl und Extraktion von Informationen ähnlich.

# Import des Selector-Moduls von parsel
from parsel import Selector

# Import und Initialisierung von bia-bob
from bia_bob import bob
# API Key wird aus condas Umgebungsvariable gelesen
bob.initialize(endpoint='blablador', model='alias-fast')
This notebook may contain text, code and images generated by artificial intelligence. Used model: alias-fast, vision model: None, endpoint: https://helmholtz-blablador.fz-juelich.de:8000/v1, bia-bob version: 0.26.1.. Do not enter sensitive or private information and verify generated contents according to good scientific practice. Read more: https://github.com/haesleinhuepf/bia-bob#disclaimer

Wir arbeiten zunächst an folgendem HTML Inhalt, gespeichert in der Variable text.

text = """
    <html>
        <body>
            <h1>Hello, Parsel!</h1>
            <ul>
                <li><a href="http://example.com">Link 1</a></li>
                <li><a href="http://scrapy.org">Link 2</a></li>
            </ul>
            <script type="application/json">{"a": ["b", "c"]}</script>
        </body>
    </html>
"""
# HTML Inhalt in parsels Selector laden
selector = Selector(text=text)

Um Elemente und deren Inhalt aus strukturierten Datenformaten zu extrahieren, stellt parsel entsprechende Selektoren (Selectors) bereit:

  • CSS

  • XPath

Siehe dazu auch folgende Online-Ressourcen:

# Selection via CSS
selector.css('h1::text').get()
'Hello, Parsel!'
# Selection via XPath
selector.xpath('//h1/text()').re(r'\w+')
['Hello', 'Parsel']

Mit JMESPath integriert parsel auch eine Abfragesprache für JSON, siehe JMESPath Dokumentation.

selector.css('script::text').jmespath("a").get()
'b'
selector.css('script::text').jmespath("a").getall()
['b', 'c']

Auch hier können wir bei Bedarf wieder unseren KI-Assistenten um Rat fragen.

%%bob
Analysiere den Inhalt der HTML in {text}.
Gib mir Code, um daraus mithilfe der Bibliothek parsel den Text-Inhalt des zweiten <li> Elements zu extrahieren.

Use the parsel library to extract the content of the second <li> element. Here is the code to achieve that:

# Inhalt des zweiten <li> Elements extrahieren
second_li_content = selector.xpath('//ul/li[2]/a/text()').get()

print(second_li_content)
Link 2

Parsen einer Website mit requests und parsel#

Nun nutzen wir die Bibliothek requests, um mittels einer GET Anfrage den HTML-Inhalt der Website zu erhalten. Diese HTML können wir dann lokal parsen, um die gwünschten Informationen zu extrahieren.

Für unsere Übung nutzen wir die Website https://quotes.toscrape.com/. Ziel ist die Extraktion der Zitate - hier jeweils den Text und den Namen der AutorInnen. Machen wir uns zunächst mit dem Inhalt der Website vertraut. Hierfür rufen wir die Website im Browser auf und werfen mit den Browser-Tools einen Blick auf die zugrundeliegende Struktur.

Wenn wir uns mit der Struktur der Website vertraut gemacht haben, können wir einen GET Request stellen, um den HTML-Inhalt zu erhalten

# Import von requests for HTTP Methoden
import requests
# GET Request an Website
response = requests.get('https://quotes.toscrape.com/')
# Ausgabe der ersten 500 Zeichen des HTML Inhaltes der Response
print(response.text[:500])
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Quotes to Scrape</title>
    <link rel="stylesheet" href="/static/bootstrap.min.css">
    <link rel="stylesheet" href="/static/main.css">
    
    
</head>
<body>
    <div class="container">
        <div class="row header-box">
            <div class="col-md-8">
                <h1>
                    <a href="/" style="text-decoration: none">Quotes to Scrape</a>
                </h1>
            </div>
            <div cla
# HTML Inhalt in parsels Selector laden
selector = Selector(text=response.text)

Jetzt bist du dran. Extrahiere für jedes Zitat im HTML-Inhalt den Text und den Namen der AutorIn. Speichere das Ergebnis als eine Liste von Tupeln ab…[(Text, AutorIn), (Text, AutorIn), ...].

Hierfür bietet sich der folgende Ablauf an:

  • Identifikation der Zitat-Elemente im HTML und deren Attribute

  • Sammeln aller Zitat-Elemente in einer Liste

  • Iteration über die Zitat-Elemente und Extraktion der gewünschten Informationen

Du kannst natürlich auch unseren KI-Assistenten um Rat fragen.

# Liste zum Sammeln der extrahierten Informationen
quotes = []
# TODO