Wie verwende ich Xpath in Python?

224

Welche Bibliotheken unterstützen Xpath? Gibt es eine vollständige Implementierung? Wie wird die Bibliothek genutzt? Wo ist die Website?

smci
quelle
4
Ich habe diesen hinterhältigen Verdacht, dass die Antworten auf diese Frage jetzt etwas abgestanden sind.
Warren P
4
Die Antwort von @ gringo-suave sieht nach einem guten Update aus. stackoverflow.com/a/13504511/1450294
Michael Scheper
Scrapy bietet XPath-Selektoren an .
CS95
Wie @WarrenP sagt, sind die meisten Antworten hier extrem veraltetes altes Python-2.x, wirklich veraltet. Vielleicht sollte diese Frage mit python-2.x
smci

Antworten:

129

libxml2 hat eine Reihe von Vorteilen:

  1. Einhaltung der Spezifikation
  2. Aktive Entwicklung und Beteiligung der Gemeinschaft
  3. Geschwindigkeit. Dies ist wirklich ein Python-Wrapper um eine C-Implementierung.
  4. Allgegenwart. Die libxml2-Bibliothek ist allgegenwärtig und daher gut getestet.

Nachteile sind:

  1. Einhaltung der Spezifikation . Es ist streng. Dinge wie die Standardbehandlung von Namespaces sind in anderen Bibliotheken einfacher.
  2. Verwendung von nativem Code. Dies kann ein Problem sein, abhängig davon, wie Ihre Anwendung verteilt / bereitgestellt wird. Es sind Drehzahlen verfügbar, die einige dieser Schmerzen lindern.
  3. Manuelle Ressourcenhandhabung. Beachten Sie im folgenden Beispiel die Aufrufe von freeDoc () und xpathFreeContext (). Das ist nicht sehr pythonisch.

Wenn Sie eine einfache Pfadauswahl vornehmen , bleiben Sie bei ElementTree (das in Python 2.5 enthalten ist). Wenn Sie die vollständige Einhaltung der Spezifikationen oder die Geschwindigkeit benötigen und mit der Verteilung von nativem Code fertig werden können, wählen Sie libxml2.

Beispiel für die Verwendung von libxml2 XPath


import libxml2

doc = libxml2.parseFile("tst.xml")
ctxt = doc.xpathNewContext()
res = ctxt.xpathEval("//*")
if len(res) != 2:
    print "xpath query: wrong node set size"
    sys.exit(1)
if res[0].name != "doc" or res[1].name != "foo":
    print "xpath query: wrong node set value"
    sys.exit(1)
doc.freeDoc()
ctxt.xpathFreeContext()

Beispiel für die Verwendung von ElementTree XPath


from elementtree.ElementTree import ElementTree
mydoc = ElementTree(file='tst.xml')
for e in mydoc.findall('/foo/bar'):
    print e.get('title').text

Ryan Cox
quelle
8
mit python 2.7.10 auf osx musste ich elementTree alsfrom xml.etree.ElementTree import ElementTree
Ben Page
Da es sich um einen C-Wrapper handelt, kann es schwierig sein, ihn auf AWS Lambda
bereitzustellen
85

Das lxml-Paket unterstützt xpath. Es scheint ziemlich gut zu funktionieren, obwohl ich einige Probleme mit der self :: Achse hatte. Es gibt auch Amara , aber ich habe es nicht persönlich benutzt.

James Sulak
quelle
1
amara ist ziemlich nett und man braucht nicht immer xpath.
Gatoatigrado
Bitte fügen Sie einige grundlegende Details zur Verwendung von XPath mit lxml hinzu.
jpmc26
56

Klingt wie eine lxml-Werbung hier. ;) ElementTree ist in der Standardbibliothek enthalten. Unter 2.6 und darunter ist sein xpath ziemlich schwach, aber in 2.7+ deutlich verbessert :

import xml.etree.ElementTree as ET
root = ET.parse(filename)
result = ''

for elem in root.findall('.//child/grandchild'):
    # How to make decisions based on attributes even in 2.6:
    if elem.attrib.get('name') == 'foo':
        result = elem.text
        break
Gringo Suave
quelle
39

Verwenden Sie LXML. LXML nutzt die volle Leistung von libxml2 und libxslt, umschließt sie jedoch mit mehr "Pythonic" -Bindungen als die Python-Bindungen, die in diesen Bibliotheken enthalten sind. Als solches erhält es die vollständige XPath 1.0-Implementierung. Native ElemenTree unterstützt eine begrenzte Teilmenge von XPath, obwohl es für Ihre Anforderungen möglicherweise gut genug ist.

user210794
quelle
29

Eine andere Option ist py-dom-xpath , es funktioniert nahtlos mit Minidom und ist reines Python, funktioniert also mit Appengine.

