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.