【问题标题】:Scraping dynamic html fields with lxml使用 lxml 抓取动态 html 字段
【发布时间】:2016-05-14 09:27:02
【问题描述】:

我一直在尝试使用 lxml 抓取 HTML 页面的动态字段 代码很简单,如下:

from lxml import html
import requests
page = requests.get('http://www.airmilescalculator.com/distance/blr-to-cdg/')
tree = html.fromstring(page.content)
miles = tree.xpath('//input[@class="distanceinput2"]/text()')
print miles

我得出的结果只是一个空列表[] 结果应该是列表中的一个数字。 但是我可以抓取同一页面的静态字段。

提前感谢您的帮助。

【问题讨论】:

    标签: python html web-scraping lxml lxml.html


    【解决方案1】:

    您不能从input 字段中选择文本节点,因为没有文本节点。

    <input type="text" class="distanceinput2" .. />
    

    要从input 字段中获取value,请使用:

    miles = [node.value for node in tree.xpath('//input[@class="distanceinput2"]')]
    

    你应该得到它们。

    计算所需的值,因此我们需要访问页面并模拟Click 来获取它们。splinter 包是为此而制作的。

    from pyvirtualdisplay import Display
    display = Display(visible=0)
    display.start()
    
    from splinter import Browser
    
    url = 'http://www.airmilescalculator.com/distance/blr-to-cdg/'
    
    browser = Browser()
    browser.visit(url)
    browser.find_by_id('haemulti')[0].click()
    
    print browser.find_by_id('totaldistancemiles')[0].value
    print browser.find_by_id('totaldistancekm')[0].value
    print browser.find_by_id('nauticalmiles')[0].value
    
    browser.quit()
    
    
    display.stop()
    

    pyvirtualdisplay 用于隐藏浏览器。

    输出:

    $python test.py 
    4868
    7834
    4230
    

    【讨论】:

    • 如上述答案中所述,数据来自 Ajax 请求。有没有办法废弃 Ajax 加载的字段?
    • @TauseefHussain 检查我的编辑。我希望这会有用。
    【解决方案2】:

    您已经知道,距离是根据对 Google Maps API 的 XHR 调用结果动态计算的。仅使用 requests 模拟/重复这并不容易,因为您至少需要一个真实浏览器具有的 Javascript 引擎。

    您可以通过selenium 和无头PhantomJS browser 解决它:

    from selenium import webdriver
    
    driver = webdriver.PhantomJS()
    driver.get("http://www.airmilescalculator.com/distance/blr-to-cdg/")
    
    distance = driver.find_element_by_id("totaldistancemilestext").text
    print(distance)
    

    打印4868

    【讨论】:

    • 非常感谢。我不知道如何处理phantomJS 我在尝试运行代码selenium.common.exceptions.WebDriverException: Message: 'phantomjs' executable n eeds to be in PATH. 时出现错误@ 有什么我遗漏的吗?
    • @TauseefHussain PhantomJS 必须在 PATH 上的某个位置。或者您可以明确提供路径,示例:stackoverflow.com/a/34840307/771848.
    • 像魔术一样工作 :) 非常感谢!我将不得不进一步深入研究 PhantomJS 以了解更多信息。
    【解决方案3】:

    这里的问题是文本框中的值是由 javascript 添加的。当页面加载时文本字段中的值为0。所以,即使你抓取,你也不会得到这个值,因为被抓取的内容得到了这个

    <input class="distanceinput2" id="totaldistancemiles" name="totaldistancemiles" readonly="readonly" size="5" title="Distance in miles" type="text" value="0"/>
    <input class="distanceinput2" id="totaldistancekm" name="totaldistancekm" readonly="readonly" size="5" title="Distance in kilometers" type="text" value="0"/>
    <input class="distanceinput2" id="nauticalmiles" name="nauticalmiles" readonly="readonly" size="5" title="Distance in nautical miles" type="text" value="0"/>
    

    所以,如果你想得到网站上的值,通过抓取是不可能的。

    你可以试试 phantom JS,它就像一个无头浏览器。还没有尝试过,但看起来有机会。这是一个可以提供帮助的link

    希望有帮助!

    【讨论】:

    • 是的,我刚刚想通了。数据来自 ajax 请求。知道如何去做吗?我可以使用其他任何库吗?
    • 试试 phantom JS (realpython.com/blog/python/…)
    猜你喜欢
    • 2018-02-22
    • 1970-01-01
    • 2015-02-04
    • 2016-04-20
    • 1970-01-01
    • 2018-01-02
    • 1970-01-01
    • 2013-12-30
    • 2018-04-12
    相关资源
    最近更新 更多