วิธีใช้ Xpath ใน Python


224

ไลบรารีใดบ้างที่รองรับ Xpath มีการนำไปใช้อย่างเต็มรูปแบบหรือไม่? มีการใช้ห้องสมุดอย่างไร เว็บไซต์อยู่ที่ไหน


4
ฉันมีความสงสัยส่อเสียดนี้ว่าคำตอบของคำถามนี้ค่อนข้างเก่าแล้ว
Warren P

4
คำตอบโดย @ gringo-suave ดูเหมือนเป็นการปรับปรุงที่ดี stackoverflow.com/a/13504511/1450294
Michael Scheper

Scrapy ข้อเสนอXPath เตอร์
cs95

ดังที่ @WarrenP พูดว่าคำตอบส่วนใหญ่ที่นี่เก่าเกินไปอย่างยิ่งกับ Python-2.x ที่ล้าสมัยจริง ๆ บางทีคำถามนี้ควรติดแท็กpython-2.x
smci

คำตอบ:


129

libxml2มีข้อดีหลายประการ:

  1. ปฏิบัติตามสเป็ค
  2. การพัฒนาอย่างแข็งขันและการมีส่วนร่วมของชุมชน
  3. ความเร็ว. นี่เป็นเสื้อคลุมงูหลามรอบ ๆ การติดตั้ง C
  4. การแพร่หลาย ไลบรารี libxml2 นั้นแพร่หลายและผ่านการทดสอบอย่างดี

ข้อเสียรวมถึง:

  1. ปฏิบัติตามสเป็คสเป็คมันเข้มงวด สิ่งต่างๆเช่นการจัดการเนมสเปซเริ่มต้นนั้นง่ายกว่าในไลบรารีอื่น
  2. การใช้รหัสพื้นเมือง ซึ่งอาจเป็นอาการปวดทั้งนี้ขึ้นอยู่กับวิธีการแจกจ่าย / ปรับใช้แอปพลิเคชันของคุณ RPM มีให้ใช้เพื่อลดความเจ็บปวดนี้
  3. การจัดการทรัพยากรด้วยตนเอง หมายเหตุในตัวอย่างด้านล่างการเรียกไปยัง freeDoc () และ xpathFreeContext () นี่ไม่ใช่ Pythonic มาก

หากคุณกำลังเลือกเส้นทางอย่างง่าย ๆ ให้ใช้ElementTree (ซึ่งรวมอยู่ใน Python 2.5) หากคุณต้องการการปฏิบัติตามข้อกำหนดอย่างเต็มรูปแบบหรือความเร็วดิบและสามารถรับมือกับการแจกจ่ายรหัสเนทีฟไปกับ libxml2

ตัวอย่างการใช้งาน 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()

ตัวอย่างการใช้ ElementTree XPath


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


8
ใช้ python 2.7.10 บน osx ฉันต้องนำเข้า ElementTree asfrom xml.etree.ElementTree import ElementTree
Ben หน้า

เพราะมันเป็นเครื่องห่อหุ้ม C คุณอาจพบปัญหาในการปรับใช้กับ AWS Lambda เว้นแต่ว่าคุณจะรวบรวมอินสแตนซ์ EC2 หรืออิมเมจ Docker ของ AWS Linux
CpILL

85

แพคเกจ lxmlสนับสนุน XPath ดูเหมือนว่าจะทำงานได้ดีแม้ว่าฉันจะมีปัญหากับแกนตัวเอง :: นอกจากนี้ยังมีAmaraแต่ฉันไม่ได้ใช้เป็นการส่วนตัว


1
สวยดีของอมราและไม่จำเป็นต้องมีพา ธ
gatoatigrado

โปรดเพิ่มรายละเอียดพื้นฐานบางอย่างเกี่ยวกับวิธีใช้ XPath ด้วย lxml
jpmc26

56

ฟังดูเหมือนโฆษณา lxml ที่นี่ ;) ElementTree รวมอยู่ในไลบรารี std ต่ำกว่า 2.6 และต่ำกว่า xpath ของมันค่อนข้างอ่อนแอ แต่ใน2.7+ ดีขึ้นมาก :

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

ใช้ LXML LXML ใช้พลังเต็มรูปแบบของ libxml2 และ libxslt แต่ล้อมรอบพวกมันไว้ในการผูก "Pythonic" มากกว่าการผูก Python ที่อยู่ในไลบรารีเหล่านั้น เช่นนั้นจะได้รับการใช้งาน XPath 1.0 แบบเต็ม Native ElemenTree รองรับชุดย่อยของ XPath ที่ จำกัด แม้ว่ามันจะดีพอสำหรับความต้องการของคุณ


29

อีกทางเลือกหนึ่งคือpy-dom-xpathมันทำงานได้อย่างราบรื่นกับ minidom และเป็น Python ที่บริสุทธิ์ดังนั้นจึงใช้ได้กับ appengine

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

