XPath Crawling Complete Guide 2026: Der Schlüssel zur präzisen Extraktion von Webdaten

Ich habe eine vollständige Anleitung zum Web-Scraping mit XPath von Anfang bis Ende erstellt. Es enthält Python lxml/requests Beispiele, einen Vergleich mit CSS-Selektoren und wichtige Ausdrücke bis zum Jahr 2026.

24
XPath Crawling Complete Guide 2026: Der Schlüssel zur präzisen Extraktion von Webdaten

웹-Scraping beginnt in der Regel mit dem Erlernen von CSS-Selektoren. Wenn Sie jedoch auf komplexere Seiten treffen, kann es schwierig sein, die gewünschten Elemente nur mit CSS-Selektoren zu extrahieren. Dies tritt auf, wenn Sie nur Elemente auswählen möchten, die einen bestimmten Text enthalten, rückwärts nach Elternknoten mit bestimmten Kindknoten suchen oder bedingte Filter anwenden müssen.

In solchen Fällen ist XPath erforderlich.

XPath ist eine Standardsprache zum Navigieren durch bestimmte Knoten in XML-/HTML-Dokumenten. Es ist leistungsfähiger als CSS-Selektoren und ermöglicht in einigen Fällen die Auswahl, die mit CSS überhaupt nicht möglich ist. Bis zum Jahr 2026 unterstützen alle wichtigen Scraping-Tools wie Python lxml, Scrapy, Playwright und Selenium XPath.

In diesem Artikel werden vom Grundkonzept von XPath über praktische Scraping-Codes bis hin zu Debugging-Tipps alles auf einmal zusammengefasst.


1. Was ist XPath?

XPath (XML Path Language) ist ein W3C-Standard und eine Abfragesprache zum Navigieren durch die Baumstruktur von XML- und HTML-Dokumenten. Seit seiner ersten Veröffentlichung im Jahr 1999 hat es sich als Kerntechnologie des Webstandards etabliert.

Das HTML einer Webseite ist eine Baumstruktur. Es beginnt mit der Wurzel html, gefolgt von body, verschiedenen div-, span- und a-Tags, die in Eltern-Kind-Beziehung stehen. XPath stellt diese Baumstruktur ähnlich wie Dateisystempfade dar.

Zum Beispiel wird im Dateisystem ein Pfad wie /home/user/documents/report.txt angegeben, während in HTML ein Knoten mit /html/body/div/p spezifiziert wird.

CSS-Selektor vs. XPath: Wann verwendet man was?

Funktion CSS-Selektor XPath
Grundlegende Elementauswahl Kompakt Möglich
Auswahl von Elementen mit bestimmtem Text Nicht möglich contains(text(), 'Stichwort')
Rückwärtsauswahl des Elternknotens Nicht möglich .. oder parent::
Zugriff auf Geschwisterknoten Eingeschränkt following-sibling::, preceding-sibling::
Bedingte Filterung Nur grundlegend Komplexe Bedingungen möglich
Lernschwierigkeit Einfach Mittel
Browserleistung Schnell Etwas langsamer

In der Regel ist es effektiv, CSS-Selektoren als Grundlage zu verwenden und bei Bedarf XPath als Unterstützung einzusetzen.


2. Referenz zur Kernsyntax von XPath

Grundausdruck für Pfade

/html/body/div          # 절대 경로 (루트부터 전체 경로)
//div                   # 문서 전체에서 모든 div 요소
//div[@class='title']   # class 'title' div
//a[@href]              # href 속성이 있는 모든 a 태그

Das Doppel-Slash // ist entscheidend. In der Praxis werden relative Pfade mit // häufiger verwendet als absolute Pfade (/html/body/...), da sie auch bei Änderungen in der Seitenstruktur relativ stabil sind.

Attributselektor

//div[@id='main']                    # id 'main' div
//input[@type='submit']              # type 'submit' input
//a[contains(@class, 'btn')]         # class 'btn' 포함된 a
//img[@src and @alt]                 # src alt 속성 모두 있는 img
//a[not(@href)]                      # href 없는 a 태그

contains() ähnelt CSS [class*="btn"], kann jedoch auch auf den Textinhalt angewendet werden, was deutlich flexibler ist.

Textselektor

//h2[text()='이벤트 공지']                    # 정확히 '이벤트 공지' 텍스트인 h2
//p[contains(text(), '할인')]                  # '할인' 텍스트를 포함하는 p
//button[normalize-space(text())='구매하기']   # 공백 제거  '구매하기' 버튼

Hier liegt die Stärke von XPath. CSS-Selektoren können keine Elemente basierend auf dem Textinhalt auswählen, aber XPath ermöglicht dies durch die Kombination von text() und contains().

Achsen-Navigation

//span[@class='price']/parent::div          # 특정 span 부모 div
//td[contains(@class, 'total')]/../td[1]    # 형제 td  번째
//h3/following-sibling::p                   # h3 다음에 오는 형제 p 태그
//li[last()]                                # 마지막 li 항목
//li[position() <= 5]                       #  5 li 항목

