【问题标题】:Why does lxml not return the text associated with this html element?为什么 lxml 不返回与此 html 元素关联的文本?
【发布时间】:2015-10-25 00:38:59
【问题描述】:

我是使用 python 解析 html 的新手,我遇到了麻烦。我正在尝试编写一个简短的脚本来每天从网站上获取一个数字。然而,代码并没有像我想要的那样返回一个数字,而是返回None

以下网页显示每天通过特定区域的自行车数量:http://eco-public.com/public2/?id=100023038。我正在尝试编写一个简短的 python 脚本来记录“昨天”骑行的自行车数量(每天的数量不同,通常在 500 到 1,500 之间)。当我检查网页的那个元素时,我看到它的 xpath 是://*[@id="region-lastDay"]/div/p[2]/text()。但是,当我尝试使用以下代码返回数字时,它会返回值 None

import lxml.html as lh
import urllib2
doc = lh.parse(urlopen('http://eco-public.com/public2/?id=100023038'))
daily = doc.xpath('//*[@id="region-lastDay"]')
for i in daily:
    print i.text

我做错了什么?

【问题讨论】:

    标签: python html xpath web-scraping lxml


    【解决方案1】:

    div 在 html 代码中为空。

    <div id="region-lastDay" class="col-xs-12 col-sm-6 col-md-4" ></div>
    

    它充满了javascript。 lxml 无法处理 Javascript 部分。您需要可以处理 javascript 部分的包(例如selenium)。

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.ui import WebDriverWait
    
    
    driver = webdriver.Firefox()  # OR  Chrome() / PhantomJS() / ...
    driver.get('http://eco-public.com/public2/?id=100023038')
    xpath = '//*[@id="region-lastDay"]/div'
    WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, xpath)))
    daily = driver.find_elements_by_xpath(xpath)
    for i in daily:
        print i.text
    # driver.quit()
    

    【讨论】:

      【解决方案2】:

      如果您查看浏览器对该 URL 发出的原始请求(例如,使用 Chrome 或 Firefox 中的开发者工具,或者只是打印出 urlopen(...).read() 的值),您会看到 region-lastDay 元素如下所示:

          <!-- Key Numbers -->
          <div class="row" id="keyrow">
              <div id="region-total"  class="col-xs-12 col-sm-6 col-md-4"></div>
              <div id="region-lastDay" class="col-xs-12 col-sm-6 col-md-4" ></div>
          </div>
      

      它确实是空的,因为在初始页面加载后,该元素正在使用返回 JSON 的 AJAX 调用填充(通过 Chrome 的开发人员工具 -> 网络选项卡观察):

      因此,您需要使用json 来解析来自用于 AJAX 调用的 URL 的响应,而不是使用 lxml

      从 JSON 中获取最后一个元素,如下所示:

      >>> import urllib.request
      >>> import json
      >>> response = urllib.request.urlopen("http://www.eco-public.com/api/h7q239dd/data/periode/100023038?begin=20150623&end=20150801&step=4")
      >>> data = json.loads(response.read().decode('utf8'))
      >>> data[-1]
      {'comptage': 695, 'timestamp': 1438380000000, 'date': '2015-08-01 00:00:00.0'}
      

      您可能还需要调整 URL 中的 startend 参数以获取其他日期的数据。

      【讨论】:

        【解决方案3】:

        我知道这是一个老问题;但是,我在加载 Javascript 生成的页面时遇到问题,因为 lxml 在 JS 加载之前抓取数据并且我找到了解决方案。

        此解决方案将要求您使用这些导入:

        import sys  
        from PyQt4.QtGui import *  
        from PyQt4.QtCore import *  
        from PyQt4.QtWebKit import *  
        from lxml import html 
        

        这段代码等待页面渲染

        #Take this class for granted.Just use result of rendering.
        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 = 'http://pycoders.com/archive/'  
        r = Render(url)  
        result = r.frame.toHtml()
        #This step is important.Converting QString to Ascii for lxml to process
        archive_links = html.fromstring(str(result.toAscii()))
        print archive_links
        

        使用 Render 类,您可以加载页面并将其转换为 Ascii for lxml。 我有“print archive_links”所以你可以看到它返回的结构,你不需要这个。

        现在要抓取您收集的信息,您可以使用 lxml。

        #Now using correct Xpath we are fetching URL of archives
        archive_links = tree.xpath('//divass="campaign"]/a/@href')
        print archive_links
        

        所有这些代码从上到下放在一起将为您提供一个包含 JS 生成元素的加载页面,并允许您使用 lxml 获取它们。

        内容来源:https://impythonist.wordpress.com/2015/01/06/ultimate-guide-for-scraping-javascript-rendered-web-pages/

        【讨论】:

          猜你喜欢
          • 2020-08-30
          • 2012-03-23
          • 1970-01-01
          • 1970-01-01
          • 2020-04-13
          • 2019-12-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多