> Source: https://ashareapi.com/docs/guides/chatgpt-sites-dashboard/  ·  Markdown version for LLMs / AI agents

教程

# 用 ChatGPT Sites 搭一个 A 股情绪看板
 ChatGPT Sites 能用一段话生成网页，数据靠浏览器里一个 fetch 拿。免费端点已开放跨域，不用后端、不用 Key，页面直接调。代码见下。

## 为什么不用后端？因为接口已经允许跨域
 浏览器要调别的域名，会先问对方「允不允许」。实测两个免费端点都返回 `access-control-allow-origin: *`（2026-10-28 验证）⇒ 页面里直接 `fetch` 就能取到数据，**不需要自己搭服务器做代理**。
 先自己验一下，返回头里要有那一行：

 命令行（验证跨域头）
```
curl -s -D - -o /dev/null \
 -H "Origin: https://example.chatgpt.site" \
 https://api.ashareapi.com/v1/changedist | grep -i access-control

# access-control-allow-origin: *
```

## 先定看板要显示什么
 一张情绪看板用前三行就够了。全部 96 个端点见端点清单，其中 7 个免费、无需注册。
 |
| | 读数 | 端点 | 要 Key 吗 | 单位

| | 上涨 / 下跌家数 | `/v1/changedist` | 不要 | 家

| | 涨停 / 跌停家数 | `/v1/changedist` | 不要 | 家

| | 两市成交额 | `/v1/changedist` | 不要 | 亿元（在 `data` 文本里）

| | 个股最新价 | `/v1/quote?code=sh600519` | 不要 | 元

| | 热搜榜 | `/v1/hot` | 不要 | —

 上涨 / 下跌家数
 `/v1/changedist`
 不要
 家

 涨停 / 跌停家数
 `/v1/changedist`
 不要
 家

 两市成交额
 `/v1/changedist`
 不要
 亿元（在 `data` 文本里）

 个股最新价
 `/v1/quote?code=sh600519`
 不要
 元

 热搜榜
 `/v1/hot`
 不要
 —

## 第一步：把页面描述交给 ChatGPT
 新建一个 Site，把下面这段直接贴进去。它决定布局，数据部分下一步再补：

 给 ChatGPT 的描述（可直接粘贴）
```
做一个单页的 A 股情绪看板，要求：
1. 顶部四个卡片：上涨家数、下跌家数、涨停家数、两市成交额
2. 数据从 https://api.ashareapi.com/v1/changedist 取，
 用浏览器里的 fetch 直接调，不要写后端
3. 涨用红色、跌用绿色，深色背景
4. 每 30 秒自动刷新一次
```
 生成后站点地址形如 ` . .chatgpt.site`。AI 在生成时并不知道真实字段名，取值逻辑多半对不上，用下一步的代码整段替换即可。

## 第二步：把数据接进去（完整代码，整段替换）
 下面这份是**对着真实返回写死的**，把 AI 生成的 ` ` 整段换掉即可（页面结构也一并给全，方便直接替换整个文件）：

 HTML + 原生 JS（无依赖，可直接跑）
```
<!doctype html>
<html lang="zh">
<meta charset="utf-8">
<title>A股情绪看板</title>
<style>
 body{margin:0;padding:24px;background:#0b0b0f;color:#e9e9f2;
 font:14px/1.5 -apple-system,"Segoe UI",sans-serif}
 .row{display:flex;gap:12px;flex-wrap:wrap}
 .card{min-width:120px;padding:14px 18px;border-radius:10px;
 background:#16161d;border:1px solid #2a2a36}
 .k{font-size:12px;color:#8a8aa0}
 .v{margin-top:4px;font-size:26px;font-weight:600}
 .up{color:#ff4d4f}.down{color:#00c853}
 #ts{margin-top:16px;font-size:12px;color:#8a8aa0}
</style>
<div class="row" id="cards"></div>
<div id="ts"></div>

<script>
var API = "https://api.ashareapi.com/v1";

function card(k, v, cls) {
 return '<div class="card"><div class="k">' + k + '</div>' +
 '<div class="v ' + (cls || "") + '">' + v + '</div></div>';
}

async function loadMood() {
 var r = await fetch(API + "/changedist");
 var b = await r.json();
 if (!b.ok) throw new Error("changedist 返回失败");

 var s = (b.structured && b.structured[0]) || {}; // key 是中文
 var m = String(b.data).match(/两市成交额：([\d.]+)亿/); // 成交额只在 data 文本里

 document.getElementById("cards").innerHTML =
 card("上涨", s["上涨"], "up") +
 card("下跌", s["下跌"], "down") +
 card("涨停", s["涨停"], "up") +
 card("跌停", s["跌停"], "down") +
 card("上涨占比", s["上涨占比"]) +
 card("两市成交额", m ? m[1] + " 亿" : "—");

 document.getElementById("ts").textContent =
 "更新于 " + new Date().toLocaleTimeString();
}

loadMood();
setInterval(loadMood, 30000); // 30 秒；别低于 12 秒
</script>
</html>
```

## ⚠️ 三个真实踩坑

-
 **字段名是中文** —— `structured[0]` 的 key 就是 `"上涨"` `"下跌"` `"涨停"`，不是 `up` / `down`。AI 生成的代码几乎一定猜成英文，务必对一遍真实返回。