Die Rückwärtsnavigation zum Elternknoten ist eine Funktion, die nur in XPath möglich ist. Zum Beispiel ist dies nützlich, wenn Sie den gesamten Kartencontainer abrufen möchten, der einen bestimmten Klassenbutton enthält.


3. XPath-Scraping mit Python (lxml)

Grundinstallation und Struktur

import requests
from lxml import html

url = "https://example.com/products"
response = requests.get(url, headers={
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)"
})

tree = html.fromstring(response.content)

# XPath로 데이터 추출
titles = tree.xpath('//h2[@class="product-title"]/text()')
prices = tree.xpath('//span[@class="price"]/text()')
links = tree.xpath('//a[@class="product-link"]/@href')

for title, price, link in zip(titles, prices, links):
    print(f"{title} | {price} | {link}")

Analysieren Sie HTML mit lxml.html.fromstring() und übergeben Sie den XPath-Ausdruck an die Methode .xpath(). Das Ergebnis ist eine Liste.

Text vs. @Attributauswahl

# 요소 텍스트 추출: /text()
titles = tree.xpath('//h1/text()')

# 속성값 추출: /@속성명
hrefs = tree.xpath('//a/@href')
images = tree.xpath('//img/@src')

# 요소 객체 자체를 가져올 때 (하위 탐색 필요 시)
product_cards = tree.xpath('//div[@class="product-card"]')
for card in product_cards:
    title = card.xpath('.//h2/text()')  # 점(.)은 현재 요소 기준
    price = card.xpath('.//span[@class="price"]/text()')
    print(title[0] if title else "N/A", price[0] if price else "N/A")

Wichtig zu wissen: Wenn Sie über Elementobjekte iterieren, müssen Sie in der internen .xpath()-Anweisung einen Punkt (.) hinzufügen, um relativ zum aktuellen Element zu suchen. Wenn Sie //h2/text() ohne Punkt verwenden, wird das gesamte Dokument erneut durchsucht.

Flexibles Auswählen mit contains()

# class에 특정 단어가 포함된 경우
items = tree.xpath('//*[contains(@class, "item")]')

# 텍스트에 특정 단어가 포함된 링크
discount_links = tree.xpath('//a[contains(text(), "할인")]/@href')

# 여러 조건 조합 (and/or)
main_buttons = tree.xpath('//button[contains(@class, "btn") and @type="submit"]')

4. Scraping dynamischer Seiten: Playwright + XPath

Statische HTML-Seiten können mit requests + lxml ausreichen, aber für JavaScript-gerenderte dynamische Seiten sind Playwright oder Selenium erforderlich. Beide Tools unterstützen XPath.

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page()
    page.goto("https://target-site.com")

    # XPath로 요소 선택
    # locator 방식 (권장)
    price = page.locator('xpath=//span[@class="final-price"]').first.text_content()

    # evaluate로 XPath 직접 실행
    result = page.evaluate("""
        () => {
            const el = document.evaluate(
                '//h1[@class="product-name"]/text()',
                document,
                null,
                XPathResult.FIRST_ORDERED_NODE_TYPE,
                null
            ).singleNodeValue;
            return el ? el.nodeValue : null;
        }
    """)

    print(price, result)
    browser.close()

Fügen Sie dem XPath-Ausdruck in Playwright locator('xpath=...') voran, um ihn zu verwenden.


5. XPath-Debugging: Direktes Testen im Browser

Bevor Sie Scraping-Code schreiben, können Sie überprüfen, ob das XPath im Browser korrekt ist.

Verwendung der Chrome-Entwicklertools:
1. Drücken Sie F12 oder klicken Sie mit der rechten Maustaste → Inspektion
2. Wählen Sie den Tab Konsole
3. Geben Sie den folgenden Code ein:

// 단일 요소 찾기
$x('//h1[@class="title"]')

// 모든 매칭 요소 텍스트 출력
$x('//span[@class="price"]').map(e => e.textContent)

// 첫 번째 매칭 텍스트
$x('//div[@class="product-name"]')[0]?.textContent

$x() ist eine integrierte XPath-Testfunktion, die sowohl in Chrome als auch in Firefox verfügbar ist. Stellen Sie sicher, dass das gewünschte Element mit dieser Funktion korrekt ausgewählt wird, bevor Sie den Code schreiben.


6. Praxisbeispiel: Extrahieren von E-Commerce-Produktdaten

import requests
from lxml import html

