Bagaimana cara menggunakan Xpath di Python?

224

Apa perpustakaan yang mendukung Xpath? Apakah ada implementasi penuh? Bagaimana perpustakaan digunakan? Di mana situs webnya?

smci
sumber
4
Saya curiga bahwa jawaban atas pertanyaan ini agak basi sekarang.
Warren P
4
Jawaban oleh @ gringo-suave terlihat seperti pembaruan yang bagus. stackoverflow.com/a/13504511/1450294
Michael Scheper
Scrapy menawarkan pemilih XPath .
cs95
Seperti @WarrenP mengatakan, sebagian besar jawaban di sini adalah Python-2.x tua yang sangat basi, benar-benar ketinggalan zaman. Mungkin pertanyaan ini harus ditandai python-2.x
smci

Jawaban:

129

libxml2 memiliki sejumlah keunggulan:

  1. Kesesuaian dengan spesifikasi
  2. Pengembangan aktif dan partisipasi masyarakat
  3. Mempercepat. Ini benar-benar pembungkus python di sekitar implementasi C.
  4. Ubiquity. Pustaka libxml2 meresap dan dengan demikian diuji dengan baik.

Kerugian meliputi:

  1. Kesesuaian dengan spesifikasi . Sangat ketat. Hal-hal seperti penanganan namespace default lebih mudah di perpustakaan lain.
  2. Penggunaan kode asli. Ini bisa sangat menyakitkan tergantung pada bagaimana Anda aplikasi Anda didistribusikan / digunakan. RPM tersedia yang meringankan beberapa rasa sakit ini.
  3. Penanganan sumber daya manual. Catatan dalam contoh di bawah ini adalah panggilan ke freeDoc () dan xpathFreeContext (). Ini tidak terlalu Pythonic.

Jika Anda melakukan pemilihan jalur sederhana, tetap dengan ElementTree (yang termasuk dalam Python 2.5). Jika Anda membutuhkan kepatuhan spesifikasi penuh atau kecepatan mentah dan dapat mengatasi distribusi kode asli, lanjutkan dengan libxml2.

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

Contoh Penggunaan 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
sumber
8
menggunakan python 2.7.10 di osx saya harus mengimpor ElementTree asfrom xml.etree.ElementTree import ElementTree
Ben Page
karena ini adalah pembungkus C Anda mungkin menemukan kesulitan untuk menyebarkannya ke AWS Lambda kecuali jika Anda mengompilasi pada instance EC2 atau gambar Docker dari AWS Linux
CpILL
85

The paket lxml mendukung XPath. Tampaknya bekerja dengan cukup baik, meskipun saya memiliki beberapa masalah dengan sumbu self ::. Ada juga Amara , tetapi saya belum menggunakannya secara pribadi.

James Sulak
sumber
1
Amara cukup bagus, dan seseorang tidak selalu membutuhkan xpath.
gatoatigrado
Silakan tambahkan beberapa detail dasar tentang cara menggunakan XPath dengan lxml.
jpmc26
56

Kedengarannya seperti iklan lxml di sini. ;) ElementTree termasuk dalam perpustakaan std. Di bawah 2.6 dan di bawah xpath-nya cukup lemah, tetapi di 2.7+ lebih baik :

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
sumber
39

Gunakan LXML. LXML menggunakan kekuatan penuh libxml2 dan libxslt, tetapi membungkusnya lebih banyak "Pythonic" binding daripada Python binding yang asli ke perpustakaan itu. Dengan demikian, ia akan mendapatkan implementasi penuh XPath 1.0. Native ElemenTree mendukung subset terbatas XPath, meskipun mungkin cukup baik untuk kebutuhan Anda.

pengguna210794
sumber
29

Pilihan lain adalah py-dom-xpath , ia bekerja dengan mulus dengan minidom dan Python murni jadi berfungsi pada appengine.

