6a7a2b089a
1. 新增免费演出雷达工具:含秀动/猫眼/大麦平台抓取、本地代理鉴权配置 2. 新增建行定投评估模块:四大指数PE-TTM估值与定投档位建议 3. 新增推送告警白名单过滤功能,限制推送指定指数告警 4. 重构周报首页提醒逻辑,移至服务端处理并减少前端请求 5. 新增多套调试探针脚本与单元测试用例
137 lines
6.3 KiB
JavaScript
137 lines
6.3 KiB
JavaScript
/**
|
||
* 探针脚本:验证「建行定投评估」所需数据源
|
||
* 目标:
|
||
* - 沪深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探针结束')
|
||
})()
|