def scrape_product_list(url):
    headers = {"User-Agent": "Mozilla/5.0 (compatible; DataCollector/1.0)"}
    resp = requests.get(url, headers=headers, timeout=10)
    tree = html.fromstring(resp.content)

    # 상품 카드 전체 목록 가져오기
    cards = tree.xpath('//li[contains(@class, "product-item")]')

    results = []
    for card in cards:
        name = card.xpath('.//strong[@class="product-name"]/text()')
        price = card.xpath('.//span[contains(@class, "price")]/text()')
        rating = card.xpath('.//span[@class="rating"]/text()')
        reviews = card.xpath('.//span[@class="review-count"]/text()')
        link = card.xpath('.//a[@class="product-link"]/@href')

        results.append({
            "name": name[0].strip() if name else None,
            "price": price[0].strip() if price else None,
            "rating": rating[0].strip() if rating else None,
            "reviews": reviews[0].strip() if reviews else None,
            "url": link[0] if link else None,
        })

    return results

products = scrape_product_list("https://example-shop.com/category/shoes")
print(f"수집된 상품 수: {len(products)}")

7. Häufige Fehler und deren Behebung

IndexError: list index out of range

# 잘못된 방법
title = tree.xpath('//h1/text()')[0]  # 요소 없으면 에러 발생

# 올바른 방법
titles = tree.xpath('//h1/text()')
title = titles[0] if titles else None

Element sichtbar, aber nicht mit XPath erfasst

Die Ursache liegt meistens an Namensräumen oder dynamischen Rendering-Problemen.

# 네임스페이스가 있는 경우
namespaces = {'ns': 'http://www.w3.org/1999/xhtml'}
result = tree.xpath('//ns:div[@id="content"]', namespaces=namespaces)

# 실제로 화면에는 있지만 XPath로 안 잡힐 때 → 동적 렌더링 확인
# requests로 받은 HTML에는 없고, 브라우저에서만 보이는 경우
# → Playwright/Selenium으로 전환 필요

Leerzeichenprobleme beim Extrahieren von Text

# normalize-space()로 앞뒤 공백 및 연속 공백 제거
clean_text = tree.xpath('normalize-space(//h1/text())')

# Python에서 후처리
texts = [t.strip() for t in tree.xpath('//p/text()') if t.strip()]

8. Grenzen von XPath und Alternativen

Obwohl XPath leistungsstark ist, hat es auch seine Grenzen.

Anfällig für Strukturänderungen: Wenn Sie den absoluten Pfad (/html/body/div[2]/div[3]/ul/li) verwenden, wird der gesamte XPath bei einer Site-Neugestaltung nutzlos. Verwenden Sie stattdessen XPath basierend auf @id und @class.

JavaScript-Rendering: XPath ist ein HTML-Analysetool, kein Rendering-Tool. Dynamisch geladene Inhalte können nicht mit requests + lxml gesammelt werden.

Großangelegtes Scraping: Für das Sammeln von Tausenden von Seiten ist es effizienter, Scrapy zu verwenden, das sowohl XPath als auch CSS-Selektoren unterstützt und über Funktionen wie asynchrone Verarbeitung, Middleware und Pipelines verfügt.


Scraping ohne XPath mit HashScraper

Das Erlernen von XPath ist zwar nützlich, aber die Kosten für die Wartung eines Produktions-Crawlers sind oft höher als gedacht. Sie müssen XPath jedes Mal aktualisieren, wenn sich die Website-Struktur ändert, und sich um JavaScript-Rendering, IP-Blockaden usw. kümmern.

HashScraper erledigt diesen Prozess mit einem einzigen API-Aufruf. Geben Sie einfach die URL an, ohne zusätzliche XPath- oder CSS-Selektoren, und erhalten Sie das JavaScript-gerenderte HTML im Markdown-, JSON- oder HTML-Format zurück.

import requests

response = requests.post(
    "https://api.hashscraper.com/v1/scrape",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "url": "https://target-site.com/products",
        "renderJs": True,
        "outputFormat": "markdown"
    }
)

data = response.json()
print(data["content"])  # 정제된 마크다운으로 반환

Wenn Sie keine Zeit haben, einen Crawler selbst zu erstellen oder sich um das Crawling-Setup kümmern möchten, starten Sie mit dem kostenlosen Test von HashScraper.


Zusammenfassung

  • XPath wird für komplexe Auswahl verwendet, die nicht mit CSS-Selektoren gelöst werden können
  • Textbasierte Auswahl, Rückwärtsnavigation zum Elternknoten, bedingte Filterung sind die Hauptvorteile
  • Python: Kombination von lxml und .xpath() ist am verbreitetsten
  • Dynamische Seiten: Verwendung von Playwright locator('xpath=...')
  • Debugging: Schnelles Testen mit Chrome-Konsole $x()
  • Für groß angelegtes Scraping sollten Sie die Verwendung des HashScraper-APIs in Betracht ziehen

Wenn Ihnen dieser Artikel geholfen hat, lesen Sie auch den umfassenden Leitfaden zum Playwright-Scraping und den umfassenden Leitfaden zum Scrapy-Scraping.

Comments

Add Comment

Your email won't be published and will only be used for reply notifications.

Weiterlesen

Get notified of new posts

We'll email you when 해시스크래퍼 기술 블로그 publishes new content.

Your email will only be used for new post notifications.