-
 **上涨占比 是 "20%" 这样的字符串，不是数字 20** —— 带百分号。要参与计算先 `parseFloat()`，直接丢进图表库会变成 NaN。

-
 **成交额不在 structured 里** —— `structured` 只装了第一张表（涨跌家数）；成交额在 `data` 这段 Markdown 文本里，只能正则提取：`b.data.match(/两市成交额：([\d.]+)亿/)`。

## 第三步：想加个股，就再调一个端点

 JavaScript（接在同一个 script 里）
```
async function loadStock(code) {
 var r = await fetch(API + "/quote?code=" + code);
 var b = await r.json();
 if (!b.ok || !b.data || !b.data.length) return null;

 var bar = b.data[0]; // 按日期倒序，data[0] 是最新一根
 return {
 date: bar.date,
 last: Number(bar.last),
 high: Number(bar.high),
 low: Number(bar.low),
 volume: Number(bar.volume), // 手
 amount: Number(bar.amount), // 元
 turnover: Number(bar.turnover) // %
 };
}

loadStock("sh600519").then(console.log);
```
 |
| | 字段 | 含义 | 单位 | 示例值（sh600519 · 2026-10-29 盘中）

| | `date` | 交易日 | — | 2026-10-29

| | `last` | 最新价 | 元 | 1344.93

| | `high` / `low` | 当日最高 / 最低 | 元 | 1349.99 / 1330.01

| | `volume` | 成交量 | **手** | 8251

| | `amount` | 成交额 | **元** | 1105305033

| | `turnover` | 换手率 | % | 0.07

 `date`
 交易日
 —
 2026-10-29

 `last`
 最新价
 元
 1344.93

 `high` / `low`
 当日最高 / 最低
 元
 1349.99 / 1330.01

 `volume`
 成交量
 **手**
 8251

 `amount`
 成交额
 **元**
 1105305033

 `turnover`
 换手率
 %
 0.07

 `volume` 是手（1 手 = 100 股）、`amount` 是元 —— 这两个单位是最常见的错误来源，建议在代码里写注释。**自查办法**：`last × volume × 100 ≈ amount`，对得上说明单位没读错（示例：1344.93 × 8251 × 100 ≈ 11.1 亿，与 `amount` 同一量级）。表内数值随行情变化，单位是固定的。

## 看板跑起来之后要注意的三件事

-
 **匿名限流 5 次/分钟** —— 自动刷新间隔别小于 12 秒，否则会拿到 429。上面代码用的 30 秒是安全的。

-
 **别在前端硬编码付费 Key** —— 页面源码是公开的，Key 会被抄走。需要更高频率就在服务端取数，Key 只放在服务端。

-
 **看板只描述状态，不预测方向** —— 上涨家数远多于下跌家数，只说明「今天普涨」，不等于「明天该买」。情绪读数要和历史均值、量能一起看。

## 这套东西不适合做什么

-
 **不适合秒级刷新** —— 免费额度 5 次/分，做高频轮询只会被限流。要高频请用 Key 并在服务端聚合。

-
 **不适合直接做成多用户产品** —— 所有访客共用你这一层匿名额度，人一多就互相挤。

-
 **不适合当作交易信号** —— 本文只讲怎么取数和展示，不构成投资建议。

## 常见问题
 ChatGPT 生成的页面调接口会被跨域拦住吗？
 **不会。** 实测免费端点返回 `access-control-allow-origin: *`（2026-10-28 验证），浏览器里直接 `fetch` 即可。自己验一行命令就能确认，见第一步。

 要注册或申请 Key 吗？
 **不用。** `changedist` / `quote` / `hot` 都在 7 个免费端点里 —— 无需注册、无需 Key，匿名可调（5 次/分钟）。

 做好的页面能分享给别人看吗？
 站点地址可以分享，形如 ` . .chatgpt.site`。**能否匿名访问取决于你在 ChatGPT Sites 里的站点设置** —— 建议用无痕窗口打开验一次：若提示登录，就是站点还没开放。

 为什么我的涨跌家数和别的平台不一样？
 先核对**口径**：`/v1/changedist` 是**当期**（今天）；而 `/v1/market-overview?type=updown` 是 **T-1**（返回里会标数据日期）。另外各平台对统计范围（是否含 ST / 北交所 / 停牌）的处理可能不同。

 能加 K 线图吗？
 可以。`/v1/kline?code=sh600519&count=60` 取日线（免费、前复权），交给任意前端图表库画即可。字段与参数见端点清单里的 `kline`。

 最后更新: 2026-10-28
 代码与字段取自线上真实返回（2026-10-29 复核）：`/v1/changedist` 的 `structured[0]` key 为中文（上涨 / 下跌 / 涨停 / 跌停 / 上涨占比 / 停牌 / 平盘），`上涨占比` 为带百分号字符串，两市成交额只在 `data` 文本中；`/v1/quote` 的 `data` 按日期倒序，`volume` 单位为手、`amount` 单位为元；两个端点均返回 `access-control-allow-origin: *`。文中数值为示例，随行情变化；字段与限流以端点文档为准。

 接着看

-
[端点清单（96 个端点，含 changedist / quote / hot）](/endpoints)

-
[用数据量化 A股市场情绪（全免费端点）](/docs/guides/market-mood)

-
[用 Python 获取实时行情：3 种方法对比](/docs/guides/python-ashare-quotes)

-
[错误码与限流](/docs/errors)

 [← 全部教程](/docs/guides)
