雅虎财经更新了他们的网站。我有一个lxml/etree脚本,用于提取分析师建议。然而,现在,分析师的建议已经存在,但只是作为一个图形。您可以在此页上看到一个示例。右手栏上的“推荐趋势”图表显示了分析师报告的数量,这些报告显示了强劲的买入、买入、持有、表现不佳和卖出。
我猜雅虎会在接下来的一段时间里对页面做一些调整,但这让我怀疑这样的数据是否可以合理提取?
我以前经常得到这样的消息来源:
url = 'https://finance.yahoo.com/quote/'+code+'/analyst?p='+code
tree = etree.HTML(urllib.request.urlopen(url).read())然后在html树中找到数据。但很明显现在这是不可能的。
发布于 2016-09-01 16:07:33
正如注释说的那样,他们已经转移到ReactJS,所以lxml不再是重点,因为在HTML页面中没有数据。现在,您需要环顾四周,找到它们从中提取数据的端点。在推荐趋势的情况下它就在那里。
#!/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()输出结果如下。
{
'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
}]
}
}]
}
}如何查找数据
我所做的大概是:
/* -- Data -- */开头的部分)发布于 2016-08-27 06:28:21
该页面非常动态,涉及大量在浏览器中执行的javascript。为了遵循@Padraic关于切换到selenium的建议,下面是一个完整的示例工作代码,它在最后生成一个月到趋势的字典。每个杆的值是以杆高的比例计算的:
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)指纹:
{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值是在每个栏的顶部看到的标签。
希望这对你来说至少是个好的开始。如果您想让我详细说明代码的任何部分或要求提供任何其他信息,请通知我。
https://stackoverflow.com/questions/39007227
复制相似问题