匹配范围
*://xueqiu.com/**://*.xueqiu.com/*xueqiu-stock-quote雪球股票实时行情 用途 查询雪球股票实时行情,返回股票名称、代码、价格、涨跌幅、成交额、市值和交易状态等信息。 执行前提 先打开 https://xueqiu.com/ 或雪球股票页面,并保持当前 Cookie 可用。接口可能依赖登录态、Cookie 或站点风控,未登录、登录过期、验证码或访问频率过高时可能失败。脚本使用浏览器 credentials: "…
*://xueqiu.com/**://*.xueqiu.com/*dom.read1const rawParams = params && typeof params === "object" ? params : {};2 3function assertXueqiuPage() {4 if (!/(^|\.)xueqiu\.com$/i.test(location.hostname)) {5 throw new Error("Open a xueqiu.com page first, then run this script");6 }7}8 9function requiredSymbol() {10 const symbol = String(rawParams.symbol ?? "").trim().toUpperCase();11 if (!symbol) throw new Error("symbol is required");12 return symbol;13}14 15function formatAmount(value) {16 if (value === undefined || value === null || value === "") return null;17 const number = Number(value);18 if (!Number.isFinite(number)) return String(value);19 if (Math.abs(number) >= 1e12) return `${(number / 1e12).toFixed(2)}万亿`;20 if (Math.abs(number) >= 1e8) return `${(number / 1e8).toFixed(2)}亿`;21 if (Math.abs(number) >= 1e4) return `${(number / 1e4).toFixed(2)}万`;22 return String(number);23}24 25function percentString(value) {26 if (value === undefined || value === null || value === "") return null;27 const number = Number(value);28 return Number.isFinite(number) ? `${number.toFixed(2)}%` : String(value);29}30 31async function readJson(response) {32 try {33 return await response.json();34 } catch {35 return null;36 }37}38 39assertXueqiuPage();40const symbol = requiredSymbol();41const url = `https://stock.xueqiu.com/v5/stock/batch/quote.json?symbol=${encodeURIComponent(symbol)}`;42 43const response = await fetch(url, {44 headers: { Accept: "application/json" },45 credentials: "include",46});47 48const payload = await readJson(response);49 50if (!response.ok) {51 const detail = payload?.error_description || `HTTP ${response.status}`;52 throw new Error(`Quote request failed: ${detail}`);53}54 55if (payload?.error_code || payload?.error_description) {56 throw new Error(`Quote request failed: ${payload.error_description || payload.error_code}`);57}58 59const items = Array.isArray(payload?.data?.items) ? payload.data.items : [];60if (items.length === 0) {61 throw new Error(`No quote data returned for ${symbol}`);62}63 64const item = items[0] || {};65const quote = item.quote || {};66const market = item.market || {};67 68return [{69 name: quote.name,70 symbol: quote.symbol,71 exchange: quote.exchange,72 currency: quote.currency,73 price: quote.current,74 change: quote.chg,75 changePercent: percentString(quote.percent),76 open: quote.open,77 high: quote.high,78 low: quote.low,79 prevClose: quote.last_close,80 amplitude: percentString(quote.amplitude),81 volume: quote.volume,82 amount: formatAmount(quote.amount),83 turnoverRate: percentString(quote.turnover_rate),84 marketCap: formatAmount(quote.market_capital),85 floatMarketCap: formatAmount(quote.float_market_capital),86 ytdPercent: percentString(quote.current_year_percent),87 marketStatus: market.status || null,88 time: quote.timestamp ? new Date(quote.timestamp).toISOString() : null,89 url: quote.symbol ? `https://xueqiu.com/S/${quote.symbol}` : null,90}];