技能创建器
skill-creator
创建、改进和评估自定义技能,把专业流程转化为可重复使用的 AI 能力。
headless-web-scraping【数据与研究】Extract data from web pages using the scrapling Python library — select the appropriate fetcher tier (HTTP, stealth Chromium, or full browser automation) based on target site defenses, configure headless browsing, and extract structured data with CSS selectors. Use when WebFetch is insufficient for JS-rendered pages, anti-bot-protected sites, or stru…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
Extract data from web pages that resist simple HTTP requests — JS-rendered content, Cloudflare-protected sites, dynamic SPAs — using scrapling three-tier fetcher architecture + CSS-based data extraction.
WebFetch or requests.get() returns empty or blocked responsesFind which scrapling fetcher matches target site defenses.
# Decision matrix:
# 1. Fetcher — static HTML, no JS, no anti-bot (fastest)
# 2. StealthyFetcher — Cloudflare/Turnstile, TLS fingerprint checks
# 3. DynamicFetcher — JS-rendered SPAs, click/scroll interactions
# Quick probe: try Fetcher first, escalate on failure
from scrapling import Fetcher
fetcher = Fetcher()
response = fetcher.get("https://example.com/target-page")
if response.status == 200 and response.get_all_text():
print("Fetcher tier sufficient")
else:
print("Escalate to StealthyFetcher or DynamicFetcher")
| Signal | Recommended Tier |
|---|---|
| Static HTML, no protection | Fetcher |
| 403/503, Cloudflare challenge page | StealthyFetcher |
| Page loads but content area empty | DynamicFetcher |
| Need to click buttons or scroll | DynamicFetcher |
| altcha CAPTCHA present | None (cannot be automated) |
Got: One of three tiers identified. Most modern sites → StealthyFetcher correct starting point.
If fail: All three tiers return blocked responses? Check if site uses altcha CAPTCHA (proof-of-work challenge can't be bypassed). If so, document limitation + provide manual extraction instructions.
Set up selected fetcher with appropriate options.
from scrapling import Fetcher, StealthyFetcher, DynamicFetcher
# Tier 1: Fast HTTP with TLS fingerprint impersonation
fetcher = Fetcher()
fetcher.configure(
timeout=30,
retries=3,
follow_redirects=True
)
# Tier 2: Headless Chromium with anti-detection
fetcher = StealthyFetcher()
fetcher.configure(
headless=True,
timeout=60,
network_idle=True # wait for all network requests to settle
)
# Tier 3: Full browser automation
fetcher = DynamicFetcher()
fetcher.configure(
headless=True,
timeout=90,
network_idle=True,
wait_selector="div.results" # wait for specific element before extracting
)
Got: Fetcher instance configured + ready. No errors on instantiation. StealthyFetcher + DynamicFetcher → Chromium binary available (scrapling manages this automatically on first run).
If fail:
playwright or browser binary not found -- run python -m playwright install chromiumconfigure() -- increase timeout value or check network connectivitypip install scraplingNavigate to target URL + extract structured data with CSS selectors.
# Fetch the page
response = fetcher.get("https://example.com/target-page")
# Single element extraction
title = response.find("h1.page-title")
if title:
print(title.get_all_text())
# Multiple elements
items = response.find_all("div.result-item")
for item in items:
name = item.find("span.name")
price = item.find("span.price")
print(f"{name.get_all_text()}: {price.get_all_text()}")
# Get attribute values
links = response.find_all("a.product-link")
urls = [link.get("href") for link in links]
# Get raw HTML content of an element
detail_html = response.find("div.description").html_content
Key API reference:
| Method | Purpose |
|---|---|
response.find("selector") | First matching element |
response.find_all("selector") | All matching elements |
element.get("attr") | Attribute value (href, src, data-*) |
element.get_all_text() | All text content, recursively |
element.html_content | Raw inner HTML |
Got: Extracted data matches visible page content. Elements non-None + text content non-empty for populated pages.
If fail:
find() returns None -- inspect actual HTML (response.html_content) to verify selector; page may use different class names than expectedget_all_text() -- content may be inside shadow DOM or iframe; try DynamicFetcher with wait_selector.css_first() -- not part of scrapling API (common confusion with other libraries)Implement fallback logic for CAPTCHA detection, empty responses, session requirements.
import time
def scrape_with_fallback(url, selector):
"""Try each fetcher tier in order, with CAPTCHA detection."""
tiers = [
("Fetcher", Fetcher),
("StealthyFetcher", StealthyFetcher),
("DynamicFetcher", DynamicFetcher),
]
for tier_name, tier_class in tiers:
fetcher = tier_class()
fetcher.configure(headless=True, timeout=60)
try:
response = fetcher.get(url)
except Exception as error:
print(f"{tier_name} failed: {error}")
continue
# Detect CAPTCHA / challenge pages
page_text = response.get_all_text().lower()
if "altcha" in page_text or "proof of work" in page_text:
print(f"altcha CAPTCHA detected -- cannot automate")
return None
if response.status == 403 or response.status == 503:
print(f"{tier_name} blocked (HTTP {response.status}), escalating")
continue
result = response.find(selector)
if result and result.get_all_text().strip():
return result.get_all_text()
print(f"{tier_name} returned empty content, escalating")
print("All tiers exhausted. Manual extraction required.")
return None
Got: Function returns extracted text on success, or None with diagnostic message when all tiers fail. CAPTCHA pages detected + reported not retried indefinitely.
If fail:
Implement delays + respect site policies before running at scale.
import time
import urllib.robotparser
def check_robots_txt(base_url, target_path):
"""Check if scraping is allowed by robots.txt."""
rp = urllib.robotparser.RobotFileParser()
rp.set_url(f"{base_url}/robots.txt")
rp.read()
return rp.can_fetch("*", f"{base_url}{target_path}")
def scrape_urls(urls, selector, delay=1.0):
"""Scrape multiple URLs with rate limiting."""
results = []
fetcher = StealthyFetcher()
fetcher.configure(headless=True, timeout=60)
for url in urls:
response = fetcher.get(url)
data = response.find(selector)
if data:
results.append(data.get_all_text())
time.sleep(delay) # respect the server
return results
Ethical scraping checklist:
robots.txt before scraping -- respect Disallow directivesGot: Scraping runs at controlled rate. robots.txt checked before bulk operations. No 429 responses triggered.
If fail:
robots.txt disallows path -- respect directive; do not overrideconfigure() method used (not deprecated constructor kwargs).find() / .find_all() API used (not .css_first() or other library methods)robots.txt checked before bulk operations.css_first() instead of .find(): scrapling uses .find() + .find_all() for element selection -- .css_first() belongs to different library, raises AttributeErrorFetcher first, then escalate -- DynamicFetcher 10-50x slower due to full browser startupconfigure(): scrapling v0.4.x deprecated passing options to constructor; always use configure() method