Skip to content

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 lxml

HTML-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

MethodeBeispielFindet
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

WerkzeugAm besten fürGeschwindigkeitJavaScriptLernkurve
requests + BeautifulSoupStatische HTML-SeitenSchnellNeinEinfach
SeleniumJavaScript-gerenderte SeitenLangsamJaMittel
ScrapyGroßangelegtes CrawlingSchnellMit PluginsSteil
PlaywrightModerne JS-AppsMittelJaMittel
httpx + selectolaxHochleistungs-ParsingSehr schnellNeinEinfach

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.json

Datenbereinigung 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

PraxisBeschreibung
robots.txt prüfenDie Crawling-Regeln der Website respektieren
Verzögerungen hinzufügentime.sleep() zwischen Anfragen verwenden (1-3 Sekunden)
Sich identifizierenEinen beschreibenden User-Agent-String setzen
Antworten cachenBereits vorhandene Seiten nicht erneut scrapen
Nach APIs suchenViele Websites haben öffentliche APIs, die schneller und erlaubt sind
AGB lesenEinige Websites verbieten Scraping ausdrücklich
Rate-LimitingServer 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 results

Gescrapte 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.

📚