Was ist Scrapling?
Scrapling ist ein adaptives Python-Web-Scraping-Framework, entwickelt vom Entwickler D4Vinci. Es hat 2026 auf GitHub Trending schnell an Popularität gewonnen und über 57.000 Sterne erhalten, was es zu einem Vertreter der neuen Generation von Crawler-Tools macht.
Warum braucht man Scrapling?
Traditionelle Crawler-Frameworks (wie Scrapy, BeautifulSoup) stehen vor drei großen Schmerzpunkten:
- Code-Ausfall bei Website-Strukturänderungen: CSS-Selektoren oder XPath brechen sofort zusammen, sobald die Seite überarbeitet wird.
- Blockierung durch Anti-Bot-Systeme: Schutzmaßnahmen wie Cloudflare Turnstile oder Akamai lassen normale Anfragen direkt mit einem 403-Fehler zurückkommen.
- Schlechte Skalierbarkeit: Vom kleinen Datenabruf bis zum groß angelegten parallelen Crawling muss viel Code neu geschrieben werden.
Das Kerndesign-Prinzip von Scrapling lautet "One library, zero compromises" (Eine Bibliothek, keine Kompromisse):
- Adaptiver Parser: Lernt die Website-Struktur automatisch und lokalisiert Elemente nach Updates selbstständig neu.
- Integriertes Anti-Blocking: Funktioniert sofort out-of-the-box und umgeht Cloudflare Turnstile und andere gängige Schutzmaßnahmen.
- Scrapy-ähnliche API: Entwickler, die mit Scrapy vertraut sind, können nahtlos wechseln.
- Von der Einzelanfrage bis zum Voll-Crawl: Dieselbe API unterstützt sowohl einfaches Scraping als auch groß angelegtes paralleles Crawling.
Scrapling vs. traditionelle Crawler-Tools
| Feature | BeautifulSoup | Scrapy | Scrapling |
|---|---|---|---|
| Lernkurve | Niedrig | Mittel | Mittel |
| Adaptives Parsing | ❌ | ❌ | ✅ |
| Cloudflare-Umgehung | ❌ | Benötigt Plugin | ✅ Integriert |
| Paralleles Crawling | ❌ | ✅ | ✅ |
| Unterstützung dynamischer Seiten | ❌ | Benötigt Middleware | ✅ Integriertes Playwright |
| Pause/Fortsetzen | ❌ | Benötigt Erweiterung | ✅ Integriert |
| Streaming-Ausgabe | ❌ | ❌ | ✅ |
Installation von Scrapling
Systemvoraussetzungen
- Python 3.8+
- pip Paketmanager
Schnelle Installation
pip install scrapling
Installation überprüfen
from scrapling.fetchers import Fetcher
# Grundlegende Funktionen testen
p = Fetcher.fetch('https://example.com')
print(p.title) # Gibt den Seitentitel aus
Optionale Abhängigkeiten
Wenn du dynamisches Rendering (JavaScript-Websites) benötigst, musst du Playwright installieren:
pip install playwright
playwright install chromium
Schnellstart: Dein erster Crawler
Beispiel 1: Einfaches Page-Scraping
Beginnen wir mit einem einfachen Beispiel – wir holen uns die Top-News von Hacker News.
from scrapling.fetchers import Fetcher
# HTTP-Anfrage senden
page = Fetcher.fetch('https://news.ycombinator.com/')
# Daten mit CSS-Selektoren extrahieren
stories = page.css('.titleline > a')
for story in stories[:5]: # Nur die ersten 5 nehmen
title = story.text
link = story.attrs.get('href', '')
print(f"Titel: {title}")
print(f"Link: {link}")
print("-" * 40)
Beispielausgabe:
Titel: Show HN: Ich habe ein Tool für Echtzeit-Code-Zusammenarbeit gebaut
Link: https://github.com/example/collab-tool
----------------------------------------
Titel: Ask HN: Was ist deine Lieblings-Python-Bibliothek im Jahr 2026?
Link: https://news.ycombinator.com/item?id=123456
----------------------------------------
Beispiel 2: Adaptives Parsing (Auto-save)
Das Kernfeature von Scrapling ist das adaptive Parsing. Wenn du Daten zum ersten Mal abgreifst, kannst du auto_save=True aktivieren. Scrapling lernt dann die Seitenstruktur und speichert die Merkmale. Wenn die Website später überarbeitet wird, übergibst du einfach adaptive=True, und es findet die Zielelemente automatisch wieder.
from scrapling.fetchers import Fetcher
page = Fetcher.fetch('https://quotes.toscrape.com/')
# Erster Abruf: auto_save aktivieren
quotes = page.css('.quote', auto_save=True)
for quote in quotes[:3]:
text = quote.css('.text::text').get()
author = quote.css('.author::text').get()
print(f"{text} — {author}")
Wenn sich die Website-Struktur ändert:
# Spätere Abrufe: adaptive=True übergeben
page = Fetcher.fetch('https://quotes.toscrape.com/')
quotes = page.css('.quote', adaptive=True) # Passt sich automatisch der neuen Struktur an!
for quote in quotes[:3]:
text = quote.css('.text::text').get()
author = quote.css('.author::text').get()
print(f"{text} — {author}")
💡 Funktionsweise: Scrapling zeichnet verschiedene Merkmale eines Elements auf (Tag-Typ, benachbarter Text, Attributmuster usw.). Selbst wenn sich CSS-Klassennamen ändern, kann es das Element über andere Merkmale wiederfinden.
Fortgeschrittene Funktionen
1. Cloudflare Turnstile umgehen
Viele Websites nutzen Cloudflare Turnstile oder andere Anti-Bot-Systeme. Der StealthyFetcher von Scrapling kann diese Schutzmaßnahmen automatisch handhaben.
from scrapling.fetchers import StealthyFetcher
# Adaptiven Modus aktivieren
StealthyFetcher.adaptive = True
# Cloudflare automatisch umgehen
page = StealthyFetcher.fetch(
'https://example-protected-site.com',
headless=True, # Headless-Browser-Modus
network_idle=True # Warten, bis das Netzwerk inaktiv ist
)
# Daten normal extrahieren
products = page.css('.product-item')
for product in products:
name = product.css('.name::text').get()
price = product.css('.price::text').get()
print(f"{name}: {price}")
Erklärung der wichtigsten Parameter:
- headless=True: Verwendet einen Headless-Browser, um echtes Nutzerverhalten zu simulieren.
- network_idle=True: Wartet, bis alle Netzwerkanfragen abgeschlossen sind, bevor extrahiert wird (ideal für SPA-Anwendungen).
- adaptive=True: Aktiviert das adaptive Parsing.
2. Dynamisches Seiten-Rendering (Playwright)
Für Websites, die JavaScript-Rendering benötigen, verwende den DynamicFetcher.
from scrapling.fetchers import DynamicFetcher
page = DynamicFetcher.fetch(
'https://spa-example.com',
wait_for='.content-loaded', # Warten, bis ein bestimmtes Element erscheint
timeout=30000 # Timeout-Zeit (Millisekunden)
)
# Dynamisch geladene Inhalte extrahieren
articles = page.css('article')
for article in articles:
title = article.css('h2::text').get()
summary = article.css('.summary::text').get()
print(f"{title}\n{summary}\n")
3. Asynchrones paralleles Scraping
Verwende den AsyncFetcher, um hochparalleles Scraping zu实现.
import asyncio
from scrapling.fetchers import AsyncFetcher
async def fetch_multiple_pages():
urls = [
'https://example.com/page/1',
'https://example.com/page/2',
'https://example.com/page/3',
'https://example.com/page/4',
'https://example.com/page/5',
]
# Anfragen parallel starten
pages = await AsyncFetcher.fetch_many(urls, concurrency=3)
for url, page in zip(urls, pages):
if page:
title = page.title
print(f"{url}: {title}")
else:
print(f"{url}: Anfrage fehlgeschlagen")
asyncio.run(fetch_multiple_pages())
Spider-Framework: Groß angelegtes Crawling
Scrapling bietet ein Scrapy-ähnliches Spider-Framework, das groß angelegtes paralleles Crawling unterstützt.
Basis-Spider
from scrapling.spiders import Spider, Response
class QuoteSpider(Spider):
name = "quotes"
start_urls = ["https://quotes.toscrape.com/"]
async def parse(self, response: Response):
# Zitate der aktuellen Seite extrahieren
for quote in response.css('.quote'):
yield {
"text": quote.css('.text::text').get(),
"author": quote.css('.author::text').get(),
"tags": quote.css('.tag::text').getall()
}
# Zur nächsten Seite blättern
next_page = response.css('.next a::attr(href)').get()
if next_page:
yield self.follow(next_page, callback=self.parse)
# Crawler starten
QuoteSpider().start()
Parallelitätskonfiguration
class MultiPageSpider(Spider):
name = "multi-page"
start_urls = [f"https://example.com/page/{i}" for i in range(1, 101)]
# Parallelität konfigurieren
custom_settings = {
"concurrency": 5, # Maximale Parallelität
"download_delay": 1, # Download-Verzögerung (Sekunden)
"robots_txt_obey": True, # robots.txt beachten
}
async def parse(self, response: Response):
title = response.css('h1::text').get()
yield {"url": response.url, "title": title}
MultiPageSpider().start()
Pause und Fortsetzen
Scrapling unterstützt checkpoint-basierte Persistenz. Wenn du Strg+C drückst, um elegant zu beenden, wird beim nächsten Start automatisch fortgesetzt.
class LongRunningSpider(Spider):
name = "long-crawl"
start_urls = ["https://large-site.com/"]
custom_settings = {
"checkpoint_dir": "./checkpoints", # Checkpoint-Verzeichnis
}
async def parse(self, response: Response):
# Daten extrahieren...
yield {"data": "..."}
# Weiter crawlen
for link in response.css('a::attr(href)').getall():
yield self.follow(link, callback=self.parse)
LongRunningSpider().start()
Praxisbeispiele
Fall 1: GitHub Trending-Projekte scrapen
from scrapling.fetchers import Fetcher
def scrape_github_trending():
page = Fetcher.fetch('https://github.com/trending')
repos = page.css('.Box-row')
trending = []
for repo in repos[:10]:
name = repo.css('h2 a::text').get('').strip()
description = repo.css('p.col-9::text').get('').strip()
stars = repo.css('[href$=stargazers] span::text').get('').strip()
language = repo.css('[itemprop=programmingLanguage]::text').get('').strip()
trending.append({
"name": name,
"description": description,
"stars": stars,
"language": language
})
return trending
if __name__ == "__main__":
results = scrape_github_trending()
for repo in results:
print(f"📦 {repo['name']}")
print(f" {repo['description'][:80]}...")
print(f" ⭐ {repo['stars']} | 📝 {repo['language']}")
print()
Fall 2: E-Commerce-Preisüberwachung
from scrapling.fetchers import StealthyFetcher
import json
from datetime import datetime
def monitor_prices():
urls = [
"https://amazon.com/dp/B08N5WRWNW",
"https://amazon.com/dp/B0BSHF7WHW",
"https://amazon.com/dp/B09G9FPHY6",
]
results = []
for url in urls:
page = StealthyFetcher.fetch(url, headless=True)
title = page.css('#productTitle::text').get('').strip()
price = page.css('.a-price .a-offscreen::text').get('').strip()
results.append({
"url": url,
"title": title,
"price": price,
"timestamp": datetime.now().isoformat()
})
print(f"✅ {title[:50]}... - {price}")
# In JSON speichern
with open('price_monitor.json', 'w', encoding='utf-8') as f:
json.dump(results, f, ensure_ascii=False, indent=2)
print(f"\n📊 {len(results)} Preisdaten in price_monitor.json gespeichert")
if __name__ == "__main__":
monitor_prices()
Fall 3: Streaming-Ausgabe (Echtzeit-Verarbeitung)
Für lang laufende Crawler kannst du den Streaming-Modus verwenden, um Daten in Echtzeit zu verarbeiten.
from scrapling.spiders import Spider, Response
class StreamingSpider(Spider):
name = "streaming-demo"
start_urls = ["https://quotes.toscrape.com/"]
async def parse(self, response: Response):
for quote in response.css('.quote'):
item = {
"text": quote.css('.text::text').get(),
"author": quote.css('.author::text').get()
}
yield item # Sofort ausgeben, nicht auf Fertigstellung warten
next_page = response.css('.next a::attr(href)').get()
if next_page:
yield self.follow(next_page, callback=self.parse)
# Streaming-Konsum
async def main():
spider = StreamingSpider()
async for item in spider.stream():
# Jedes Item in Echtzeit verarbeiten
print(f"Empfangen: {item['text'][:50]}... von {item['author']}")
# Kann sofort in Datenbank gespeichert oder an Message Queue gesendet werden
import asyncio
asyncio.run(main())
Fortgeschrittene Tipps
1. Proxy-Rotation
from scrapling.spiders import Spider, Response
class ProxySpider(Spider):
name = "proxy-spider"
start_urls = ["https://httpbin.org/ip"]
custom_settings = {
"proxy_list": [
"http://proxy1.example.com:8080",
"http://proxy2.example.com:8080",
"http://proxy3.example.com:8080",
],
"proxy_rotation": "per_request", # Proxy bei jeder Anfrage rotieren
}
async def parse(self, response: Response):
ip = response.json().get('origin')
print(f"Aktuelle IP: {ip}")
2. Benutzerdefinierte Export-Pipelines
from scrapling.spiders import Spider, Response
import csv
class CSVS pider(Spider):
name = "csv-export"
start_urls = ["https://quotes.toscrape.com/"]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.csv_file = open('quotes.csv', 'w', newline='', encoding='utf-8')
self.writer = csv.writer(self.csv_file)
self.writer.writerow(['Text', 'Autor', 'Tags'])
async def parse(self, response: Response):
for quote in response.css('.quote'):
text = quote.css('.text::text').get()
author = quote.css('.author::text').get()
tags = ', '.join(quote.css('.tag::text').getall())
self.writer.writerow([text, author, tags])
next_page = response.css('.next a::attr(href)').get()
if next_page:
yield self.follow(next_page, callback=self.parse)
def close(self, reason):
self.csv_file.close()
print(f"✅ Daten in quotes.csv gespeichert")
3. Entwicklungsmodus (Response-Caching)
Beim Debuggen von Parsing-Logik solltest du vermeiden, den Server wiederholt anzufordern.
from scrapling.spiders import Spider, Response
class DevSpider(Spider):
name = "dev-mode"
start_urls = ["https://example.com"]
custom_settings = {
"dev_mode": True, # Entwicklungsmodus aktivieren
"cache_dir": "./http_cache", # Cache-Verzeichnis
}
async def parse(self, response: Response):
# Beim ersten Lauf: Response auf der Festplatte cachen
# Bei späteren Läufen: Direkt von der Festplatte lesen, keine Netzwerkanfrage nötig
title = response.css('h1::text').get()
yield {"title": title}
Häufig gestellte Fragen
F1: Was ist der Unterschied zwischen Scrapling und Scrapy?
A: Scrapling kann als moderne, erweiterte Version von Scrapy betrachtet werden: - Adaptives Parsing: Scrapy-Selektoren versagen bei Seitenüberarbeitungen, Scrapling passt sich automatisch an. - Integriertes Anti-Blocking: Scrapy benötigt zusätzliche Middleware, um Cloudflare zu umgehen, Scrapling funktioniert out-of-the-box. - Übersichtlichere API: Die Fetcher-API von Scrapling ist besser für kleines, schnelles Scraping geeignet.
Wenn du bereits mit Scrapy vertraut bist, ist der Wechsel zu Scrapling fast ohne Lernaufwand möglich.
F2: Wie gehe ich mit Seiten nach dem Login um?
A: Verwende StealthyFetcher oder DynamicFetcher, um den Login zu simulieren:
from scrapling.fetchers import DynamicFetcher
page = DynamicFetcher.fetch(
'https://example.com/login',
headless=True,
wait_for='#dashboard' # Warten, bis nach dem Login weitergeleitet wird
)
# Login durchführen (über Playwright)
page.page.fill('#username', 'dein_benutzername')
page.page.fill('#password', 'dein_passwort')
page.page.click('#login-button')
page.page.wait_for_selector('#dashboard')
# Jetzt können Inhalte nach dem Login gescrapt werden
data = page.css('.private-data::text').getall()
F3: Wie begrenze ich die Crawling-Geschwindigkeit, um Blockierungen zu vermeiden?
A: Konfiguriere Download-Verzögerungen und Parallelitätslimits im Spider:
class PoliteSpider(Spider):
custom_settings = {
"concurrency": 2, # Parallelität reduzieren
"download_delay": 2, # 2 Sekunden Intervall zwischen jeder Anfrage
"robots_txt_obey": True, # robots.txt beachten
}
F4: Welche Selektoren unterstützt Scrapling?
A: Es unterstützt CSS-Selektoren und XPath:
# CSS-Selektoren
page.css('.class-name::text').get()
page.css('#id-name').getall()
# XPath
page.xpath('//div[@class="example"]/text()').get()
Zusammenfassung
Scrapling ist das Python-Web-Scraping-Framework, auf das man 2026 am meisten achten sollte. Es kombiniert adaptives Parsing, Anti-Blocking-Fähigkeiten und eine Scrapy-ähnliche API perfekt, sodass Entwickler mit minimalem Code die stabilsten Crawler implementieren können.
Rückblick auf die Kernvorteile: - ✅ Adaptiver Parser: Lokalisiert Elemente nach Seitenüberarbeitungen automatisch neu - ✅ Integriertes Anti-Blocking: Umgeht Cloudflare Turnstile out-of-the-box - ✅ Von der Einzelanfrage bis zum Voll-Crawl: Dieselbe API deckt alle Szenarien ab - ✅ Parallelität, Pause/Fortsetzen, Streaming-Ausgabe: Produktionsreife Features rundum vorhanden
Ressourcen-Links: - GitHub-Repository - Offizielle Dokumentation - Discord-Community
Wenn dir dieser Artikel geholfen hat, teile ihn gerne mit anderen Entwicklern!