Web Scraping mit Python: Vollständige Anleitung mit Requests, BeautifulSoup und Selenium
Updated on
Sie brauchen Daten, die nicht über APIs verfügbar sind -- Produktpreise von Konkurrenzwebseiten, Forschungsarbeiten von akademischen Portalen, Stellenangebote von Recruiting-Plattformen oder Nachrichtenartikel aus mehreren Quellen. Manuelles Kopieren von Daten ist langsam, fehleranfällig und in großem Maßstab unmöglich. Web Scraping automatisiert diesen Prozess, aber die Wahl des falschen Tools oder Ansatzes führt zu blockierten Anfragen, kaputten Parsern und rechtlichen Problemen.
Dieser Leitfaden behandelt den vollständigen Python-Web-Scraping-Stack: requests + BeautifulSoup für statische Seiten, Selenium für JavaScript-gerenderte Inhalte und Scrapy für großangelegtes Crawling. Sie lernen praktische Techniken für reale Herausforderungen.
Schnellstart: requests + BeautifulSoup
Die gängigste Kombination für das Scraping statischer HTML-Seiten:
import requests
from bs4 import BeautifulSoup
# Seite abrufen
url = 'https://books.toscrape.com/'
response = requests.get(url)
response.raise_for_status() # Fehler bei schlechtem Statuscode auslösen
# HTML parsen
soup = BeautifulSoup(response.text, 'html.parser')
# Buchtitel extrahieren
books = soup.select('article.product_pod h3 a')
for book in books[:5]:
print(book['title'])Installation
# Erforderliche Pakete installieren
# pip install requests beautifulsoup4 lxmlHTML-Parsing mit BeautifulSoup
Elemente finden
from bs4 import BeautifulSoup
html = """
<div class="products">
<div class="product" id="p1">
<h2 class="name">Widget A</h2>
<span class="price">$9.99</span>
<p class="desc">A useful widget</p>
</div>
<div class="product" id="p2">
<h2 class="name">Widget B</h2>
<span class="price">$14.99</span>
<p class="desc">A better widget</p>
</div>
</div>
"""
soup = BeautifulSoup(html, 'html.parser')
# Nach Tag suchen
print(soup.find('h2').text) # "Widget A"
# Nach Klasse suchen
prices = soup.find_all('span', class_='price')
for p in prices:
print(p.text) # "$9.99", "$14.99"
# Nach ID suchen
product = soup.find(id='p2')
print(product.find('h2').text) # "Widget B"
# CSS-Selektor
names = soup.select('.product .name')
for n in names:
print(n.text)Gängige Selektoren
| Methode | Beispiel | Findet |
|---|---|---|
find('tag') | soup.find('h2') | Erstes h2-Element |
find_all('tag') | soup.find_all('a') | Alle Anker-Elemente |
find(class_='x') | soup.find(class_='price') | Erstes Element mit Klasse |
find(id='x') | soup.find(id='main') | Element mit ID |
select('css') | soup.select('div.product > h2') | CSS-Selektor-Treffer |
select_one('css') | soup.select_one('#header') | Erster CSS-Treffer |
Daten extrahieren
from bs4 import BeautifulSoup
html = '<a href="/page/2" class="next" data-page="2">Next Page</a>'
soup = BeautifulSoup(html, 'html.parser')
link = soup.find('a')
# Textinhalt
print(link.text) # "Next Page"
print(link.get_text(strip=True)) # "Next Page" (bereinigt)
# Attribute
print(link['href']) # "/page/2"
print(link.get('class')) # ['next']
print(link['data-page']) # "2"Umgang mit Headern und Sessions
Viele Websites blockieren Anfragen ohne geeignete Header:
import requests
from bs4 import BeautifulSoup
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept-Language': 'en-US,en;q=0.9',
}
# Session für Cookies und persistente Header verwenden
session = requests.Session()
session.headers.update(headers)
response = session.get('https://books.toscrape.com/')
soup = BeautifulSoup(response.text, 'html.parser')
print(f"{len(soup.select('article.product_pod'))} Bücher gefunden")Paginierung
Nächste-Seite-Links folgen
import requests
from bs4 import BeautifulSoup
base_url = 'https://books.toscrape.com/catalogue/'
all_books = []
url = 'https://books.toscrape.com/catalogue/page-1.html'
while url:
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
# Bücher von der aktuellen Seite extrahieren
for book in soup.select('article.product_pod'):
title = book.select_one('h3 a')['title']
price = book.select_one('.price_color').text
all_books.append({'title': title, 'price': price})
# Nächste Seite finden
next_btn = soup.select_one('li.next a')
if next_btn:
url = base_url + next_btn['href']
else:
url = None
print(f"Bisher {len(all_books)} Bücher gescrapt...")
print(f"Gesamt: {len(all_books)} Bücher")JavaScript-Seiten mit Selenium scrapen
Wenn eine Seite Inhalte mit JavaScript rendert, erhält requests nur das rohe HTML vor dem Rendern. Verwenden Sie Selenium, um einen echten Browser zu steuern:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# Headless Chrome einrichten
options = webdriver.ChromeOptions()
options.add_argument('--headless')
driver = webdriver.Chrome(options=options)
try:
driver.get('https://quotes.toscrape.com/js/')
# Auf Inhaltsladung warten
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CLASS_NAME, 'quote'))
)
quotes = driver.find_elements(By.CLASS_NAME, 'quote')
for quote in quotes:
text = quote.find_element(By.CLASS_NAME, 'text').text
author = quote.find_element(By.CLASS_NAME, 'author').text
print(f'"{text}" -- {author}')
finally:
driver.quit()Werkzeugvergleich
| Werkzeug | Am besten für | Geschwindigkeit | JavaScript | Lernkurve |
|---|---|---|---|---|
requests + BeautifulSoup | Statische HTML-Seiten | Schnell | Nein | Einfach |
Selenium | JavaScript-gerenderte Seiten | Langsam | Ja | Mittel |
Scrapy | Großangelegtes Crawling | Schnell | Mit Plugins | Steil |
Playwright | Moderne JS-Apps | Mittel | Ja | Mittel |
httpx + selectolax | Hochleistungs-Parsing | Sehr schnell | Nein | Einfach |
Scrapy für großangelegtes Scraping
Für das Crawling von Tausenden von Seiten bietet Scrapy eingebaute Nebenläufigkeit, Retry-Logik und Datenpipelines:
# spider.py
import scrapy
class BookSpider(scrapy.Spider):
name = 'books'
start_urls = ['https://books.toscrape.com/']
def parse(self, response):
for book in response.css('article.product_pod'):
yield {
'title': book.css('h3 a::attr(title)').get(),
'price': book.css('.price_color::text').get(),
}
# Paginierung folgen
next_page = response.css('li.next a::attr(href)').get()
if next_page:
yield response.follow(next_page, self.parse)
# Ausführen mit: scrapy runspider spider.py -o books.jsonDatenbereinigung und -speicherung
import requests
from bs4 import BeautifulSoup
import pandas as pd
# Daten scrapen
url = 'https://books.toscrape.com/'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
books = []
for item in soup.select('article.product_pod'):
title = item.select_one('h3 a')['title']
price_text = item.select_one('.price_color').text
price = float(price_text.replace('£', ''))
rating_class = item.select_one('p.star-rating')['class'][1]
books.append({
'title': title,
'price': price,
'rating': rating_class,
})
# In DataFrame konvertieren
df = pd.DataFrame(books)
print(df.head())
# Als CSV speichern
df.to_csv('books.csv', index=False)Ethische Scraping-Praktiken
| Praxis | Beschreibung |
|---|---|
| robots.txt prüfen | Die Crawling-Regeln der Website respektieren |
| Verzögerungen hinzufügen | time.sleep() zwischen Anfragen verwenden (1-3 Sekunden) |
| Sich identifizieren | Einen beschreibenden User-Agent-String setzen |
| Antworten cachen | Bereits vorhandene Seiten nicht erneut scrapen |
| Nach APIs suchen | Viele Websites haben öffentliche APIs, die schneller und erlaubt sind |
| AGB lesen | Einige Websites verbieten Scraping ausdrücklich |
| Rate-Limiting | Server nicht mit gleichzeitigen Anfragen überlasten |
import time
import requests
def polite_scrape(urls, delay=2):
"""Scraping mit Verzögerungen zwischen Anfragen."""
results = []
for url in urls:
response = requests.get(url)
results.append(response.text)
time.sleep(delay) # Höflich bleiben
return resultsGescrapte Daten analysieren
Nach dem Sammeln von Daten durch Web Scraping hilft PyGWalker (opens in a new tab) beim interaktiven Erkunden und Visualisieren des gescrapten Datensatzes in Jupyter:
import pandas as pd
import pygwalker as pyg
df = pd.read_csv('scraped_data.csv')
walker = pyg.walk(df)Zum iterativen Ausführen von Scraping-Skripten in Jupyter mit KI-Unterstützung bietet RunCell (opens in a new tab) eine KI-gestützte Umgebung, in der Sie Selektoren debuggen und Parsing-Logik interaktiv testen können.
Häufig gestellte Fragen
Was ist die beste Python-Bibliothek für Web Scraping?
Für statische Seiten ist requests + BeautifulSoup die einfachste und beliebteste Wahl. Für JavaScript-gerenderte Seiten verwenden Sie Selenium oder Playwright. Für großangelegtes Crawling mit Tausenden von Seiten bietet Scrapy eingebaute Nebenläufigkeit und Pipeline-Management.
Wie scrape ich eine Website, die JavaScript verwendet?
Verwenden Sie Selenium oder Playwright, um einen Headless-Browser zu steuern, der JavaScript ausführt. Alternativ prüfen Sie im Netzwerk-Tab des Browsers nach API-Endpunkten, die JSON-Daten zurückgeben -- das direkte Scraping der API ist schneller und zuverlässiger als Browser-Automatisierung.
Ist Web Scraping legal?
Die Legalität von Web Scraping hängt von der Gerichtsbarkeit, den Nutzungsbedingungen der Website und der Datenverwendung ab. Das Scraping öffentlich verfügbarer Daten ist in vielen Gerichtsbarkeiten generell legal, aber prüfen Sie immer die robots.txt und AGB der Website. Vermeiden Sie das Scraping persönlicher Daten oder urheberrechtlich geschützter Inhalte.
Wie vermeide ich Blockierungen beim Scraping?
Verwenden Sie Verzögerungen zwischen Anfragen (1-3 Sekunden), rotieren Sie User-Agent-Strings, respektieren Sie robots.txt, verwenden Sie Sessions für Cookies und vermeiden Sie zu viele gleichzeitige Anfragen. Wenn Sie dauerhaft blockiert werden, prüfen Sie, ob die Website eine öffentliche API hat.
Wie gehe ich mit Paginierung beim Web Scraping um?
Finden Sie den "Nächste Seite"-Link oder -Button im HTML, extrahieren Sie dessen URL und folgen Sie ihm in einer Schleife, bis keine weiteren Seiten existieren. Alternativ, wenn Seiten Query-Parameter verwenden (z.B. ?page=2), iterieren Sie direkt durch die Seitennummern.
Fazit
Pythons Web-Scraping-Ökosystem deckt jedes Szenario ab: requests + BeautifulSoup für schnelles Scraping statischer Seiten, Selenium für JavaScript-intensive Websites und Scrapy für Crawling im Produktionsmaßstab. Beginnen Sie mit dem einfachsten Werkzeug, das funktioniert, fügen Sie nur bei Bedarf Komplexität hinzu und scrapen Sie immer ethisch -- respektieren Sie robots.txt, fügen Sie Verzögerungen hinzu und prüfen Sie zuerst nach APIs. Speichern Sie Ihre gescrapten Daten in strukturierten Formaten wie CSV oder DataFrames für sofortige Analyse.