MCP HubMCP Hub
스킬 목록으로 돌아가기

headless-web-scraping

pjt222
업데이트됨 Yesterday
5 조회
17
2
17
GitHub에서 보기
디자인apiautomationdesigndata

정보

이 스킬은 scrapling Python 라이브러리를 사용해 웹 페이지에서 데이터를 추출하며, 사이트 방어 수준에 따라 HTTP, 스텔스 크로미움, 완전 브라우저 자동화 중 적절한 방식을 자동 선택합니다. JavaScript 렌더링 콘텐츠와 봇 방지 보호 사이트를 처리할 수 있으며, CSS 선택자를 활용한 구조화된 데이터 추출이 가능합니다. 동적 콘텐츠로 인해 WebFetch가 실패하거나 다중 요소 추출을 위해 DOM 탐색이 필요한 경우 사용하세요.

빠른 설치

Claude Code

추천
기본
npx skills add pjt222/agent-almanac -a claude-code
플러그인 명령대체
/plugin add https://github.com/pjt222/agent-almanac
Git 클론대체
git clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/headless-web-scraping

Claude Code에서 이 명령을 복사하여 붙여넣어 스킬을 설치하세요

문서

無頭網頁抓取

以 scrapling 之三層抓取器架構與 CSS 基資料提取自阻簡單 HTTP 請求之網頁——JS 渲染內容、 Cloudflare 保護站與動態 SPA——提取資料。

適用時機

  • 目標頁需 JavaScript 渲染(SPA、React、Vue)
  • 站有反爬保護(Cloudflare Turnstile、TLS 指紋)
  • 需經 CSS 選擇器結構化提取多元素
  • 簡單 WebFetchrequests.get() 返空或被阻之響應
  • 大規模提取表資料、連結列或重複 DOM 結構

輸入

  • 必要:目標 URL 或欲抓取之 URL 列表
  • 必要:欲提取之資料(CSS 選擇器、欄位名或目標元素之描述)
  • 選擇性:抓取器層覆寫(預設:依站行為自動選)
  • 選擇性:輸出格式(預設:JSON;替代:CSV、Python dict)
  • 選擇性:秒之速率限延遲(預設:1)

步驟

步驟一:擇抓取器層

定何 scrapling 抓取器配目標站之防禦。

# 決策矩陣:
# 1. Fetcher        — 靜態 HTML、無 JS、無反爬(最速)
# 2. StealthyFetcher — Cloudflare/Turnstile、TLS 指紋核
# 3. DynamicFetcher  — JS 渲染之 SPA、點擊/滾動互動

# 快速試探:先 Fetcher,失則升級
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")
訊號建議層
靜態 HTML、無保護Fetcher
403/503、Cloudflare 挑戰頁StealthyFetcher
頁載但內容區空DynamicFetcher
需點按鈕或滾動DynamicFetcher
altcha CAPTCHA 存無(不可自動化)

預期: 三層之一已識。對多數現代站,StealthyFetcher 為正確起點。

失敗時: 若三層皆返阻響應,核站是否用 altcha CAPTCHA(不可繞之工作量證明挑戰)。若然,記限並供手動提取指引。

步驟二:配抓取器

以合宜選項設所擇抓取器。

from scrapling import Fetcher, StealthyFetcher, DynamicFetcher

# 層一:以 TLS 指紋假冒之快速 HTTP
fetcher = Fetcher()
fetcher.configure(
    timeout=30,
    retries=3,
    follow_redirects=True
)

# 層二:附反偵測之無頭 Chromium
fetcher = StealthyFetcher()
fetcher.configure(
    headless=True,
    timeout=60,
    network_idle=True  # 待所有網路請求定
)

# 層三:完全瀏覽器自動化
fetcher = DynamicFetcher()
fetcher.configure(
    headless=True,
    timeout=90,
    network_idle=True,
    wait_selector="div.results"  # 提取前待特定元素
)

預期: 抓取器實例已配可用。實例化無錯。StealthyFetcherDynamicFetcher 須 Chromium 二進制(scrapling 首次執行自動管之)。

失敗時:

  • playwright 或瀏覽器二進制未覓 —— 執行 python -m playwright install chromium
  • configure() 之逾時 —— 增逾時值或核網路連線
  • 導入錯 —— 裝 scrapling:pip install scrapling

步驟三:抓取並提取資料

導至目標 URL 並以 CSS 選擇器提取結構化資料。

# 抓取頁
response = fetcher.get("https://example.com/target-page")

# 單元素提取
title = response.find("h1.page-title")
if title:
    print(title.get_all_text())

# 多元素
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()}")

# 取屬性值
links = response.find_all("a.product-link")
urls = [link.get("href") for link in links]

# 取元素之原始 HTML 內容
detail_html = response.find("div.description").html_content

關鍵 API 參考:

方法用途
response.find("selector")首配之元素
response.find_all("selector")所有配之元素
element.get("attr")屬性值(href、src、data-*)
element.get_all_text()所有文字內容,遞迴
element.html_content原始內部 HTML

預期: 所提取資料配可見頁內容。元素非 None,文字內容於有內容頁非空。

失敗時:

  • find()None —— 察實際 HTML(response.html_content)以驗選擇器;頁或用與預期不同之類名
  • get_all_text() 空 —— 內容或於 shadow DOM 或 iframe 中;試 DynamicFetcherwait_selector
  • 勿用 .css_first() —— 非 scrapling API 之部分(常與他庫混淆)

