使用 yahoo Finance 的 bs4 读取 url

Posted

技术标签:

【中文标题】使用 yahoo Finance 的 bs4 读取 url【英文标题】:Reading url using bs4 from yahoo finance 【发布时间】:2018-04-10 04:27:36 【问题描述】:

我正在尝试使用以下代码从 yahoo Finance 读取历史 CSV 数据:

import datetime
import time
from bs4 import BeautifulSoup


per1 = str(int(time.mktime((datetime.datetime.today() - td(days=365)).timetuple())))
per2 = str(int(time.mktime((datetime.datetime.today()).timetuple())))
url = 'https://query1.finance.yahoo.com/v7/finance/download/MSFT?period1=' + per1 + '&period2=' + per2 + '&interval=1d&events=history&crumb=OQg/YFV3fvh'

url 变量可以在您访问 yahoo Finance 时看到,输入代码并将鼠标悬停在“下载数据”按钮上。

我收到身份验证错误,我认为这是由于缺少 cookie,所以我尝试了以下操作:

import requests
ses = requests.Session()
url1 = 'https://finance.yahoo.com/quote/MSFT/history?p=MSFT'
ses.get(url1)
soup = BeautifulSoup(ses.get(url).content)
print soup.prettify()

这次我收到了不正确的 cookie 错误。

有人可以建议如何解决这个问题吗?

【问题讨论】:

你能发布错误的堆栈跟踪吗? 请注意有一个pandas library for this purpose。效果非常好。 我遇到了提取雅虎财务数据时显示错误的线程,但似乎已经修复。谢谢。我必须说,公认的答案是一个很好的学习工具。 【参考方案1】:

查询字符串的crumb 参数不断变化,可能随着每个浏览器会话而变化。所以,当你从浏览器复制它的值,关闭它,然后在浏览器的另一个实例中使用它,它就会过期。

因此,当您在 requests 会话中使用它时,它无法识别 cookie 值并产生错误也就不足为奇了。

第 1 步

在任何浏览器中研究网络标签都会有所帮助。在这种特殊情况下,这个crumb 部分可能是在您单击主页中的代码时生成的。因此,您必须先获取该 URL。

tickers = ('000001.SS', 'NKE', 'MA', 'SBUX')
url = 'https://finance.yahoo.com/quote/0?p=0'.format(tickers[0])
r = s.get(url, headers = req_headers)

这个 URL 只需要获取一次。因此,您为此使用哪个代码无关紧要。

第 2 步

服务器返回的响应包含您下载 CSV 文件时传递给查询字符串中crumb 参数的值。

但是,它包含在上一个请求返回的页面的script 标记中。这意味着您不能单独使用 BeautifulSoup 来提取 crumb 值。

我最初尝试re 将其从script 标记的文本中提取出来。但由于某种原因,我无法做到。所以我转到json 来解析它。

soup = BeautifulSoup(r.content, 'lxml')
script_tag = soup.find(text=re.compile('crumb'))

response_dict = json.loads(script_tag[script_tag.find('"context":'):script_tag.find(';') + 4])
crumb = response_dict['context']['dispatcher']['stores']['CrumbStore']['crumb']

请注意,BeautifulSoup 需要提取 script 元素的内容,以便稍后传递给 json 以将其解析为 Python dict 对象。

我必须使用pprint 将生成的dict 打印到文件中,以查看crumb 值的确切存储位置。

第 3 步

获取 CSV 文件的最终 URL 如下所示:

for ticker in tickers:
    csv_url = 'https://query1.finance.yahoo.com/v7/finance/download/0?period1=1506656676&period2=1509248676&interval=1d&events=history&crumb=1'.format(ticker, crumb)

    r = s.get(csv_url, headers = req_headers)

结果

这是下载的文件的前几行:

Date,Open,High,Low,Close,Adj Close,Volume
2017-09-29,3340.311035,3357.014893,3340.311035,3348.943115,3348.943115,144900
2017-10-09,3403.246094,3410.169922,3366.965088,3374.377930,3374.377930,191700
2017-10-10,3373.344971,3384.025879,3358.794922,3382.988037,3382.988037,179400

注意:

我在两个请求中都使用了适当的标头。因此,如果您跳过该部分并且没有得到所需的结果,您可能也必须包含它们。

req_headers = 
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
    'accept-encoding': 'gzip, deflate, br',
    'accept-language': 'en-US,en;q=0.8',
    'upgrade-insecure-requests': '1',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'

【讨论】:

“在任何浏览器中研究网络选项卡都会有所帮助”:在网络选项卡下,您要查找哪个特定变量?

以上是关于使用 yahoo Finance 的 bs4 读取 url的主要内容,如果未能解决你的问题,请参考以下文章

使用 BeautifulSoup 搜索 Yahoo Finance

使用Yahoo Finance进行网络抓取

如何从Yahoo Finance中解析类似JSON的数据?

如何使用 Yahoo,Finance stock API 获取股票数据

使用 Python 抓取 Yahoo Finance 的资产负债表

Yahoo Finance API / URL 不起作用:Pandas DataReader 的 Python 修复