import xpath
xpath.find('//item', doc)
Sam
quelle
2
Einfacher als lxml und libxml2, wenn Sie bereits mit minidom arbeiten. Funktioniert wunderbar und ist mehr "Pythonic". Mit contextder findFunktion können Sie ein anderes xpath-Ergebnis als neuen Suchkontext verwenden.
Ben
3
Ich habe auch py-dom-xpath verwendet, als ich ein Plugin schrieb, weil es reines Python ist. Aber ich glaube nicht, dass es mehr gepflegt wird, und bin mir dieses Fehlers bewusst ("Kann nicht auf ein Element zugreifen, dessen Name 'text' ist"): code.google.com/p/py-dom-xpath/issues/detail?id = 8
Jon Coombs
py-dom-xpath scheint vor Jahren im Jahr 2010 eingemottet worden zu sein . Bitte bearbeiten Sie dies mindestens in Ihrer Antwort.
smci
14

Sie können verwenden:

PyXML :

from xml.dom.ext.reader import Sax2
from xml import xpath
doc = Sax2.FromXmlFile('foo.xml').documentElement
for url in xpath.Evaluate('//@Url', doc):
  print url.value

libxml2 :

import libxml2
doc = libxml2.parseFile('foo.xml')
for url in doc.xpathEval('//@Url'):
  print url.content
0xAX
quelle
Als ich den PyXML-Code ausprobierte, kam ich ImportError: No module named extvonfrom xml.dom.ext.reader import Sax2
Aminah Nuraini,
9

Die neueste Version von elementtree unterstützt XPath ziemlich gut. Da ich kein XPath-Experte bin, kann ich nicht sicher sagen, ob die Implementierung voll ist, aber sie hat die meisten meiner Anforderungen bei der Arbeit in Python erfüllt. Ich habe auch lxml und PyXML verwendet und finde etree nett, weil es ein Standardmodul ist.

HINWEIS: Ich habe seitdem lxml gefunden und für mich ist es definitiv die beste XML-Bibliothek für Python. Es macht XPath auch gut (obwohl wieder vielleicht keine vollständige Implementierung).

jkp
quelle
7
Die XPath-Unterstützung von ElementTree ist derzeit bestenfalls minimal. Es gibt große Lücken in der Funktionalität, wie das Fehlen von Attributselektoren, keine nicht standardmäßigen Achsen, keine untergeordnete Indizierung usw. Version 1.3 (in Alpha) fügt einige dieser Funktionen hinzu, ist jedoch immer noch eine unverschämt teilweise Implementierung.
James Brady
8

Sie können das einfache soupparservon verwendenlxml

Beispiel:

from lxml.html.soupparser import fromstring

tree = fromstring("<a>Find me!</a>")
print tree.xpath("//a/text()")
Aminah Nuraini
quelle
Welchen Unterschied macht die Verwendung von Soupparser?
Padraic Cunningham
Es ist nur eine Alternative
Aminah Nuraini
7

Wenn Sie die Leistungsfähigkeit von XPATH mit der Möglichkeit kombinieren möchten, an jedem Punkt auch CSS zu verwenden, können Sie Folgendes verwenden parsel:

>>> from parsel import Selector
>>> sel = Selector(text=u"""<html>
        <body>
            <h1>Hello, Parsel!</h1>
            <ul>
                <li><a href="http://example.com">Link 1</a></li>
                <li><a href="http://scrapy.org">Link 2</a></li>
            </ul
        </body>
        </html>""")
>>>
>>> sel.css('h1::text').extract_first()
'Hello, Parsel!'
>>> sel.xpath('//h1/text()').extract_first()
'Hello, Parsel!'
eLRuLL
quelle
Wie soll mein Xpath aussehen, wenn ich "Link 1" und "Link 2" erhalten möchte?
weefwefwqg3
1
//li/a/text()
Um
4

Eine weitere Bibliothek ist 4Suite: http://sourceforge.net/projects/foursuite/

Ich weiß nicht, wie konform es ist. Aber es hat sehr gut für meinen Gebrauch funktioniert. Es sieht verlassen aus.

Codeape
quelle
3

PyXML funktioniert gut.

Sie haben nicht gesagt, welche Plattform Sie verwenden, aber wenn Sie unter Ubuntu sind, können Sie es bekommen sudo apt-get install python-xml. Ich bin sicher, andere Linux-Distributionen haben es auch.

Wenn Sie einen Mac verwenden, ist xpath bereits installiert, aber nicht sofort verfügbar. Sie können PY_USE_XMLPLUSin Ihrer Umgebung festlegen oder Python ausführen, bevor Sie xml.xpath importieren:

if sys.platform.startswith('darwin'):
    os.environ['PY_USE_XMLPLUS'] = '1'

Im schlimmsten Fall müssen Sie es möglicherweise selbst bauen. Dieses Paket wird nicht mehr gepflegt, funktioniert aber immer noch gut und funktioniert mit modernen 2.x Pythons. Grundlegende Dokumente finden Sie hier .

David Joyner
quelle
0

Wenn Sie es für HTML benötigen :

import lxml.html as html
root  = html.fromstring(string)
root.xpath('//meta')
Thomas G.
quelle