2
ง่ายกว่า lxml และ libxml2 หากคุณทำงานกับ minidom อยู่แล้ว ทำงานได้อย่างสวยงามและเป็น "Pythonic" มากกว่า contextในfindฟังก์ชั่นให้คุณใช้ผล XPath อื่นเป็นบริบทค้นหาใหม่
Ben

3
ฉันก็ใช้ py-dom-xpath เหมือนกันกับที่ฉันเขียนปลั๊กอิน แต่ฉันไม่คิดว่ามันจะได้รับการดูแลอีกต่อไปและระวังข้อผิดพลาดนี้ ("ไม่สามารถเข้าถึงองค์ประกอบที่ชื่อ" text ""): code.google.com/p/py-dom-xpath/issues/detail?id = 8
Jon Coombs

ดูเหมือนว่า py-dom-xpath จะถูก mothballed เมื่อหลายปีก่อนในปี 2010โปรดแก้ไขอย่างน้อยในคำตอบของคุณ
smci

14

คุณสามารถใช้ได้:

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

เมื่อฉันลองใช้รหัส PyXML ฉันได้รับImportError: No module named extจากfrom xml.dom.ext.reader import Sax2
Aminah Nuraini

9

elementtreeเวอร์ชันล่าสุดรองรับ XPath ได้ค่อนข้างดี ไม่ได้เป็นผู้เชี่ยวชาญ XPath ฉันไม่สามารถพูดได้อย่างแน่นอนว่าการใช้งานเต็ม แต่มันก็ตอบสนองความต้องการส่วนใหญ่ของฉันเมื่อทำงานใน Python ฉันยังใช้ lxml และ PyXML และฉันพบว่า etree เป็นสิ่งที่ดีเพราะเป็นโมดูลมาตรฐาน

หมายเหตุ: ตั้งแต่ฉันพบ lxml และสำหรับฉันมันคือ lib XML ที่ดีที่สุดสำหรับ Python มันทำ XPath ได้เป็นอย่างดีเช่นกัน


7
การสนับสนุน XPath ของ ElementTree นั้นน้อยที่สุด มีช่องว่างขนาดใหญ่ในการใช้งานเช่นการขาดตัวเลือกคุณลักษณะไม่มีแกนที่ไม่ใช่ค่าเริ่มต้นไม่มีการจัดทำดัชนีลูกเป็นต้นเวอร์ชัน 1.3 (เป็นอัลฟ่า) เพิ่มคุณสมบัติเหล่านี้บางส่วน
James Brady

8

คุณสามารถใช้ง่ายsoupparserจากlxml

ตัวอย่าง:

from lxml.html.soupparser import fromstring

tree = fromstring("<a>Find me!</a>")
print tree.xpath("//a/text()")

การใช้ soupparser สร้างความแตกต่างอะไร?
Padraic Cunningham

เป็นเพียงทางเลือก
Aminah Nuraini

7

หากคุณต้องการให้พลังของ XPATH รวมกับความสามารถในการใช้ CSS ได้ทุกเมื่อคุณสามารถใช้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!'

Xpath ของฉันควรมีลักษณะอย่างไรถ้าฉันต้องการได้รับ "ลิงก์ 1" และ "ลิงก์ 2"
weefwefwqg3

1
สำหรับการรับข้อความควรมีลักษณะดังนี้//li/a/text()
eLRuLL

4

ห้องสมุดอื่นคือ 4Suite: http://sourceforge.net/projects/foursuite/

ฉันไม่รู้ว่ามันเป็นไปตามสเป็ค แต่มันใช้งานได้ดีมากสำหรับการใช้งานของฉัน ดูเหมือนว่าจะถูกทิ้งร้าง


3

PyXMLทำงานได้ดี

คุณไม่ได้พูดในสิ่งที่แพลตฟอร์มที่คุณใช้ sudo apt-get install python-xmlแต่ถ้าคุณอยู่ในอูบุนตูคุณจะได้รับมันด้วย ฉันแน่ใจว่า distros Linux อื่นมีเช่นกัน

หากคุณใช้ Mac xpath ได้รับการติดตั้งแล้ว แต่ไม่สามารถเข้าถึงได้ทันที คุณสามารถตั้งค่าPY_USE_XMLPLUSในสภาพแวดล้อมของคุณหรือทำด้วยวิธี Python ก่อนที่คุณจะนำเข้า xml.xpath:

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

ในกรณีที่เลวร้ายที่สุดคุณอาจต้องสร้างมันขึ้นมาเอง แพ็คเกจนี้ไม่ได้รับการบำรุงรักษาอีกต่อไป แต่ก็ยังสร้างได้ดีและใช้งานได้กับ 2.x Pythons ที่ทันสมัย เอกสารพื้นฐานที่นี่


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.