import xpath
xpath.find('//item', doc)
Sam
sumber
2
Lebih mudah daripada lxml dan libxml2 jika Anda sudah bekerja dengan minidom. Bekerja dengan indah dan lebih "Pythonic". The contextdalam findfungsi membiarkan Anda menggunakan hasil xpath lain sebagai konteks pencarian baru.
Ben
3
Saya juga telah menggunakan py-dom-xpath ketika saya menulis sebuah plugin, karena itu adalah python murni. Tetapi saya tidak berpikir itu dipertahankan lagi, dan waspadai bug ini ("Tidak dapat mengakses elemen yang namanya 'teks'"): code.google.com/p/py-dom-xpath/issues/detail?id = 8
Jon Coombs
py-dom-xpath tampaknya telah mothballed tahun lalu pada tahun 2010 , harap sunting ini menjadi jawaban Anda.
smci
14

Kamu bisa memakai:

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
sumber
ketika saya mencoba kode PyXML, saya dapatkan ImportError: No module named extdarifrom xml.dom.ext.reader import Sax2
Aminah Nuraini
9

Versi terbaru dari elementtree mendukung XPath dengan cukup baik. Tidak menjadi ahli XPath saya tidak bisa mengatakan dengan pasti apakah implementasinya penuh tetapi telah memenuhi sebagian besar kebutuhan saya ketika bekerja dengan Python. Saya juga menggunakan lxml dan PyXML dan saya merasa etree bagus karena ini adalah modul standar.

CATATAN: Saya sejak menemukan lxml dan bagi saya itu jelas merupakan XML lib terbaik di luar sana untuk Python. Itu tidak baik XPath juga (meskipun sekali lagi mungkin bukan implementasi penuh).

jkp
sumber
7
Dukungan XPath dari ElementTree saat ini sangat minim. Ada banyak celah yang menganga dalam fungsi, seperti kurangnya pemilih atribut, tidak ada sumbu non-default, tidak ada indeks anak, dll. Versi 1.3 (dalam alpha) menambahkan beberapa fitur ini, tetapi masih merupakan implementasi parsial tanpa malu-malu.
James Brady
8

Anda dapat menggunakan yang sederhana soupparserdarilxml

Contoh:

from lxml.html.soupparser import fromstring

tree = fromstring("<a>Find me!</a>")
print tree.xpath("//a/text()")
Aminah Nuraini
sumber
Apa perbedaan menggunakan supparser?
Padraic Cunningham
Itu hanya sebuah alternatif
Aminah Nuraini
7

Jika Anda ingin memiliki kekuatan XPATH dikombinasikan dengan kemampuan untuk juga menggunakan CSS di titik mana pun Anda dapat menggunakan 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
sumber
bagaimana seharusnya tampilan Xpath saya jika saya ingin mendapatkan "Tautan 1" dan "Tautan 2"?
weefwefwqg3
1
untuk mendapatkan teks, itu harus seperti//li/a/text()
eLRuLL
4

Pustaka lain adalah 4Suite: http://sourceforge.net/projects/foursuite/

Saya tidak tahu bagaimana memenuhi spesifikasi itu. Tetapi itu telah bekerja dengan sangat baik untuk saya gunakan. Itu terlihat ditinggalkan.

kode kode
sumber
3

PyXML berfungsi dengan baik.

Anda tidak mengatakan platform apa yang Anda gunakan, namun jika Anda menggunakan Ubuntu, Anda bisa mendapatkannya sudo apt-get install python-xml. Saya yakin distro Linux lain juga memilikinya.

Jika Anda menggunakan Mac, xpath sudah diinstal tetapi tidak segera dapat diakses. Anda dapat mengatur PY_USE_XMLPLUSdi lingkungan Anda atau melakukannya dengan cara Python sebelum Anda mengimpor xml.xpath:

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

Dalam kasus terburuk Anda mungkin harus membangunnya sendiri. Paket ini tidak lagi dipertahankan tetapi masih membangun dengan baik dan bekerja dengan Python 2.x modern. Dokumen dasar ada di sini .

David Joyner
sumber
0

Jika Anda membutuhkannya untuk html :

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