Jak korzystać z Xpath w Pythonie?


224

Jakie biblioteki obsługują Xpath? Czy jest pełna implementacja? Jak używana jest biblioteka? Gdzie jest jego strona internetowa?


4
Mam podstępne podejrzenie, że odpowiedzi na to pytanie są teraz trochę nieaktualne.
Warren P

4
Odpowiedź @ gringo-suave wygląda na dobrą aktualizację. stackoverflow.com/a/13504511/1450294
Michael Scheper

Złomowanie oferuje selektory XPath .
cs95,

Jak mówi @WarrenP, większość odpowiedzi tutaj to bardzo nieaktualny stary Python-2.x, naprawdę nieaktualny. Może to pytanie powinno być oznaczone python-2.x
smci

Odpowiedzi:


129

libxml2 ma wiele zalet:

  1. Zgodność ze specyfikacją
  2. Aktywny rozwój i udział społeczności
  3. Prędkość. To jest naprawdę opakowanie Pythona wokół implementacji C.
  4. Wszechobecność. Biblioteka libxml2 jest wszechobecna, a zatem dobrze przetestowana.

Minusy obejmują:

  1. Zgodność z specyfikacją . To jest surowe. Rzeczy takie jak domyślna obsługa przestrzeni nazw są łatwiejsze w innych bibliotekach.
  2. Korzystanie z kodu natywnego. Może to być uciążliwe w zależności od sposobu dystrybucji / wdrażania aplikacji. Dostępne są RPM, które łagodzą ten ból.
  3. Ręczna obsługa zasobów. Uwaga w poniższym przykładzie wywołań funkcji freeDoc () i xpathFreeContext (). To nie jest bardzo Pythonic.

Jeśli dokonujesz prostego wyboru ścieżki, trzymaj się elementu ElementTree (który jest zawarty w Pythonie 2.5). Jeśli potrzebujesz pełnej specyfikacji lub surowej prędkości i poradzisz sobie z dystrybucją kodu natywnego, skorzystaj z libxml2.

Przykład użycia XPath libxml2


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()

Przykład użycia XPath ElementTree


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


8
używając Pythona 2.7.10 na OSX musiałem zaimportować ElementTree jakofrom xml.etree.ElementTree import ElementTree
Ben Page

ponieważ jest to opakowanie C, możesz mieć trudności z wdrożeniem go w AWS Lambda, chyba że skompilujesz na instancji EC2 lub obrazie Docker AWS Linux
CpILL

85

Do pakietów lxml podpory XPath. Wygląda na to, że działa całkiem dobrze, chociaż miałem pewne problemy z osią self ::. Jest też Amara , ale nie korzystałem z niej osobiście.


1
amara jest całkiem fajna i nie zawsze trzeba xpath.
gatoatigrado

Dodaj kilka podstawowych informacji o tym, jak używać XPath z lxml.
jpmc26

56

Brzmi jak reklama lxml tutaj. ;) ElementTree jest zawarty w bibliotece std. Poniżej 2.6 i poniżej jego xpath jest dość słaby, ale w 2.7+ znacznie poprawiony :

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

39

Użyj LXML. LXML wykorzystuje pełną moc libxml2 i libxslt, ale pakuje je w więcej „Pythonic” powiązań niż w Python, które są rodzime dla tych bibliotek. W związku z tym uzyskuje pełną implementację XPath 1.0. Natywny ElemenTree obsługuje ograniczony podzbiór XPath, chociaż może być wystarczający dla twoich potrzeb.


29

Inną opcją jest py-dom-xpath , działa płynnie z minidom i jest czystym Pythonem, więc działa na appengine.

import xpath
xpath.find('//item', doc)

2
Łatwiejsze niż lxml i libxml2, jeśli już pracujesz z Minidom. Działa pięknie i jest bardziej „Pythonic”. Funkcja contextin findpozwala użyć innego wyniku xpath jako nowego kontekstu wyszukiwania.
Ben

3
Ja również używam py-dom-xpath podczas pisania wtyczki, ponieważ jest to czysty python. Ale nie sądzę, aby był już utrzymywany i należy pamiętać o tym błędzie („Nie można uzyskać dostępu do elementu o nazwie„ tekst ””): code.google.com/p/py-dom-xpath/issues/detail?id = 8
Jon Coombs


14

Możesz użyć:

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

kiedy próbuję kodu PyXML, dostałem ImportError: No module named extodfrom xml.dom.ext.reader import Sax2
Aminah Nuraini

9

Najnowsza wersja elementtree całkiem dobrze obsługuje XPath. Nie będąc ekspertem XPath, nie jestem pewien, czy implementacja jest pełna, ale spełniła większość moich potrzeb podczas pracy w Pythonie. Korzystam również z lxml i PyXML i uważam, że etree jest fajny, ponieważ jest to standardowy moduł.

UWAGA: Od tamtej pory znalazłem lxml i dla mnie jest to zdecydowanie najlepsza dostępna biblioteka XML dla Pythona. Ładnie radzi sobie także z XPath (choć może nie jest to pełna implementacja).


7
Obsługa XPath przez ElementTree jest obecnie w najlepszym razie minimalna. Istnieją ogromne luki w funkcjonalności, takie jak brak selektorów atrybutów, brak domyślnych osi, brak indeksowania podrzędnego itp. Wersja 1.3 (w wersji alfa) dodaje niektóre z tych funkcji, ale wciąż jest bezwstydnie częściową implementacją.
James Brady


7

Jeśli chcesz mieć moc XPATH w połączeniu z możliwością korzystania z CSS w dowolnym momencie, możesz użyć 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!'

jak powinien wyglądać mój Xpath, jeśli chcę uzyskać „Link 1” i „Link 2”?
weefwefwqg3

1
aby uzyskać tekst, powinno to być coś w rodzaju//li/a/text()
eLRuLL


3

PyXML działa dobrze.

Nie powiedziałeś, jakiej platformy używasz, jednak jeśli korzystasz z Ubuntu, możesz to zrobić sudo apt-get install python-xml. Jestem pewien, że inne dystrybucje Linuksa też to mają.

Jeśli korzystasz z komputera Mac, xpath jest już zainstalowany, ale nie jest od razu dostępny. Możesz ustawić PY_USE_XMLPLUSw swoim środowisku lub zrobić to w Pythonie przed zaimportowaniem xml.xpath:

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

W najgorszym przypadku może być konieczne samodzielne zbudowanie go. Ten pakiet nie jest już obsługiwany, ale nadal działa poprawnie i współpracuje z nowoczesnymi Pythonami 2.x. Podstawowe dokumenty są tutaj .


0

Jeśli będziesz go potrzebować do HTML :

import lxml.html as html
root  = html.fromstring(string)
root.xpath('//meta')
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.