yahoo_fin get_quote_table频繁触发JSONDecodeError的原因排查
Hey there, let’s break down why you’re hitting this persistent JSONDecodeError with yahoo_fin’s get_quote_table and how to fix it:
What’s Causing the Issue?
Your error stack trace points to a failure when parsing Yahoo Finance’s response as JSON—this usually boils down to one of these top reasons:
- Yahoo Finance API changes: yahoo_fin relies on Yahoo’s unofficial, unpublicized API endpoints, which Yahoo frequently modifies to block scrapers. The library’s parsing logic likely can’t handle the latest response format anymore (hence the "Expecting value" JSON error, meaning the response wasn’t valid JSON at all—probably an HTML error page or anti-scraping message).
- Rate limiting/anti-scraping blocks: Yahoo might be flagging your requests (especially from Heroku, which uses shared IPs) as automated traffic. Instead of returning data, it’s sending non-JSON responses that break the library’s parsing.
- Outdated library + old Python version: You’re using Python 3.6, which is no longer supported. Many newer versions of yahoo_fin drop support for end-of-life Python releases, leaving you stuck with an outdated version that can’t handle Yahoo’s current API.
Fixes to Try
Let’s go through actionable solutions from simplest to most robust:
Upgrade yahoo_fin (and check Python compatibility)
First, update the library to the latest version that works with Python 3.6. Run these commands:pip uninstall yahoo-fin -y pip install yahoo-fin==0.8.9.1(Version 0.8.9.1 is one of the last releases that supports Python 3.6—if this doesn’t work, check the yahoo_fin PyPI page for other compatible versions.)
Add retries and delays to avoid blocks
Yahoo’s anti-scraping measures often trigger if you make too many requests too fast. Wrap yourget_quote_tablecalls in a retry function with delays:import time from yahoo_fin import stock_info def safe_get_quote(ticker, max_retries=3, wait_time=2): for attempt in range(max_retries): try: return stock_info.get_quote_table(ticker) except Exception as e: print(f"Attempt {attempt+1} failed for {ticker}: {str(e)}") time.sleep(wait_time) raise RuntimeError(f"Failed to fetch data for {ticker} after {max_retries} attempts") # Use it like this: quote_data = safe_get_quote(all_tickers[i]) price_opens[i] = quote_data["Previous Close"]Switch to a more reliable library: yfinance
yahoo_fin is no longer actively maintained as frequently as yfinance, a more popular and robust alternative for Yahoo Finance data. yfinance handles API changes better and supports newer Python versions. Here’s how to rewrite your code with yfinance:import yfinance as yf def get_stock_data(ticker): ticker_obj = yf.Ticker(ticker) info = ticker_obj.info live_price = ticker_obj.history(period="1m")["Close"].iloc[-1] return { "Live Price": live_price, "Previous Close": info["previousClose"], "Day Range": f"{info['dayLow']} - {info['dayHigh']}" } # Example usage: data = get_stock_data(all_tickers[i]) price_opens[i] = data["Previous Close"]Install yfinance first with
pip install yfinance.Upgrade your Python version (critical for long-term stability)
Python 3.6 reached end-of-life in 2021, meaning no security updates or library compatibility fixes. Upgrading to Python 3.8+ will let you use the latest versions of financial libraries and avoid future compatibility issues. If you’re on Heroku, you can specify the Python version in yourruntime.txtfile.
Why This Fixes Your Error
The root issue is that yahoo_fin can’t parse the response from Yahoo Finance anymore—either because the API changed, or Yahoo is blocking your requests. Upgrading the library fixes API format mismatches, retries/delays avoid blocks, and switching to yfinance gives you a more maintainable solution.
内容的提问来源于stack exchange,提问作者Andrew Cao

