/** * 探针脚本:验证「建行定投评估」所需数据源 * 目标: * - 沪深300 / 中证500:PE-TTM + 近10年PE历史(算分位) * - 标普500 / 纳指100:实时 PE-TTM(尽力找10年历史) * 用法:node dev_test_scripts/debug/debug_dip_eval_sources.js */ const axios = require('axios') const UA = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)', 'Referer': 'https://quote.eastmoney.com/' } const cut = (s, n = 500) => String(s == null ? '' : s).replace(/\s+/g, ' ').slice(0, n) // ---------- 1. 东方财富数据中心「估值分析」(A股指数每日 PE_TTM 历史) ---------- const probeEmValuation = async (code, pageSize = 3) => { const url = `https://datacenter-web.eastmoney.com/api/data/v1/get?reportName=RPT_VALUEANALYSIS_DET&columns=ALL&filter=(SECURITY_CODE%3D%22${code}%22)&pageNumber=1&pageSize=${pageSize}&sortTypes=-1&sortColumns=TRADE_DATE&source=WEB&client=WEB` try { const res = await axios.get(url, { timeout: 10000, headers: UA, validateStatus: () => true }) const rows = res.data && res.data.result && res.data.result.data if (!Array.isArray(rows) || !rows.length) return console.log(` [东财估值分析 ${code}] 无数据 status=${res.status} body=${cut(JSON.stringify(res.data), 300)}`) const r = rows[0] console.log(` [东财估值分析 ${code}] OK 最新=${r.TRADE_DATE} PE_TTM=${r.PE_TTM} PE静态=${r.PE_LAR} PE动=${r.PE_TTM_RATIO || r.DYNAMIC_PE} 字段=${Object.keys(r).join(',')}`) } catch (e) { console.log(` [东财估值分析 ${code}] 异常: ${e.message}`) } } // ---------- 2. 东方财富 push2 实时字段(f162/f163/f164/f167) ---------- const probePush2 = async (secid) => { const url = `https://push2.eastmoney.com/api/qt/stock/get?secid=${secid}&fields=f43,f57,f58,f162,f163,f164,f167&invt=2&fltt=2` try { const res = await axios.get(url, { timeout: 10000, headers: UA, validateStatus: () => true }) const d = res.data && res.data.data if (!d) return console.log(` [push2 ${secid}] 无数据 body=${cut(JSON.stringify(res.data), 300)}`) console.log(` [push2 ${secid}] OK 名称=${d.f58} 点位=${d.f43} f162=${d.f162} f163=${d.f163} f164=${d.f164} f167=${d.f167}`) } catch (e) { console.log(` [push2 ${secid}] 异常: ${e.message}`) } } // ---------- 3. 腾讯美股指数 ---------- const probeTencent = async (symbols) => { const iconv = require('iconv-lite') const url = `http://qt.gtimg.cn/q=${symbols.join(',')}` try { const res = await axios.get(url, { timeout: 10000, responseType: 'arraybuffer', validateStatus: () => true }) const text = iconv.decode(Buffer.from(res.data), 'gb18030') for (const line of String(text).split(/;\s*/).filter(Boolean)) { console.log(` [腾讯] ${cut(line, 600)}`) } } catch (e) { console.log(` [腾讯 ${symbols}] 异常: ${e.message}`) } } // ---------- 4. 新浪美股指数 ---------- const probeSina = async (symbols) => { const iconv = require('iconv-lite') const url = `https://hq.sinajs.cn/list=${symbols.join(',')}` try { const res = await axios.get(url, { timeout: 10000, responseType: 'arraybuffer', headers: { 'User-Agent': 'Mozilla/5.0', 'Referer': 'https://finance.sina.com.cn' }, validateStatus: () => true }) const text = iconv.decode(Buffer.from(res.data), 'gb18030') for (const line of String(text).split(/\r?\n/).filter(Boolean)) { console.log(` [新浪] ${cut(line, 600)}`) } } catch (e) { console.log(` [新浪 ${symbols}] 异常: ${e.message}`) } } // ---------- 5. multpl.com 标普500 PE(当前 + 月度历史) ---------- const probeMultpl = async () => { try { const res = await axios.get('https://www.multpl.com/s-p-500-pe-ratio', { timeout: 15000, headers: { 'User-Agent': UA['User-Agent'] }, validateStatus: () => true }) const m = String(res.data).match(/Current S&P 500 PE Ratio[\s\S]{0,400}?([0-9]+\.[0-9]+)/i) console.log(` [multpl 当前PE] status=${res.status} 匹配=${m ? m[1] : '未匹配'} 片段=${cut(res.data.match(/Current S&P 500 PE Ratio[\s\S]{0,200}/i), 260)}`) } catch (e) { console.log(` [multpl 当前PE] 异常: ${e.message}`) } try { const res = await axios.get('https://www.multpl.com/s-p-500-pe-ratio/table/by-month', { timeout: 15000, headers: { 'User-Agent': UA['User-Agent'] }, validateStatus: () => true }) const html = String(res.data) const rows = html.match(/[\s\S]*?<\/tr>/g) || [] console.log(` [multpl 月度历史] status=${res.status} 表格行数=${rows.length} 示例=${cut(rows.slice(1, 4).join(' | '), 300)}`) } catch (e) { console.log(` [multpl 月度历史] 异常: ${e.message}`) } } // ---------- 6. WSJ 指数页(NDX / SPX) ---------- const probeWsj = async (path) => { const url = `https://www.wsj.com/market-data/quotes/index/${path}` try { const res = await axios.get(url, { timeout: 15000, headers: { 'User-Agent': UA['User-Agent'], 'Accept': 'text/html' }, validateStatus: () => true }) const html = String(res.data) const m = html.match(/P\/E[\s\S]{0,120}?([0-9][0-9,]*\.?[0-9]*)/i) console.log(` [WSJ ${path}] status=${res.status} len=${html.length} PE匹配=${m ? m[1] : '未匹配'}`) } catch (e) { console.log(` [WSJ ${path}] 异常: ${e.message}`) } } // ---------- 7. 东财全球指数 push2(美股 secid=100.*) ---------- const probeEmGlobal = async () => { await probePush2('100.INX') // 标普500 await probePush2('100.NDX') // 纳指100(猜测代码) await probePush2('100.DJIA') // 道指对照 } ;(async () => { console.log('=== A股指数:东财数据中心估值分析(近10年每日PE_TTM) ===') await probeEmValuation('000300') await probeEmValuation('000905') console.log('\n=== A股指数:push2 实时字段 ===') await probePush2('1.000300') await probePush2('1.000905') console.log('\n=== 美股指数:腾讯 ===') await probeTencent(['usINX', 'usIXIC', 'usDJI', 'us.NDX']) console.log('\n=== 美股指数:新浪 ===') await probeSina(['gb_$inx', 'gb_$ixic', 'gb_$dji', 'gb_$ndx']) console.log('\n=== 美股指数:东财全球指数 push2 ===') await probeEmGlobal() console.log('\n=== 标普500:multpl.com ===') await probeMultpl() console.log('\n=== 美股指数:WSJ ===') await probeWsj('NDX') await probeWsj('SPX') console.log('\n探针结束') })()