- deploy/bot/ — XMPP bot核心(xmpp_agent_core + xmpp_zhiwei_bot) - deploy/profile-scripts/ — cron脚本(price_monitor等) - 运行时文件已替换为指向MoFin的符号链接 - 改代码只需改MoFin,系统自动生效
108 lines
3.9 KiB
Python
108 lines
3.9 KiB
Python
#!/usr/bin/env python3
|
||
"""import_full_stocks.py — 导入全量A股+港股列表到stocks表
|
||
|
||
数据来源:深交所/上交所公开列表(通过akshare或腾讯API)
|
||
运行:python3 import_full_stocks.py
|
||
"""
|
||
import sys, json, time, urllib.request
|
||
from pathlib import Path
|
||
|
||
DB_PATH = Path("/home/hmo/MoFin/data/mofin.db")
|
||
|
||
def fetch_tencent_batch(codes):
|
||
"""腾讯批量查询股票名称"""
|
||
url = f"http://qt.gtimg.cn/q={','.join(codes)}"
|
||
try:
|
||
req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
|
||
proxy = urllib.request.ProxyHandler({})
|
||
opener = urllib.request.build_opener(proxy)
|
||
with opener.open(req, timeout=15) as r:
|
||
text = r.read().decode("gbk")
|
||
results = {}
|
||
for line in text.strip().split("\n"):
|
||
if "~" not in line:
|
||
continue
|
||
parts = line.split("~")
|
||
name_part = parts[0] if parts else ""
|
||
code = ""
|
||
m = __import__('re').search(r'_(sh|sz|hk)(\d+)', name_part)
|
||
if m:
|
||
code = m.group(2)
|
||
name = parts[1] if len(parts) > 1 else ""
|
||
market = parts[2] if len(parts) > 2 else ""
|
||
if code and name:
|
||
results[code] = (name, market)
|
||
return results
|
||
except Exception as e:
|
||
print(f" 腾讯API错误: {e}", file=sys.stderr)
|
||
return {}
|
||
|
||
def main():
|
||
import sqlite3
|
||
conn = sqlite3.connect(str(DB_PATH))
|
||
|
||
# 获取已有代码
|
||
existing = set(r[0] for r in conn.execute("SELECT code FROM stocks").fetchall())
|
||
print(f"当前stocks表已有: {len(existing)}只")
|
||
|
||
# 生成待查询的A股代码范围(深市000/001/002/003/300/301,沪市600/601/603/605/688/689)
|
||
prefixes = {
|
||
"深市A": [f"{i:03d}" for i in range(0, 10)], # 000-009
|
||
"深市中小": [f"{i:03d}" for i in range(10, 50)], # 010-049→实际用001/002
|
||
"深市创业": [f"{i:03d}" for i in range(300, 302)], # 300-301→实际用300
|
||
"沪市A": [f"{i:03d}" for i in range(600, 606)], # 600-605
|
||
"沪市科创": [f"{i:03d}" for i in range(688, 690)], # 688-689
|
||
}
|
||
|
||
# 实际代码规则:深市000/001/002/003/300/301,沪市600/601/603/605/688
|
||
code_ranges = []
|
||
for prefix in ["000", "001", "002", "003", "300", "301"]:
|
||
for suffix in range(1, 1000):
|
||
code_ranges.append(f"{prefix}{suffix:03d}")
|
||
for prefix in ["600", "601", "603", "605", "688"]:
|
||
for suffix in range(1, 1000):
|
||
code_ranges.append(f"{prefix}{suffix:03d}")
|
||
|
||
print(f"待查代码总量: {len(code_ranges)}")
|
||
|
||
# 分批查询(每批30个)
|
||
batch_size = 30
|
||
new_count = 0
|
||
for i in range(0, len(code_ranges), batch_size):
|
||
batch = code_ranges[i:i+batch_size]
|
||
# 过滤已存在的
|
||
batch = [c for c in batch if c not in existing]
|
||
if not batch:
|
||
continue
|
||
|
||
symbols = []
|
||
for c in batch:
|
||
if c.startswith(("5", "6", "9")):
|
||
symbols.append(f"sh{c}")
|
||
else:
|
||
symbols.append(f"sz{c}")
|
||
|
||
results = fetch_tencent_batch(symbols)
|
||
for code, (name, market) in results.items():
|
||
if code not in existing:
|
||
try:
|
||
conn.execute(
|
||
"INSERT OR IGNORE INTO stocks (code, name) VALUES (?, ?)",
|
||
(code, name)
|
||
)
|
||
new_count += 1
|
||
existing.add(code)
|
||
except Exception:
|
||
pass
|
||
|
||
if (i // batch_size) % 50 == 0:
|
||
print(f" 进度: {i}/{len(code_ranges)}, 新增{new_count}")
|
||
|
||
conn.commit()
|
||
total = conn.execute("SELECT COUNT(*) FROM stocks").fetchone()[0]
|
||
print(f"\n完成: 新增{new_count}, 总{total}只")
|
||
conn.close()
|
||
|
||
if __name__ == "__main__":
|
||
main()
|