Von BeautifulSoup zu Scrapling wechseln¶
Wenn Sie BeautifulSoup bereits kennen, wird Ihnen der Einstieg leichtfallen. Scrapling ist deutlich schneller, bietet dieselben Parsing-Funktionen und fügt weitere hinzu. Dazu kommen Funktionen zum Abrufen und Verarbeiten moderner Webseiten. Diese Anleitung hilft Ihnen, Ihren bestehenden BeautifulSoup-Code schnell an Scrapling anzupassen.
Die folgende Tabelle zeigt die häufigsten Aufgaben beim Web Scraping. Jede Zeile nennt den Code für BeautifulSoup und die entsprechende Methode in Scrapling.
Einige Abkürzungen von BeautifulSoup fehlen in Scrapling. Das ist einer der Gründe, warum BeautifulSoup langsamer ist. Wenn sich eine Funktion schon mit einer kurzen Zeile nutzen lässt, müssen wir diese nicht auf Kosten der Geschwindigkeit noch kürzer machen :)
| Aufgabe | BeautifulSoup-Code | Scrapling-Code |
|---|---|---|
| Parser importieren | from bs4 import BeautifulSoup |
from scrapling.parser import Selector |
| HTML aus einer Zeichenfolge parsen | soup = BeautifulSoup(html, 'html.parser') |
page = Selector(html) |
| Ein Element finden | element = soup.find('div', class_='example') |
element = page.find('div', class_='example') |
| Mehrere Elemente finden | elements = soup.find_all('div', class_='example') |
elements = page.find_all('div', class_='example') |
| Ein Element finden (Beispiel 2) | element = soup.find('div', attrs={"class": "example"}) |
element = page.find('div', {"class": "example"}) |
| Ein Element finden (Beispiel 3) | element = soup.find(re.compile("^b")) |
element = page.find(lambda e: re.search(r"^b", e.tag) is not None) |
| Ein Element finden (Beispiel 4) | element = soup.find(lambda e: len(list(e.children)) > 0) |
element = page.find(lambda e: len(e.children) > 0) |
| Ein Element finden (Beispiel 5) | element = soup.find(["a", "b"]) |
element = page.find(["a", "b"]) |
| Ein Element anhand seines Texts finden | element = soup.find(text="some text") |
element = page.find_by_text("some text", partial=False) |
| Den ersten Treffer mit CSS auswählen | elements = soup.select_one('div.example') |
elements = page.css('div.example').first |
| Alle Treffer mit CSS auswählen | elements = soup.select('div.example') |
elements = page.css('div.example') |
| Den Quelltext einer Seite oder eines Elements lesbar formatieren | prettified = soup.prettify() |
prettified = page.prettify() |
| Den Quelltext einer Seite oder eines Elements ohne zusätzliche Formatierung erhalten | source = str(soup) |
source = page.html_content |
| Den Tag-Namen eines Elements erhalten | name = element.name |
name = element.tag |
| Den Text eines Elements extrahieren | string = element.string |
string = element.text |
| Den gesamten Text eines Dokuments oder unter einem Tag extrahieren | text = soup.get_text(strip=True) |
text = page.get_all_text(strip=True) |
| Auf das Wörterbuch der Attribute zugreifen | attrs = element.attrs |
attrs = element.attrib |
| Attribute extrahieren | attr = element['href'] |
attr = element['href'] |
| Zum Elternelement wechseln | parent = element.parent |
parent = element.parent |
| Alle Vorfahren eines Elements erhalten | parents = list(element.parents) |
parents = list(element.iterancestors()) |
| Ein Element unter den Vorfahren suchen | target_parent = element.find_parent("a") |
target_parent = element.find_ancestor(lambda p: p.tag == 'a') |
| Alle Geschwisterelemente erhalten | Nicht verfügbar | siblings = element.siblings |
| Das nächste Geschwisterelement erhalten | next_element = element.next_sibling |
next_element = element.next |
| Ein Geschwisterelement suchen | target_sibling = element.find_next_sibling("a")target_sibling = element.find_previous_sibling("a") |
target_sibling = element.siblings.search(lambda s: s.tag == 'a') |
| Mehrere Geschwisterelemente suchen | target_sibling = element.find_next_siblings("a")target_sibling = element.find_previous_siblings("a") |
target_sibling = element.siblings.filter(lambda s: s.tag == 'a') |
| Ein Element unter den folgenden Elementen suchen | target_parent = element.find_next("a") |
target_parent = element.below_elements.search(lambda p: p.tag == 'a') |
| Mehrere Elemente unter den folgenden Elementen suchen | target_parent = element.find_all_next("a") |
target_parent = element.below_elements.filter(lambda p: p.tag == 'a') |
| Ein Element unter den Vorfahren suchen | target_parent = element.find_previous("a") ¹ |
target_parent = element.path.search(lambda p: p.tag == 'a') |
| Mehrere Elemente unter den Vorfahren suchen | target_parent = element.find_all_previous("a") ¹ |
target_parent = element.path.filter(lambda p: p.tag == 'a') |
| Das vorherige Geschwisterelement erhalten | prev_element = element.previous_sibling |
prev_element = element.previous |
| Zu den Kindelementen wechseln | children = list(element.children) |
children = element.children |
| Alle Nachfahren eines Elements erhalten | children = list(element.descendants) |
children = element.below_elements |
| Links in Absätzen mit der Klasse story auswählen | group = soup.select('p.story a') |
group = page.css('p.story a') |
Eine kompilierte Regex, die Sie direkt an Scraplings find() oder find_all() übergeben, durchsucht den Text der Elemente, nicht ihre Tag-Namen. Für Tag-Namen nutzen Sie die Lambda-Funktion aus der Tabelle. Für direkten Text können Sie page.find_by_regex(r"^b") verwenden.
¹ Hinweis: find_previous/find_all_previous von BS4 durchsuchen alle vorhergehenden Elemente in Dokumentreihenfolge. Scraplings path gibt dagegen nur Vorfahren zurück, also die Kette der Elternelemente. Die Methoden sind nicht genau gleich, aber die Suche unter den Vorfahren deckt den häufigsten Fall ab.
Ein wichtiger Unterschied: BeautifulSoup bietet Funktionen, um eine Seite nach dem Parsen zu verändern. Scrapling konzentriert sich darauf, Daten schnell zu extrahieren. Danach können Sie die Daten beliebig weiterverarbeiten. Beide Werkzeuge können beim Web Scraping helfen, aber eines ist darauf spezialisiert :)
Ein vollständiges Beispiel¶
Dieses einfache Beispiel extrahiert alle Links einer Webseite mit BeautifulSoup und Scrapling.
Mit BeautifulSoup:
import requests
from bs4 import BeautifulSoup
url = 'https://example.com'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
links = soup.find_all('a')
for link in links:
print(link['href'])
Mit Scrapling:
from scrapling import Fetcher
url = 'https://example.com'
page = Fetcher.get(url)
links = page.css('a::attr(href)').getall()
for link in links:
print(link)
Scrapling verbindet das Abrufen und Parsen in einem Schritt. So wird Ihr Code einfacher und effizienter.
Weitere Hinweise:
- Verschiedene Parser: In BeautifulSoup können Sie den Parser auswählen, zum Beispiel
lxml. Scrapling verwendet aus Leistungsgründen standardmäßig die Bibliotheklxml. - Elementtypen: In BeautifulSoup sind Elemente
Tag-Objekte, in ScraplingSelector-Objekte. Beide bieten ähnliche Methoden und Eigenschaften für Navigation und Datenextraktion. - Fehlerbehandlung: Beide Bibliotheken geben
Nonezurück, wenn sie kein Element finden, zum Beispiel mitsoup.find()oderpage.find(). In Scrapling gibtpage.css()eine leereSelectors-Liste zurück, wenn nichts passt. Mitpage.css('.foo').firsterhalten Sie sicher den ersten Treffer oderNone. Prüfen Sie aufNoneoder leere Ergebnisse, bevor Sie auf Eigenschaften zugreifen. - Textextraktion: Scrapling bietet über
TextHandlerzusätzliche Methoden zur Textverarbeitung, etwaclean(). Diese Methode hilft, überflüssige Leerzeichen, aufeinanderfolgende Leerzeichen oder unerwünschte Zeichen zu entfernen. Die vollständige Liste finden Sie in der Dokumentation.
Die Dokumentation beschreibt die Funktionen von Scrapling genauer und enthält die vollständige Liste aller Argumente der Methoden.
Diese Anleitung soll Ihnen den Wechsel von BeautifulSoup zu Scrapling erleichtern. Viel Erfolg beim Scraping!