Files
Toolbox/dev_test_scripts/debug/debug_dip_eval_sources.js
yangxiangyuan 6a7a2b089a feat: 新增免费演出雷达工具与定投评估功能,优化周报提醒逻辑
1. 新增免费演出雷达工具:含秀动/猫眼/大麦平台抓取、本地代理鉴权配置
2. 新增建行定投评估模块:四大指数PE-TTM估值与定投档位建议
3. 新增推送告警白名单过滤功能,限制推送指定指数告警
4. 重构周报首页提醒逻辑,移至服务端处理并减少前端请求
5. 新增多套调试探针脚本与单元测试用例
2026-08-04 17:33:14 +08:00

137 lines
6.3 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 探针脚本:验证「建行定投评估」所需数据源
* 目标:
* - 沪深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(/<tr>[\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探针结束')
})()