2014-09-22 5 views
8

का सीएसएस पथ मैं HTML से कुछ डेटा निकालना चाहता हूं और फिर स्रोत HTML को संशोधित किए बिना क्लाइंट पक्ष पर निकाले गए तत्वों को हाइलाइट करने में सक्षम होना चाहिए। और XPath या CSS पथ इसके लिए बहुत अच्छा लग रहा है। क्या सुंदरसूप से सीधे XPATH या CSS पथ निकालना संभव है?
अभी मैं लक्ष्य तत्व के अंकन का उपयोग करता हूं और फिर xpath निकालने के लिए lxml lib का उपयोग करता हूं, जो प्रदर्शन के लिए बहुत खराब है। मुझे BSXPath.py के बारे में पता है - यह बीएस 4 के साथ काम नहीं करता है। मूल lxml lib का उपयोग करने के लिए सबकुछ पुनर्लेखन के साथ समाधान जटिलता के कारण स्वीकार्य नहीं है।सुंदर सूप XPATH निकालें या नोड

import bs4 
import cStringIO 
import random 
from lxml import etree 


def get_xpath(soup, element): 
    _id = random.getrandbits(32) 
    for e in soup(): 
    if e == element: 
     e['data-xpath'] = _id 
     break 
    else: 
    raise LookupError('Cannot find {} in {}'.format(element, soup)) 
    content = unicode(soup) 
    doc = etree.parse(cStringIO.StringIO(content), etree.HTMLParser()) 
    element = doc.xpath('//*[@data-xpath="{}"]'.format(_id)) 
    assert len(element) == 1 
    element = element[0] 
    xpath = doc.getpath(element) 
    return xpath 

soup = bs4.BeautifulSoup('<div id=i>hello, <b id=i test=t>world!</b></div>') 
xpath = get_xpath(soup, soup.div.b) 
assert '//html/bodydiv/b' == xpath 
+1

संक्षिप्त उत्तर: नहीं, इसके लिए कोई मौजूदा विधि नहीं है। आपको इसे स्वयं बनाना होगा। –

उत्तर

4

यह सरल सीएसएस/XPath निकालने के लिए वास्तव में बहुत आसान है:

वहाँ भी इनबिल्ट "अगला" बुला समारोह से यह नेविगेट करने के कई तरीके हैं। यह वही lxml lib आपको देता है।

def get_element(node): 
    # for XPATH we have to count only for nodes with same type! 
    length = len(list(node.previous_siblings)) + 1 
    if (length) > 1: 
    return '%s:nth-child(%s)' % (node.name, length) 
    else: 
    return node.name 

def get_css_path(node): 
    path = [get_element(node)] 
    for parent in node.parents: 
    if parent.name == 'body': 
     break 
    path.insert(0, get_element(parent)) 
    return ' > '.join(path) 

soup = bs4.BeautifulSoup('<div></div><div><strong><i>bla</i></strong></div>') 
assert get_css_path(soup.i) == 'div:nth-child(2) > strong > i' 
1

मुझे डर है कि लाइब्रेरी अभी तक सक्षम नहीं है। तुम्हें पता है, इसकी एक सा जटिल सीएसएस मार्ग से उन्हें प्राप्त कर सकते हैं ... sorta ... लेकिन, जहां प्रत्येक तत्व और वर्ग, एक उदाहरण के नामकरण कर रहे हैं:

soup.find("htmlelement", class_="theclass") 

तुम भी पहचान-पत्र का उपयोग कर सकते वर्गों के बजाय या यदि आप जो भी पकड़ते हैं उसमें आप अधिक विशिष्ट होना पसंद करते हैं।

आप पथ नीचे जा रहा रखने के लिए यह संशोधन कर सकते हैं:

soup.find("htmlelement", class_="theclass").find("htmlelement2", class_="theclass2") 

इतने पर और बहुत आगे है।

find_next("td", class_="main").find_next("td", class_="main").next.next