使用 Pandas Datareader 从 Yahoo Finance 获取股票数据时出现“TypeError:字符串索引必须是整数”
- 2025-02-11 09:51:00
- admin 原创
- 70
问题描述:
import pandas_datareader
end = "2022-12-15"
start = "2022-12-15"
stock_list = ["TATAELXSI.NS"]
data = pandas_datareader.get_data_yahoo(symbols=stock_list, start=start, end=end)
print(data)
当我运行此代码时,出现错误"TypeError: string indices must be integers"
。
编辑:我已经更新了代码并将列表作为符号参数传递,但它仍然显示相同的错误
错误 :
Traceback (most recent call last):
File "C:UsersDeepak ShetterPycharmProjects@DAYSOFPYTHONmp3downloader.py", line 7, in <module>
data = pandas_datareader.get_data_yahoo(symbols=[TATAELXSI], start=start, end=end)
File "C:UsersDeepak ShetterPycharmProjects@DAYSOFPYTHONenvlibsite-packagespandas_datareaderdata.py", line 80, in get_data_yahoo
return YahooDailyReader(*args, **kwargs).read()
File "C:UsersDeepak ShetterPycharmProjects@DAYSOFPYTHONenvlibsite-packagespandas_datareaderase.py", line 258, in read
df = self._dl_mult_symbols(self.symbols)
File "C:UsersDeepak ShetterPycharmProjects@DAYSOFPYTHONenvlibsite-packagespandas_datareaderase.py", line 268, in _dl_mult_symbols
stocks[sym] = self._read_one_data(self.url, self._get_params(sym))
File "C:UsersDeepak ShetterPycharmProjects@DAYSOFPYTHONenvlibsite-packagespandas_datareaderyahoodaily.py", line 153, in _read_one_data
data = j["context"]["dispatcher"]["stores"]["HistoricalPriceStore"]
TypeError: string indices must be integers
解决方案 1:
我的解决方案很简单,我只需用 yf.download 替换 pandas_datareader.get_data_yahoo。无需担心结果,因为 yf.download 也会给你一个数据框。我简化了语法,如下所示:
import yfinance as yf
df = yf.download(your_ticks_or_a_tick_list, start=start_date, end=end_date)
但请记住清除所有单元的输出,然后重新启动,否则您将收到错误。
解决方案 2:
到目前为止,这里报告的解决方案对我都不起作用。根据此处的讨论,雅虎对其 API 进行了更改,从而破坏了与以前版本的 pandas datareader 的兼容性。
在同一个 Github 线程中,报告了一个修复,该修复在 Github 用户 raphi6 的拉取请求中实现。我确认拉取请求工作正常。可以使用以下 3 行安装拉取请求中的版本:
conda install pycryptodome pycryptodomex
conda uninstall pandas-datareader
pip install git+https://github.com/raphi6/pandas-datareader.git@ea66d6b981554f9d0262038aef2106dda7138316
这些pycrypto*
包是我必须安装才能使其工作的依赖项。请注意,我在这里使用的是提交哈希而不是分支名称,因为它是哈希字符,并且以这种方式使用 pip 时Yahoo!_Issue#952
会出现哈希字符问题。
也可以使用 pip 而不是 conda 来执行所有命令(参见下面的更新 1)。
更新 1
要在 Google Colab 上尝试此功能,请使用(如下所示):
! pip install pycryptodome pycryptodomex
! pip uninstall --yes pandas-datareader
! pip install git+https://github.com/raphi6/pandas-datareader.git@ea66d6b981554f9d0262038aef2106dda7138316
更新 2 (2022/12/27)
尽管上周我无法让它工作,但我再次尝试,并且可以确认pdr_override()
Nikhil Mulley 在下面提到的解决方法现在可以工作(至少对于 yfinance 0.2.3 和 pandas-datareader 0.10.0 来说)。
原始答案(有效,但代码行数更多)
在同一个 Github 线程中,Github 用户 raphi6 的拉取请求中报告了一个修复程序。我确认拉取请求工作正常。拉取请求的详细安装说明可在此处找到,为了完整起见,复制如下:
git clone https://github.com/raphi6/pandas-datareader.git
cd pandas-datareader
conda uninstall pandas-datareader
conda install pycryptodome pycryptodomex
git checkout 'Yahoo!_Issue#952'
python setup.py install --record installed_files.txt
install 命令中的参数--record
是获取已安装文件的列表,以便将来轻松卸载(按照此 SO 线程)。这些pycrypto*
文件是我必须安装才能使其工作的依赖项。
解决方案 3:
这不是一个答案,但我认为问题与 pdr 数据读取器从雅虎本身获取有关
>>> import pandas_datareader as dtr
>>> from datetime import datetime
>>> initial_portfolio=['AAPL', 'MA', 'F', 'MSFT', '^GSPC']
>>> startdate = datetime(2022,12,1)
>>> enddate=datetime(2022,12,10)
>>> stock_data=dtr.yahoo.daily.YahooDailyReader(initial_portfolio,start=startdate,end=enddate).read()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "lib/python3.9/site-packages/pandas_datareader/base.py", line 258, in read
df = self._dl_mult_symbols(self.symbols)
File "lib/python3.9/site-packages/pandas_datareader/base.py", line 268, in _dl_mult_symbols
stocks[sym] = self._read_one_data(self.url, self._get_params(sym))
File "lib/python3.9/site-packages/pandas_datareader/yahoo/daily.py", line 153, in _read_one_data
data = j["context"]["dispatcher"]["stores"]["HistoricalPriceStore"]
TypeError: string indices must be integers
短期解决办法可能是使用 yfinance 覆盖,看看这是否有帮助,直到雅虎财经恢复其数据功能?
Python 3.9.1 (default, Dec 28 2020, 11:22:14)
[Clang 11.0.0 (clang-1100.0.33.17)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from pandas_datareader import data as pdr
>>> import yfinance as yf
>>> yf.pdr_override()
>>> y_symbols = ['SCHAND.NS', 'TATAPOWER.NS', 'ITC.NS']
>>> from datetime import datetime
>>> startdate = datetime(2022,12,1)
>>> enddate = datetime(2022,12,15)
>>> data = pdr.get_data_yahoo(y_symbols, start=startdate, end=enddate)
[*********************100%***********************] 3 of 3 completed
>>> data
Adj Close Close ... Open Volume
ITC.NS SCHAND.NS TATAPOWER.NS ITC.NS SCHAND.NS TATAPOWER.NS ... ITC.NS SCHAND.NS TATAPOWER.NS ITC.NS SCHAND.NS TATAPOWER.NS
Date ...
2022-12-01 339.549988 195.949997 224.850006 339.549988 195.949997 224.850006 ... 341.700012 191.600006 225.250000 16630417 544485 7833074
2022-12-02 337.149994 196.600006 225.250000 337.149994 196.600006 225.250000 ... 339.350006 196.000000 225.449997 8388835 122126 7223274
2022-12-05 336.750000 191.050003 224.199997 336.750000 191.050003 224.199997 ... 337.649994 200.850006 225.250000 9716390 107294 10750610
2022-12-06 337.299988 196.399994 228.800003 337.299988 196.399994 228.800003 ... 334.100006 191.000000 224.199997 6327430 102911 20071039
2022-12-07 340.100006 187.350006 225.850006 340.100006 187.350006 225.850006 ... 338.500000 198.000000 228.800003 9813208 122772 7548312
2022-12-08 338.399994 181.850006 225.050003 338.399994 181.850006 225.050003 ... 340.200012 186.000000 226.000000 6200447 114147 7507975
2022-12-09 341.399994 176.899994 219.399994 341.399994 176.899994 219.399994 ... 339.750000 183.899994 225.899994 8132228 179660 13087278
2022-12-12 343.200012 177.350006 217.699997 343.200012 177.350006 217.699997 ... 341.000000 177.750000 219.750000 11214662 133507 8858525
2022-12-13 345.600006 178.449997 218.850006 345.600006 178.449997 218.850006 ... 344.500000 179.350006 218.800003 10693426 74873 7265105
2022-12-14 345.399994 179.149994 222.699997 345.399994 179.149994 222.699997 ... 346.000000 180.449997 219.800003 7379878 32085 9179593
[10 rows x 18 columns]
>>>
解决方案 4:
改用雅虎财经,它对我有用:
import datetime as dt
import yfinance as yf
company = 'TATAELXSI.NS'
# Define a start date and End Date
start = dt.datetime(2020,1,1)
end = dt.datetime(2022,1,1)
# Read Stock Price Data
data = yf.download(company, start , end)
data.tail(10)
解决方案 5:
2023 年 9 月 25 日对我有用的解决方案
我更换
import pandas_datareader as web
web.DataReader('AMZN', 'yahoo', start, end)
和
import yfinance
yfinance.download('AMZN', start, end)