66 lines
2.4 KiB
Python
66 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""stock_name_hygiene.py — 股票名称卫生(每周)
|
||
2026-08-22 名称治理:XD/XR/DR 除权息日交易所简称被截断(紫金矿业→XD紫金矿),
|
||
各行情源当天均无干净名。本任务每周拉 akshare 官方全量名称,剥 XD 标记后比对,
|
||
凡 DB 名是官方名的前缀(截断)即以官方名为准修复,自愈截断/改名/ST 变更。
|
||
"""
|
||
import os, sys, re
|
||
from datetime import datetime
|
||
|
||
# ── 消息通道统一路由(broadcast/xmpp by delivery) ──
|
||
try:
|
||
from messenger import install_stdio_hook as _msh
|
||
_msh()
|
||
except Exception:
|
||
pass
|
||
|
||
DB_PATH = os.environ.get("MOFIN_DB", "/home/hmo/MoFin/data/mofin.db")
|
||
|
||
|
||
def strip_marker(n: str) -> str:
|
||
m = re.match(r"^(XD|XR|DR)(.+)$", n)
|
||
return m.group(2) if m else n
|
||
|
||
|
||
def main():
|
||
import sqlite3
|
||
import akshare as ak
|
||
|
||
print(f"[stock_name_hygiene] {datetime.now():%Y-%m-%d %H:%M:%S} 开始", flush=True)
|
||
df = ak.stock_info_a_code_name()
|
||
name_map = {str(c): strip_marker(str(n)) for c, n in zip(df["code"], df["name"])}
|
||
print(f" 官方名称源: {len(name_map)} 条", flush=True)
|
||
|
||
conn = sqlite3.connect(DB_PATH, timeout=30)
|
||
conn.row_factory = sqlite3.Row
|
||
total = 0
|
||
samples = []
|
||
for table in ["stocks", "candidates", "holdings"]:
|
||
try:
|
||
rows = conn.execute(f"SELECT code, name FROM {table}").fetchall()
|
||
except Exception:
|
||
continue
|
||
fixed = 0
|
||
for r in rows:
|
||
code, cur = str(r["code"]), str(r["name"])
|
||
full = name_map.get(code)
|
||
if not full or full == cur:
|
||
continue
|
||
# 只修明确劣化:DB名是官方名前缀(XD截断)、或DB名=代码、或仅ST标记差异
|
||
if full.startswith(cur) or cur == code or cur.lstrip("*ST") == full.lstrip("*ST"):
|
||
conn.execute(f"UPDATE {table} SET name=? WHERE code=? AND name=?", (full, code, cur))
|
||
fixed += 1
|
||
if len(samples) < 8:
|
||
samples.append(f"{code} {cur}→{full}")
|
||
if fixed:
|
||
print(f" {table}: 修复 {fixed} 行", flush=True)
|
||
total += fixed
|
||
conn.commit()
|
||
conn.close()
|
||
print(f"[stock_name_hygiene] 完成,共修复 {total} 行" + (f"(样本: {'; '.join(samples)})" if samples else ""), flush=True)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|