首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >来自yahoo的python lxml etree applet信息

来自yahoo的python lxml etree applet信息
EN

Stack Overflow用户
提问于 2016-08-17 22:29:29
回答 2查看 458关注 0票数 8

雅虎财经更新了他们的网站。我有一个lxml/etree脚本,用于提取分析师建议。然而,现在,分析师的建议已经存在,但只是作为一个图形。您可以在此页上看到一个示例。右手栏上的“推荐趋势”图表显示了分析师报告的数量,这些报告显示了强劲的买入、买入、持有、表现不佳和卖出。

我猜雅虎会在接下来的一段时间里对页面做一些调整,但这让我怀疑这样的数据是否可以合理提取?

  1. 我的意思是,有什么方法可以让图形处理吗?
  2. 即使成功了,是否也有合理的方法从图形中提取数据?

我以前经常得到这样的消息来源:

代码语言:javascript
复制
url = 'https://finance.yahoo.com/quote/'+code+'/analyst?p='+code
tree = etree.HTML(urllib.request.urlopen(url).read())

然后在html树中找到数据。但很明显现在这是不可能的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-09-01 16:07:33

正如注释说的那样,他们已经转移到ReactJS,所以lxml不再是重点,因为在HTML页面中没有数据。现在,您需要环顾四周,找到它们从中提取数据的端点。在推荐趋势的情况下它就在那里。

代码语言:javascript
复制
#!/usr/bin/env python3


import json
from pprint import pprint
from urllib.request import urlopen
from urllib.parse import urlencode


def parse():
    host   = 'https://query2.finance.yahoo.com'
    path   = '/v10/finance/quoteSummary/CSX'
    params = {
        'formatted' : 'true',
        'lang'      : 'en-US',
        'region'    : 'US',
        'modules'   : 'recommendationTrend'
    }

    response = urlopen('{}{}?{}'.format(host, path, urlencode(params)))
    data = json.loads(response.read().decode())

    pprint(data)


if __name__ == '__main__':
    parse()

输出结果如下。

代码语言:javascript
复制
{
  'quoteSummary': {
    'error': None,
    'result': [{
      'recommendationTrend': {
        'maxAge': 86400,
        'trend': [{
            'buy': 0,
            'hold': 0,
            'period': '0w',
            'sell': 0,
            'strongBuy': 0,
            'strongSell': 0
          },
          {
            'buy': 0,
            'hold': 0,
            'period': '-1w',
            'sell': 0,
            'strongBuy': 0,
            'strongSell': 0
          },
          {
            'buy': 5,
            'hold': 12,
            'period': '0m',
            'sell': 2,
            'strongBuy': 6,
            'strongSell': 1
          },
          {
            'buy': 5,
            'hold': 12,
            'period': '-1m',
            'sell': 2,
            'strongBuy': 7,
            'strongSell': 1
          },
          {
            'buy': 6,
            'hold': 11,
            'period': '-2m',
            'sell': 2,
            'strongBuy': 8,
            'strongSell': 1
          },
          {
            'buy': 6,
            'hold': 11,
            'period': '-3m',
            'sell': 2,
            'strongBuy': 8,
            'strongSell': 1
          }]
        }
    }]
  }
}

如何查找数据

我所做的大概是:

  1. 在目标小部件中找到一些唯一的标记(例如图表值或趋势字符串)
  2. 页面的开放源码(对HTML和JS使用一些格式化程序,例如)
  3. 在那里查找令牌(在第三页是以/* -- Data -- */开头的部分)
  4. 搜索".js“以获取脚本标记(或编程包含,例如require.js),并在那里查找令牌
  5. 在Firebug或工具中打开网络选项卡,检查XHR请求
  6. 然后使用邮递员 (或卷曲,如果您喜欢终端)来剥离额外的参数,看看端点是如何反应的
票数 2
EN

Stack Overflow用户

发布于 2016-08-27 06:28:21

该页面非常动态,涉及大量在浏览器中执行的javascript。为了遵循@Padraic关于切换到selenium的建议,下面是一个完整的示例工作代码,它在最后生成一个月到趋势的字典。每个杆的值是以杆高的比例计算的:

代码语言:javascript
复制
from pprint import pprint

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

driver = webdriver.Chrome()
driver.maximize_window()
driver.get("https://finance.yahoo.com/quote/CSX/analysts?p=CSX")

# wait for the chart to be visible
wait = WebDriverWait(driver, 10)
trends = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "section[data-reactid$=trends]")))
chart = trends.find_element_by_css_selector("svg.ratings-chart")

# get labels
month_names = [month.text for month in chart.find_elements_by_css_selector("g.x-axis g.tick")]
trend_names = [trend.text for trend in trends.find_elements_by_css_selector("table tr > td:nth-of-type(2)")]

# construct month-to-trend dictionary
data = {}
months = chart.find_elements_by_css_selector("g[transform]:not([class])")
for month_name, month_data in zip(month_names, months):
    total = month_data.find_element_by_css_selector("text.total").text
    data[month_name] = {'total': total}

    bars = month_data.find_elements_by_css_selector("g.bar rect")

    # let's calculate the values of bars as proportions of a bar height
    heights = {trend_name: int(bar.get_attribute("height")) for trend_name, bar in zip(trend_names[::-1], bars)}
    total_height = sum(heights.values())
    for trend_name, bar in zip(trend_names, bars):
        data[month_name][trend_name] = heights[trend_name] * 100 / total_height

driver.close()

pprint(data)

指纹:

代码语言:javascript
复制
{u'Aug': {u'Buy': 19,
          u'Hold': 45,
          u'Sell': 3,
          u'Strong Buy': 22,
          u'Underperform': 8,
          'total': u'26'},
 u'Jul': {u'Buy': 18,
          u'Hold': 44,
          u'Sell': 3,
          u'Strong Buy': 25,
          u'Underperform': 7,
          'total': u'27'},
 u'Jun': {u'Buy': 21,
          u'Hold': 38,
          u'Sell': 3,
          u'Strong Buy': 28,
          u'Underperform': 7,
          'total': u'28'},
 u'May': {u'Buy': 21,
          u'Hold': 38,
          u'Sell': 3,
          u'Strong Buy': 28,
          u'Underperform': 7,
          'total': u'28'}}

total值是在每个栏的顶部看到的标签。

希望这对你来说至少是个好的开始。如果您想让我详细说明代码的任何部分或要求提供任何其他信息,请通知我。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39007227

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档