代码之家  ›  专栏  ›  技术社区  ›  metersk

xpath使用lxml解析html时出现问题

  •  1
  • metersk  · 技术社区  · 11 年前

    我正在尝试解析来自谷歌互动网站的数据。它是在JS中呈现的,所以我使用Qt加载要解析的站点。我相信我已经正确加载并呈现了站点,但由于某种原因,当我执行xpath解析代码时,我得到了一个空列表。

    这是我的完整代码:

    import sys  
    from PyQt4.QtGui import *  
    from PyQt4.QtCore import *  
    from PyQt4.QtWebKit import *  
    from lxml import html 
    
    class Render(QWebPage):  
      def __init__(self, url):  
        self.app = QApplication(sys.argv)  
        QWebPage.__init__(self)  
        self.loadFinished.connect(self._loadFinished)  
        self.mainFrame().load(QUrl(url))  
        self.app.exec_()  
    
      def _loadFinished(self, result):  
        self.frame = self.mainFrame()  
        self.app.quit() 
    
    url = 'https://www.consumerbarometer.com/en/graph-builder/?question=M1&filter=country:singapore,canada,mexico,brazil,argentina,united_states,bulgaria,austria,belgium,croatia,czech_republic,denmark,estonia,finland,france,germany,greece,hungary,italy,ireland,latvia,lithuania,norway,netherlands,poland,portugal,russia,romania,serbia,slovakia,spain,slovenia,sweden,switzerland,ukraine,united_kingdom,australia,china,israel,hong_kong_sar,japan,korea,new_zealand,malaysia,taiwan,turkey,vietnam'  
    #This does the magic.Loads everything
    r = Render(url)  
    #result is a QString.
    result = r.frame.toHtml()
    
    #QString should be converted to string before processed by lxml
    formatted_result = str(result.toAscii())
    
    #Next build lxml tree from formatted_result
    tree = html.fromstring(formatted_result)
    
    archive_links = tree.xpath('//*[@id="main-page-wrapper"]/div/section/div/section[1]/div/div/graph/div/div[4]/div/div/graph-bar-chart/div[2]/svg/g[1]/g[2]/g[1]/text()')
    print archive_links
    

    这是我试图抓取的html: <text class="bar-text-label" y="22" dy="10">Argentina</text>

    我有什么想法吗 [] 回到我身边?

    1 回复  |  直到 11 年前
        1
  •  1
  •   alecxe    11 年前

    您可以创建一个更短、更可靠的xpath表达式,并且必须使用名称空间:

    tree.xpath('//text[@class="bar-text-label"]/text()', namespaces={'n': 'http://www.w3.org/2000/svg'})
    

    另一种解决方案是 selenium 浏览器自动化包:

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    
    driver = webdriver.Firefox()
    driver.get('https://www.consumerbarometer.com/en/graph-builder/?question=M1&filter=country:singapore,canada,mexico,brazil,argentina,united_states,bulgaria,austria,belgium,croatia,czech_republic,denmark,estonia,finland,france,germany,greece,hungary,italy,ireland,latvia,lithuania,norway,netherlands,poland,portugal,russia,romania,serbia,slovakia,spain,slovenia,sweden,switzerland,ukraine,united_kingdom,australia,china,israel,hong_kong_sar,japan,korea,new_zealand,malaysia,taiwan,turkey,vietnam')
    
    // wait for svg to appear
    WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.TAG_NAME, 'svg')))
    
    for text in driver.find_elements_by_class_name('bar-text-label'):
        print(text.text)
    
    driver.close()