YFinance Flask Web应用无法显示非美国市场股票价格问题求助
我最近做了一个用yfinance、Flask和JavaScript搭建的股票价格监控网页,美国市场的股票(比如AAPL、MSFT)都能正常显示实时价格和涨跌幅,但非美国市场的股票就出问题了——我看浏览器的网络请求明明已经拿到了数据,但前端页面就是不显示任何内容,也没有报错提示。我怀疑是数据格式或者前端选择器的问题,但自己排查了半天没找到根源,有没有大佬能帮我看看?
我的代码结构
我把代码分成了后端Flask接口和前端JavaScript逻辑两部分,具体代码如下:
Flask 后端代码
import yfinance as yf from flask import request, render_template, jsonify, Flask app = Flask(__name__, template_folder='templates') @app.route('/') def index(): return render_template('index.html') @app.route('/get_stock_data', methods=['POST']) def get_stock_data(): ticker = request.get_json()['ticker'] data = yf.Ticker(ticker).history(period='1y') if data.empty: return jsonify({"error": "No data found for the given ticker."}) return jsonify({ "currentPrice": data.iloc[-1].Close, "openPrice": data.iloc[-1].Open }) if __name__ == '__main__': app.run(debug=True)
前端JavaScript代码
var tickers = JSON.parse(localStorage.getItem('tickers')) || []; var lastPrices = {}; var counter = 10; function startUpdateCycle() { updatePrices(); setInterval(function() { counter--; $('#counter').text(counter); if (counter <= 0) { updatePrices(); counter = 10; } }, 1000); } $(document).ready(function() { tickers.forEach(function(ticker) { addTickerToGrid(ticker); }); $('#tickers').on('click', '.remove-btn', function() { var tickerToRemove = $(this).data('ticker'); tickers = tickers.filter(t => t !== tickerToRemove); localStorage.setItem('tickers', JSON.stringify(tickers)); $('#'+tickerToRemove).remove(); }); updatePrices(); $('#add-ticker-form').submit(function(e) { e.preventDefault(); var newTicker = $('#new-ticker').val().toUpperCase(); if (!tickers.includes(newTicker)) { tickers.push(newTicker); localStorage.setItem('tickers', JSON.stringify(tickers)) addTickerToGrid(newTicker); } $('new-ticker').val(''); updatePrices(); }); $('#tickers-grid').on('click', '.remove-btn', function() { var tickerToRemove = $(this).data('ticker'); tickers = tickers.filter(t => t !== tickerToRemove); localStorage.setItem('tickers', JSON.stringify(tickers)); $('#'+tickerToRemove).remove(); }); startUpdateCycle(); }); function addTickerToGrid(ticker) { $('#tickers-grid').append(`<div id="${ticker}" class="stock-box"><h2>${ticker}</h2><p id="${ticker}-price"></p><p id="${ticker}-pct"></p><button class="remove-btn" data-ticker="${ticker}">Remove</button></div>`); } function updatePrices() { tickers.forEach(function(ticker) { $.ajax({ url: '/get_stock_data', type : 'POST', data: JSON.stringify({ticker: ticker}), contentType: 'application/json; charset=utf-8', dataType: 'json', success: function (data) { var changePercent = ((data.currentPrice - data.openPrice) / data.openPrice) * 100; var colorClass; if (changePercent <= -2) { colorClass = 'dark-red' } else if (changePercent <= 0) { colorClass = 'red' } else if (changePercent == 0) { colorClass = 'gray' } else if (changePercent <= 2) { colorClass = 'green' } else { colorClass = 'dark-green' } $('#'+ticker+'-price').text('$'+data.currentPrice.toFixed(2)); $('#'+ticker+'-pct').text(changePercent.toFixed(2)+'%'); $('#'+ticker+'-price').removeClass("dark-red red gray green dark-green").addClass(colorClass); $('#'+ticker+'-pct').removeClass("dark-red red gray green dark-green").addClass(colorClass); var flashClass; if (lastPrices[ticker] > data.currentPrice) { flashClass = 'red-flash'; } else if (lastPrices[ticker] < data.currentPrice) { flashClass = 'green-flash'; } else { flashClass = 'gray-flash'; } lastPrices[ticker] = data.currentPrice; $('#'+ticker).addClass(flashClass); setTimeout(function() { $('#'+ticker).removeClass(flashClass); }, 1000); } }); }); }
问题现象
- 美国市场股票(如AAPL、GOOGL):添加后能正常显示当前价格、涨跌幅,更新也正常。
- 非美国市场股票(如港股0700.HK、德国BMW.DE):网络请求能成功返回数据(在浏览器开发者工具的Network面板里能看到currentPrice和openPrice的数值),但页面上对应的股票卡片里的价格和涨跌幅始终是空的,没有任何内容显示。
我自己排查的点
- 确认非美国股票的ticker格式正确(比如0700.HK、BMW.DE),yfinance能拿到数据,后端接口也返回了正确的JSON数据。
- 检查前端的success回调是否执行:在回调里加console.log(data),能看到正确的currentPrice和openPrice数值,说明回调是正常触发的。
现在实在不知道哪里出问题了,求大佬们指点!
问题根源与解决方案
看了你的代码和问题描述,我立刻发现了几个核心问题,其中第一个就是导致非美国股票不显示的关键:
1. jQuery选择器无法识别含特殊字符的ID
非美国股票的ticker通常包含.(比如0700.HK、BMW.DE),而.在jQuery/CSS选择器中是类选择器的标识。举个例子:
你创建的价格元素id是0700.HK-price,但你用$('#0700.HK-price')去选择时,jQuery会把它解析为「寻找id为0700且class为HK-price的元素」,完全匹配不到实际的元素,自然无法设置价格文本。
修复方案(二选一):
方案A:使用属性选择器替代ID选择器
在updatePrices函数中,把所有通过id选择元素的代码改成属性选择器,比如:// 替换原有的价格设置代码 $('[id="'+ticker+'-price"]').text('$'+data.currentPrice.toFixed(2)); $('[id="'+ticker+'-pct"]').text(changePercent.toFixed(2)+'%'); // 替换样式设置代码 $('[id="'+ticker+'-price"]').removeClass("dark-red red gray green dark-green").addClass(colorClass); $('[id="'+ticker+'-pct"]').removeClass("dark-red red gray green dark-green").addClass(colorClass); // 替换闪烁效果的代码 $('[id="'+ticker+'"]').addClass(flashClass); setTimeout(function() { $('[id="'+ticker+'"]').removeClass(flashClass); }, 1000);属性选择器会完全匹配id的字符串内容,不会解析特殊字符。
方案B:对ticker的特殊字符进行转义/替换
在创建元素时,把ticker里的特殊字符(比如.)替换为下划线_,同时保留原始ticker在data属性中:function addTickerToGrid(ticker) { // 替换特殊字符为下划线,生成安全的ID var safeId = ticker.replace(/[.#$&+,:;=?@'<>]/g, '_'); $('#tickers-grid').append(`<div id="${safeId}" class="stock-box" data-ticker="${ticker}"><h2>${ticker}</h2><p id="${safeId}-price"></p><p id="${safeId}-pct"></p><button class="remove-btn" data-ticker="${ticker}">Remove</button></div>`); }然后在
updatePrices函数中,通过元素的data-ticker获取原始ticker,用safeId来选择元素。
2. 潜在的JSON序列化问题
yfinance返回的价格是numpy的数值类型(比如numpy.float64),虽然Flask的jsonify通常能处理,但为了避免跨环境的序列化问题,建议在后端转成Python原生的float类型:
return jsonify({ "currentPrice": float(data.iloc[-1].Close), "openPrice": float(data.iloc[-1].Open) })
3. 前端输入框清空的小BUG
原代码中提交表单后清空输入框的代码是$('new-ticker').val('');,缺少了ID选择器的#,应该改为:
$('#new-ticker').val('');
额外提示:非美国股票的ticker格式
确保你输入的非美国股票ticker是yfinance支持的格式,比如:
- 港股:
0700.HK(不能只输0700) - 德国股票:
BMW.DE - 中国A股:比如贵州茅台是
600519.SS(上交所)、宁德时代是300750.SZ(深交所)
按照上面的方法修改后,非美国股票的价格应该就能正常显示了!
备注:内容来源于stack exchange,提问作者Salih




