Web-Scraping Extrahiert programmgesteuert Daten von Websites – nützlich für Recherche, Preisüberwachung, Datenaggregation und Automatisierung. Dieser Leitfaden erstellt Scraper in Python, von einfachen statischen Seiten bis hin zu dynamischen JavaScript-Sites, und behandelt dabei die rechtlichen und ethischen Praktiken, die Sie vor Ärger bewahren.
📋 Table of Contents
Zuerst verantwortungsbewusst kratzen
Bevor Sie einen Scraper schreiben, sollten Sie die Regeln verstehen:
- Überprüfen Sie robots.txt:
example.com/robots.txtsagt Ihnen, was gecrawlt werden darf - Lesen Sie die Nutzungsbedingungen: Einige Websites verbieten das Scraping
- ausdrücklich Ratenbegrenzungen beachten: Überlasten Sie den Server nicht – fügen Sie Verzögerungen zwischen den Anfragen hinzu
- Verwenden Sie offizielle APIs, sofern verfügbar: Bevorzugen Sie immer eine API gegenüber Scraping
- Kratzen Sie keine persönlichen Daten ohne Rechtsgrundlage (es gelten DSGVO und ähnliche Gesetze)
- Identifizieren Sie sich: Richten Sie einen geeigneten Benutzeragenten ein, tarnen Sie Ihren Bot nicht böswillig
Einrichtung
pip install requests beautifulsoup4 lxml
# For JavaScript-heavy sites:
pip install playwright
playwright install chromium
Scraping statischer Seiten mit Anfragen + BeautifulSoup
import requests
from bs4 import BeautifulSoup
import time
def scrape_articles(url):
headers = {
'User-Agent': 'Mozilla/5.0 (compatible; MyResearchBot/1.0)'
}
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'lxml')
articles = []
for article in soup.select('article.post'):
title = article.select_one('h2.title')
link = article.select_one('a')
articles.append({
'title': title.get_text(strip=True) if title else None,
'url': link['href'] if link else None,
})
return articles
data = scrape_articles('https://example.com/blog')
for item in data:
print(item)
Elemente präzise auswählen
soup = BeautifulSoup(html, 'lxml')
# By tag
soup.find('h1') # first h1
soup.find_all('p') # all paragraphs
# By CSS selector (most flexible)
soup.select('div.card > h2') # h2 inside div.card
soup.select_one('#main .price') # first .price inside #main
# Extract data
element.get_text(strip=True) # text content
element['href'] # attribute value
element.get('data-id', 'default') # attribute with fallback
# Navigate
element.parent # parent element
element.find_next_sibling('div') # next sibling
Scraping dynamischer (JavaScript) Websites mit Playwright
Viele moderne Websites rendern Inhalte mit JavaScript – Anfragen sehen sie nicht. Playwright führt einen echten Browser aus:
from playwright.sync_api import sync_playwright
def scrape_dynamic(url):
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page(user_agent='Mozilla/5.0 (MyBot/1.0)')
page.goto(url, wait_until='networkidle')
# Wait for content to load
page.wait_for_selector('.product-card')
# Extract data from the rendered page
products = page.eval_on_selector_all('.product-card', '''
cards => cards.map(card => ({
name: card.querySelector('.name')?.innerText,
price: card.querySelector('.price')?.innerText,
}))
''')
browser.close()
return products
results = scrape_dynamic('https://example.com/products')
Ratenbegrenzung und Höflichkeit
import time
import random
def polite_scrape(urls):
results = []
for url in urls:
try:
data = scrape_page(url)
results.append(data)
except requests.RequestException as e:
print(f"Failed {url}: {e}")
# Random delay between requests (1-3 seconds) - be gentle
time.sleep(random.uniform(1, 3))
return results
# Respect Retry-After on 429 responses
response = requests.get(url)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
time.sleep(retry_after)
Umgang mit Paginierung
def scrape_all_pages(base_url):
all_data = []
page = 1
while True:
url = f"{base_url}?page={page}"
response = requests.get(url, headers=HEADERS, timeout=10)
soup = BeautifulSoup(response.text, 'lxml')
items = soup.select('.item')
if not items:
break # no more items - stop
all_data.extend(extract_items(items))
# Check for a "next" link, or just increment
if not soup.select_one('a.next-page'):
break
page += 1
time.sleep(random.uniform(1, 2))
return all_data
Scraped-Daten speichern
import csv
import json
# To CSV
with open('data.csv', 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['title', 'url', 'price'])
writer.writeheader()
writer.writerows(data)
# To JSON
with open('data.json', 'w') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
# To a database (SQLite example)
import sqlite3
conn = sqlite3.connect('scraped.db')
conn.executemany(
"INSERT INTO products (name, price) VALUES (?, ?)",
[(d['name'], d['price']) for d in data]
)
conn.commit()
Häufig gestellte Fragen
F: Ist Web Scraping legal?
A: Es kommt darauf an. Das Scrapen öffentlich verfügbarer Daten ist oft legal, aber ein Verstoß gegen die Nutzungsbedingungen, das Scrapen personenbezogener Daten ohne Grundlage oder das Umgehen von Zugriffskontrollen kann illegal sein. Überprüfen Sie robots.txt und ToS, bevorzugen Sie offizielle APIs und lassen Sie sich für kommerzielles Scraping rechtlich beraten.
F: Anfragen/BeautifulSoup oder Dramatiker?
A: Verwenden Sie Anfragen + BeautifulSoup für statische HTML-Seiten (schneller, leichter). Verwenden Sie Playwright (oder Selenium) für mit JavaScript gerenderte Websites, bei denen Inhalte dynamisch geladen werden. Überprüfen Sie zunächst, ob sich die Daten im ursprünglichen HTML-Code befinden. Wenn ja, benötigen Sie keinen Browser.
F: Wie vermeide ich eine Blockierung?
A: Seien Sie höflich – respektieren Sie Ratenbeschränkungen, fügen Sie Verzögerungen hinzu, richten Sie einen geeigneten Benutzeragenten ein und überlasten Sie die Server nicht. Der beste Weg, Blockaden zu vermeiden, besteht darin, nicht beleidigend zu sein. Aggressives Scraping wird blockiert (und ist möglicherweise illegal).
F: Sollte ich eine API anstelle von Scraping verwenden?
A: Immer, sofern vorhanden. APIs sind zuverlässiger, legaler, strukturierter und brechen nicht, wenn sich der HTML-Code der Website ändert. Scraping ist der letzte Ausweg, wenn keine API die benötigten Daten bereitstellt.
F: Wie gehe ich mit Websites um, die eine Anmeldung erfordern?
A: Playwright kann die Anmeldung automatisieren (Formulare ausfüllen, absenden) und eine Sitzung aufrechterhalten. Aber das Scrapen hinter einem Login verstößt oft gegen die Nutzungsbedingungen – achten Sie besonders auf die Rechtmäßigkeit und scrapen Sie nur Daten, auf die Sie zugreifen dürfen.
Fazit
Web Scraping mit Python ist für die Datenerfassung leistungsstark, aber gehen Sie verantwortungsbewusst vor. Verwenden SieAnfragen + BeautifulSoup für statische Seiten und Playwright für mit JavaScript gerenderte Websites, Elemente mit CSS-Selektoren auswählen, Paginierung verwalten und in CSV/JSON/Datenbank speichern. Am wichtigsten:Überprüfen Sie robots.txt und die Nutzungsbedingungen, respektieren Sie Ratenbeschränkungen bei Verzögerungen, bevorzugen Sie offizielle APIs und kratzen Sie keine personenbezogenen Daten ohne Rechtsgrundlage. Ethisches und höfliches Scraping schützt Sie vor rechtlichen und technischen Problemen und erhält gleichzeitig die Daten, die Sie benötigen. Wenn eine API vorhanden ist, verwenden Sie stattdessen immer diese – Scraping ist der Ausweg, nicht die erste Wahl.
🔗 Share this article
✍️ Leave a Comment