步驟四:處理失敗與邊緣情形

為 CAPTCHA 偵測、空響應與會話需求實退路邏輯。

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

        # 偵測 CAPTCHA / 挑戰頁
        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

預期: 函數成功時返所提取文字,或於所有層失敗時返 None 附診斷訊息。CAPTCHA 頁被偵測並報,非無限重試。

失敗時:

  • 所有層返 403 —— 站阻所有自動化存取(WIPO、TMview、部分政府資料庫常見);記此 URL 為需手動存取
  • 逾時錯 —— 頁或於慢 CDN 後;增逾時至 120 秒
  • 會話/cookie 錯 —— 站或需登入;加 cookie 處理或先認證

步驟五:速率限與倫理抓取

大規模執行前實延遲並尊重站之政策。

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)  # 尊重伺服器

    return results

倫理抓取清單:

  1. 抓取前核 robots.txt —— 尊重 Disallow 指令
  2. 請求間用最少一秒延遲
  3. 可能時以描述性 User-Agent 識別抓取器
  4. 勿無法律基抓取個資
  5. 本地快取響應以避冗請求
  6. 收 429(過多請求)即停

預期: 抓取於受控速率執行。大量操作前核 robots.txt。無 429 響應觸發。

失敗時:

  • 429 過多請求 —— 增延遲至三至五秒或停後再試
  • robots.txt 不允路徑 —— 尊重指令;勿覆寫
  • IP 封鎖 —— 立即停;速率限不足。若存取合法(公共資料、ToS 允、robots.txt 尊重)且必續,見 rotate-scraping-proxies 之網路層升級

驗證

  • 擇正確抓取器層(不過強亦不過弱)
  • configure() 方法(非棄之建構子關鍵字參數)
  • CSS 選擇器配實頁結構(對頁源驗之)
  • .find() / .find_all() API(非 .css_first() 或他庫方法)
  • CAPTCHA 偵測已設(altcha 頁報而非重試)
  • 多 URL 抓取實速率限
  • 大量操作前核 robots.txt
  • 所提取資料非空且結構正確

常見陷阱

  • .css_first() 而非 .find():scrapling 用 .find().find_all() 以選元素 —— .css_first() 屬他庫,將引 AttributeError
  • 起於 DynamicFetcher:永先試 Fetcher 再升級 —— DynamicFetcher 因完整瀏覽器啟動慢十至五十倍
  • 建構子 kwargs 而非 configure():scrapling v0.4.x 棄傳選項予建構子;永用 configure() 方法
  • 忽 altcha CAPTCHA:無抓取器層可解 altcha 工作量證明挑戰 —— 早偵之並退至手動指引
  • 無速率限:即站不返 429,激進抓取可致 IP 封或服務降級
  • 假設穩定選擇器:網站 CSS 類常變 —— 每抓取前驗選擇器於當前頁源

相關技能

<!-- Keep under 500 lines. Extract large examples to references/EXAMPLES.md if needed. -->

GitHub 저장소

pjt222/agent-almanac
경로: i18n/wenyan-lite/skills/headless-web-scraping
0
agentsagentskillsai-assisted-developmentclaude-codeskillsteams

연관 스킬

executing-plans

디자인

executing-plans 스킬은 검토 체크포인트가 포함된 통제된 배치로 실행할 완전한 구현 계획이 있을 때 사용합니다. 이 스킬은 계획을 불러와 비판적으로 검토한 후, 소규모 배치(기본값 3개 작업)로 작업을 실행하면서 각 배치 사이에 진행 상황을 아키텍트 검토를 위해 보고합니다. 이를 통해 내재된 품질 관리 체크포인트를 갖춘 체계적인 구현이 보장됩니다.

스킬 보기

requesting-code-review

디자인

이 스킬은 코드 변경 사항을 요구 사항에 따라 분석하기 위해 코드 리뷰어 하위 에이전트를 호출합니다. 작업 완료 후, 주요 기능 구현 후, 또는 메인 브랜치에 병합하기 전에 사용해야 합니다. 이 리뷰는 현재 구현체와 원래 계획을 비교하여 문제를 조기에 발견하는 데 도움이 됩니다.

스킬 보기

connect-mcp-server

디자인

이 스킬은 개발자들이 HTTP, stdio 또는 SSE 전송 방식을 통해 MCP 서버를 Claude Code에 연결하는 포괄적인 가이드를 제공합니다. GitHub, Notion 및 사용자 정의 API와 같은 외부 서비스를 통합하기 위한 설치, 구성, 인증 및 보안을 다룹니다. MCP 통합 설정, 외부 도구 구성 또는 Claude의 모델 컨텍스트 프로토콜 작업 시 활용하세요.

스킬 보기

web-cli-teleport

디자인

이 스킬은 작업 분석을 기반으로 개발자가 Claude Code 웹 인터페이스와 CLI 인터페이스 중 선택할 수 있도록 돕고, 두 환경 간 원활한 세션 텔레포트를 가능하게 합니다. 웹, CLI 또는 모바일 환경 전환 시 세션 상태와 컨텍스트를 관리하여 워크플로를 최적화합니다. 다양한 단계에서 서로 다른 도구가 필요한 복잡한 프로젝트에 사용하세요.

스킬 보기