real-time-stock-mcp-service 1.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. real_time_stock_mcp_service-1.1.2/.gitignore +54 -0
  2. real_time_stock_mcp_service-1.1.2/LICENSE +21 -0
  3. real_time_stock_mcp_service-1.1.2/PKG-INFO +129 -0
  4. real_time_stock_mcp_service-1.1.2/README.md +117 -0
  5. real_time_stock_mcp_service-1.1.2/pyproject.toml +27 -0
  6. real_time_stock_mcp_service-1.1.2/src/stock_mcp/__init__.py +0 -0
  7. real_time_stock_mcp_service-1.1.2/src/stock_mcp/__main__.py +8 -0
  8. real_time_stock_mcp_service-1.1.2/src/stock_mcp/app.py +113 -0
  9. real_time_stock_mcp_service-1.1.2/src/stock_mcp/crawler/__init__.py +0 -0
  10. real_time_stock_mcp_service-1.1.2/src/stock_mcp/crawler/base_crawler.py +153 -0
  11. real_time_stock_mcp_service-1.1.2/src/stock_mcp/crawler/basic_data.py +106 -0
  12. real_time_stock_mcp_service-1.1.2/src/stock_mcp/crawler/financial_analysis.py +246 -0
  13. real_time_stock_mcp_service-1.1.2/src/stock_mcp/crawler/fundamental_data.py +240 -0
  14. real_time_stock_mcp_service-1.1.2/src/stock_mcp/crawler/market.py +306 -0
  15. real_time_stock_mcp_service-1.1.2/src/stock_mcp/crawler/real_time_data.py +92 -0
  16. real_time_stock_mcp_service-1.1.2/src/stock_mcp/crawler/smart_review.py +246 -0
  17. real_time_stock_mcp_service-1.1.2/src/stock_mcp/crawler/technical_data.py +238 -0
  18. real_time_stock_mcp_service-1.1.2/src/stock_mcp/crawler/test.py +16 -0
  19. real_time_stock_mcp_service-1.1.2/src/stock_mcp/crawler/test_count_changes.py +21 -0
  20. real_time_stock_mcp_service-1.1.2/src/stock_mcp/crawler/valuation_data.py +326 -0
  21. real_time_stock_mcp_service-1.1.2/src/stock_mcp/data_source_interface.py +651 -0
  22. real_time_stock_mcp_service-1.1.2/src/stock_mcp/mcp_tools/__init__.py +2 -0
  23. real_time_stock_mcp_service-1.1.2/src/stock_mcp/mcp_tools/financial_analysis.py +465 -0
  24. real_time_stock_mcp_service-1.1.2/src/stock_mcp/mcp_tools/fundamental.py +289 -0
  25. real_time_stock_mcp_service-1.1.2/src/stock_mcp/mcp_tools/kline_data.py +257 -0
  26. real_time_stock_mcp_service-1.1.2/src/stock_mcp/mcp_tools/market.py +960 -0
  27. real_time_stock_mcp_service-1.1.2/src/stock_mcp/mcp_tools/real_time_data.py +157 -0
  28. real_time_stock_mcp_service-1.1.2/src/stock_mcp/mcp_tools/search.py +143 -0
  29. real_time_stock_mcp_service-1.1.2/src/stock_mcp/mcp_tools/smart_review.py +255 -0
  30. real_time_stock_mcp_service-1.1.2/src/stock_mcp/mcp_tools/valuation.py +412 -0
  31. real_time_stock_mcp_service-1.1.2/src/stock_mcp/stock_data_source.py +212 -0
  32. real_time_stock_mcp_service-1.1.2/src/stock_mcp/utils/__init__.py +0 -0
  33. real_time_stock_mcp_service-1.1.2/src/stock_mcp/utils/markdown_formatter.py +40 -0
  34. real_time_stock_mcp_service-1.1.2/src/stock_mcp/utils/utils.py +273 -0
@@ -0,0 +1,54 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+
23
+ # Virtual Environment
24
+ venv/
25
+ ENV/
26
+ env/
27
+ .venv
28
+
29
+ # IDEs
30
+ .vscode/
31
+ .idea/
32
+ *.swp
33
+ *.swo
34
+ *~
35
+ .DS_Store
36
+
37
+ # Environment variables
38
+ .env
39
+
40
+ # Logs
41
+ *.log
42
+ logs/
43
+
44
+ # Testing
45
+ .pytest_cache/
46
+ .coverage
47
+ htmlcov/
48
+
49
+ # uv
50
+ .uv/
51
+
52
+ # MCP
53
+ .mcp/
54
+ /.lingma/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Danny Wong
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,129 @@
1
+ Metadata-Version: 2.4
2
+ Name: real-time-stock-mcp-service
3
+ Version: 1.1.2
4
+ Summary: 一个获取实时股票数据服务和分析的MCP服务器
5
+ License-File: LICENSE
6
+ Requires-Python: >=3.12
7
+ Requires-Dist: mcp>=1.1.2
8
+ Requires-Dist: pandas>=2.2.0
9
+ Requires-Dist: python-dateutil>=2.9.0
10
+ Requires-Dist: requests>=2.32.0
11
+ Description-Content-Type: text/markdown
12
+
13
+ # 实时股票分析 MCP 服务
14
+
15
+ ---
16
+
17
+ 这是一个实时股票数据服务的MCP服务器。它通过东方财富网获取金融数据,并将这些数据以工具的形式暴露给支持MCP的AI模型。
18
+
19
+ > **代码仓库:** https://github.com/DannyWongIsAvailable/real-time-stock-mcp-service.git
20
+
21
+ - 免费免登录获取数据,免token
22
+ - 部分功能支持B股,H股
23
+
24
+ ## 功能特性
25
+
26
+ - 📊 查找股票
27
+ - 📈 K线数据查询(支持B股,H股,大盘)
28
+ - 📉 技术指标分析 (MA,MACD,BOLL,KDJ等等)
29
+ - 💰 基本面数据分析(主营构成、经营范围等)
30
+ - 📊 财务分析(财务比率、业绩概况等)
31
+ - 💰 估值分析数据(市盈率、市净率等)
32
+ - 📈 市场行情跟踪(板块行情、同行对比、资金流向等)
33
+ - 🤖 智能点评和评分
34
+
35
+ 共33个MCP工具
36
+
37
+ ## 使用方法
38
+
39
+ 您可以通过以下2种方式使用本服务:
40
+
41
+ ### 1. 魔搭社区免费云资源一键部署
42
+
43
+ 您可以在魔搭社区MCP实验场中在线体验该服务,也支持客户端远程连接(streamable HTTP或SSE协议)
44
+
45
+ https://modelscope.cn/mcp/servers/DannyWong/real-time-stock-mcp
46
+
47
+ ### 2. 本地stdio模式(以Claude Desktop为例)
48
+
49
+ #### 在 Claude Desktop 中配置
50
+
51
+ 编辑 Claude Desktop 的配置文件:
52
+
53
+ **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
54
+ **MacOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
55
+
56
+ 添加以下配置:
57
+
58
+ ```json
59
+ {
60
+ "mcpServers": {
61
+ "stock-mcp": {
62
+ "args": [
63
+ "real-time-stock-mcp-service"
64
+ ],
65
+ "command": "uvx"
66
+ }
67
+ }
68
+ }
69
+ ```
70
+
71
+ > **注意:** 将路径替换为你的实际项目路径。
72
+
73
+
74
+ #### 视频教程参考:
75
+ - [火遍全网的MCP是什么?怎么用?如何自己开发一个MCP服务?一个视频带你入门!](https://www.bilibili.com/video/BV13R5EzbE6E/?spm_id_from=333.337.search-card.all.click&vd_source=08fc400fe0cfc7eaa723687b764b29f3)
76
+ - [Cherry Studio MCP 使用入门教程:从配置到使用](https://www.bilibili.com/video/BV1bkdAYTEYp/?spm_id_from=333.337.search-card.all.click&vd_source=08fc400fe0cfc7eaa723687b764b29f3)
77
+
78
+ ## 核心设计
79
+
80
+ 本项目采用**依赖注入**设计模式:
81
+
82
+ 1. `crawler` 模块获取数据
83
+ 2. `data_source_interface.py` 定义抽象数据源接口
84
+ 3. `stock_data_source.py` 提供具体实现
85
+ 4. 各工具模块通过依赖注入获取数据源实例
86
+
87
+ 这种设计使得:
88
+ - ✅ 易于扩展新功能
89
+ - ✅ 可以轻松切换不同数据源
90
+ - ✅ 便于单元测试
91
+ - ✅ 代码解耦,维护性强
92
+
93
+ ## 工具模块
94
+
95
+ 项目包含33个MCP工具模块,每个模块提供特定领域的功能:
96
+
97
+ - `search.py` - 股票搜索和交易日信息
98
+ - `real_time_data.py` - 实时股票行情数据
99
+ - `kline_data.py` - K线数据和技术指标
100
+ - `fundamental.py` - 基本面数据(主营构成、经营范围等)
101
+ - `valuation.py` - 估值分析数据(市盈率、市净率等)
102
+ - `financial_analysis.py` - 财务分析数据(财务比率、业绩概况等)
103
+ - `market.py` - 市场行情数据(板块行情、资金流向等)
104
+ - `smart_review.py` - 智能点评和评分
105
+
106
+
107
+ ## 开发指南
108
+
109
+ 详情请查看[开发指南](DEVELOPMENT.md)
110
+
111
+ ## 注意事项
112
+
113
+ ⚠️ **重要提醒**:
114
+ 1. 本服务提供的数据仅供参考,不构成投资建议
115
+ 2. 仅允许个人学习、研究、使用,禁止用于商业用途。严禁滥用!
116
+ 3. 请遵守数据使用协议和相关法律法规
117
+
118
+ ## 开源协议
119
+
120
+ [MIT License](LICENSE)
121
+
122
+ ## 贡献
123
+
124
+ 欢迎提交 Issue 和 Pull Request!
125
+
126
+ ## 联系方式
127
+
128
+ 如有问题,请提交 Issue 或联系项目开发者。
129
+ 求一个star,感激不尽!
@@ -0,0 +1,117 @@
1
+ # 实时股票分析 MCP 服务
2
+
3
+ ---
4
+
5
+ 这是一个实时股票数据服务的MCP服务器。它通过东方财富网获取金融数据,并将这些数据以工具的形式暴露给支持MCP的AI模型。
6
+
7
+ > **代码仓库:** https://github.com/DannyWongIsAvailable/real-time-stock-mcp-service.git
8
+
9
+ - 免费免登录获取数据,免token
10
+ - 部分功能支持B股,H股
11
+
12
+ ## 功能特性
13
+
14
+ - 📊 查找股票
15
+ - 📈 K线数据查询(支持B股,H股,大盘)
16
+ - 📉 技术指标分析 (MA,MACD,BOLL,KDJ等等)
17
+ - 💰 基本面数据分析(主营构成、经营范围等)
18
+ - 📊 财务分析(财务比率、业绩概况等)
19
+ - 💰 估值分析数据(市盈率、市净率等)
20
+ - 📈 市场行情跟踪(板块行情、同行对比、资金流向等)
21
+ - 🤖 智能点评和评分
22
+
23
+ 共33个MCP工具
24
+
25
+ ## 使用方法
26
+
27
+ 您可以通过以下2种方式使用本服务:
28
+
29
+ ### 1. 魔搭社区免费云资源一键部署
30
+
31
+ 您可以在魔搭社区MCP实验场中在线体验该服务,也支持客户端远程连接(streamable HTTP或SSE协议)
32
+
33
+ https://modelscope.cn/mcp/servers/DannyWong/real-time-stock-mcp
34
+
35
+ ### 2. 本地stdio模式(以Claude Desktop为例)
36
+
37
+ #### 在 Claude Desktop 中配置
38
+
39
+ 编辑 Claude Desktop 的配置文件:
40
+
41
+ **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
42
+ **MacOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
43
+
44
+ 添加以下配置:
45
+
46
+ ```json
47
+ {
48
+ "mcpServers": {
49
+ "stock-mcp": {
50
+ "args": [
51
+ "real-time-stock-mcp-service"
52
+ ],
53
+ "command": "uvx"
54
+ }
55
+ }
56
+ }
57
+ ```
58
+
59
+ > **注意:** 将路径替换为你的实际项目路径。
60
+
61
+
62
+ #### 视频教程参考:
63
+ - [火遍全网的MCP是什么?怎么用?如何自己开发一个MCP服务?一个视频带你入门!](https://www.bilibili.com/video/BV13R5EzbE6E/?spm_id_from=333.337.search-card.all.click&vd_source=08fc400fe0cfc7eaa723687b764b29f3)
64
+ - [Cherry Studio MCP 使用入门教程:从配置到使用](https://www.bilibili.com/video/BV1bkdAYTEYp/?spm_id_from=333.337.search-card.all.click&vd_source=08fc400fe0cfc7eaa723687b764b29f3)
65
+
66
+ ## 核心设计
67
+
68
+ 本项目采用**依赖注入**设计模式:
69
+
70
+ 1. `crawler` 模块获取数据
71
+ 2. `data_source_interface.py` 定义抽象数据源接口
72
+ 3. `stock_data_source.py` 提供具体实现
73
+ 4. 各工具模块通过依赖注入获取数据源实例
74
+
75
+ 这种设计使得:
76
+ - ✅ 易于扩展新功能
77
+ - ✅ 可以轻松切换不同数据源
78
+ - ✅ 便于单元测试
79
+ - ✅ 代码解耦,维护性强
80
+
81
+ ## 工具模块
82
+
83
+ 项目包含33个MCP工具模块,每个模块提供特定领域的功能:
84
+
85
+ - `search.py` - 股票搜索和交易日信息
86
+ - `real_time_data.py` - 实时股票行情数据
87
+ - `kline_data.py` - K线数据和技术指标
88
+ - `fundamental.py` - 基本面数据(主营构成、经营范围等)
89
+ - `valuation.py` - 估值分析数据(市盈率、市净率等)
90
+ - `financial_analysis.py` - 财务分析数据(财务比率、业绩概况等)
91
+ - `market.py` - 市场行情数据(板块行情、资金流向等)
92
+ - `smart_review.py` - 智能点评和评分
93
+
94
+
95
+ ## 开发指南
96
+
97
+ 详情请查看[开发指南](DEVELOPMENT.md)
98
+
99
+ ## 注意事项
100
+
101
+ ⚠️ **重要提醒**:
102
+ 1. 本服务提供的数据仅供参考,不构成投资建议
103
+ 2. 仅允许个人学习、研究、使用,禁止用于商业用途。严禁滥用!
104
+ 3. 请遵守数据使用协议和相关法律法规
105
+
106
+ ## 开源协议
107
+
108
+ [MIT License](LICENSE)
109
+
110
+ ## 贡献
111
+
112
+ 欢迎提交 Issue 和 Pull Request!
113
+
114
+ ## 联系方式
115
+
116
+ 如有问题,请提交 Issue 或联系项目开发者。
117
+ 求一个star,感激不尽!
@@ -0,0 +1,27 @@
1
+ [project]
2
+ name = "real-time-stock-mcp-service"
3
+ version = "1.1.2"
4
+ description = "一个获取实时股票数据服务和分析的MCP服务器"
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ dependencies = [
8
+ "mcp>=1.1.2",
9
+ "requests>=2.32.0",
10
+ "pandas>=2.2.0",
11
+ "python-dateutil>=2.9.0",
12
+ ]
13
+
14
+ # 给托管/本地一个稳定的命令入口:执行 stock-mcp 就能跑
15
+ [project.scripts]
16
+ real-time-stock-mcp-service = "stock_mcp.app:main"
17
+
18
+ [build-system]
19
+ requires = ["hatchling"]
20
+ build-backend = "hatchling.build"
21
+
22
+ # 告诉 hatchling 包在 src/ 下,且包名是 stock_mcp
23
+ [tool.hatch.build.targets.wheel]
24
+ packages = ["src/stock_mcp"]
25
+
26
+ [tool.hatch.build.targets.sdist]
27
+ include = ["src/stock_mcp/**", "README.md", "pyproject.toml"]
@@ -0,0 +1,8 @@
1
+ """
2
+ 让托管平台可以用 `python -m stock_mcp` 一条命令拉起服务
3
+ """
4
+
5
+ from stock_mcp.app import main
6
+
7
+ if __name__ == "__main__":
8
+ main()
@@ -0,0 +1,113 @@
1
+ """
2
+ 股票数据 MCP Server(托管友好入口)
3
+ """
4
+
5
+ import logging
6
+ import os
7
+ from datetime import datetime
8
+
9
+ from mcp.server.fastmcp import FastMCP
10
+
11
+ from stock_mcp.data_source_interface import FinancialDataInterface
12
+ from stock_mcp.stock_data_source import WebCrawlerDataSource
13
+ from stock_mcp.utils.utils import setup_logging
14
+
15
+ from stock_mcp.mcp_tools.search import register_search_tools
16
+ from stock_mcp.mcp_tools.kline_data import register_kline_tools
17
+ from stock_mcp.mcp_tools.real_time_data import register_real_time_data_tools
18
+ from stock_mcp.mcp_tools.fundamental import register_fundamental_tools
19
+ from stock_mcp.mcp_tools.valuation import register_valuation_tools
20
+ from stock_mcp.mcp_tools.financial_analysis import register_financial_analysis_tools
21
+ from stock_mcp.mcp_tools.market import register_market_tools
22
+ from stock_mcp.mcp_tools.smart_review import register_smart_review_tools
23
+
24
+
25
+ def build_app(active_data_source: FinancialDataInterface) -> FastMCP:
26
+ """
27
+ 构建 FastMCP app(只做“创建 + 注册工具”)
28
+ """
29
+ current_date = datetime.now().strftime("%Y-%m-%d")
30
+
31
+ app = FastMCP(
32
+ name="real-time-stock-mcp-service",
33
+ instructions=f"""📊 一个获取实时股票数据服务和分析的MCP服务器
34
+
35
+ **今天日期**: {current_date}
36
+
37
+ 📈 主要功能:
38
+ - 查找股票名称,代码
39
+ - 实时股票数据
40
+ - K线数据(日线、周线、月线)
41
+ - 计算技术指标
42
+ - 基本面数据(主营构成、经营范围、经营评述等)
43
+ - 估值分析数据(市盈率、市净率等)
44
+ - 板块行情数据
45
+ - 智能点评和评分
46
+ """,
47
+ )
48
+
49
+ # ✅ 注册所有工具
50
+ register_search_tools(app, active_data_source)
51
+ register_real_time_data_tools(app, active_data_source)
52
+ register_kline_tools(app, active_data_source)
53
+ register_fundamental_tools(app, active_data_source)
54
+ register_valuation_tools(app, active_data_source)
55
+ register_financial_analysis_tools(app, active_data_source)
56
+ register_market_tools(app, active_data_source)
57
+ register_smart_review_tools(app, active_data_source)
58
+
59
+ return app
60
+
61
+
62
+ def main() -> None:
63
+ """
64
+ 程序主入口:
65
+ 1) 配日志
66
+ 2) 创建数据源(依赖注入)
67
+ 3) 构建 app + 注册工具
68
+ 4) 初始化数据源
69
+ 5) app.run() 启动(stdio)
70
+ 6) finally 清理资源
71
+ """
72
+ # ✅ 托管环境常用环境变量控制日志级别,方便排障
73
+ log_level = os.getenv("LOG_LEVEL", "INFO").upper()
74
+ setup_logging(level=getattr(logging, log_level, logging.INFO))
75
+ logger = logging.getLogger(__name__)
76
+
77
+ # 1) 依赖注入:后续切换数据源只改这里
78
+ active_data_source: FinancialDataInterface = WebCrawlerDataSource()
79
+ logger.info("数据源: %s", active_data_source.__class__.__name__)
80
+
81
+ # 2) 构建 app(注册工具)
82
+ app = build_app(active_data_source)
83
+ logger.info("工具模块注册完成")
84
+
85
+ # 3) 初始化数据源
86
+ try:
87
+ if active_data_source.initialize():
88
+ logger.info("✅ 数据源初始化成功")
89
+ else:
90
+ logger.warning("⚠️ 数据源初始化失败,某些功能可能不可用")
91
+ except Exception:
92
+ logger.exception("💥 数据源初始化异常:将继续启动(功能可能受限)")
93
+
94
+ # 4) 运行服务(托管通常走 stdio,保持默认)
95
+ try:
96
+ logger.info("🚀 启动 MCP Server(stdio)")
97
+ app.run()
98
+ except KeyboardInterrupt:
99
+ logger.info("🛑 服务被中断")
100
+ except Exception:
101
+ logger.exception("💥 服务运行出错")
102
+ raise
103
+ finally:
104
+ # 5) 清理资源
105
+ try:
106
+ active_data_source.cleanup()
107
+ logger.info("🧹 资源清理完成")
108
+ except Exception:
109
+ logger.exception("💥 资源清理异常")
110
+
111
+
112
+ if __name__ == "__main__":
113
+ main()
@@ -0,0 +1,153 @@
1
+ import re
2
+ import time
3
+ import json
4
+ import random
5
+ import requests
6
+ from abc import ABC
7
+ from typing import Optional, Dict, Any
8
+
9
+
10
+ class EastMoneyBaseSpider(ABC):
11
+ """
12
+ 东方财富爬虫基类
13
+
14
+ 提供通用功能:
15
+ - Session 管理
16
+ - 请求头/Cookies 配置
17
+ - JSONP 解析
18
+ - 股票代码格式转换
19
+ """
20
+
21
+ # 子类可覆盖的默认配置
22
+ DEFAULT_TIMEOUT = 10
23
+ DEFAULT_HEADERS = {
24
+ "Accept": "application/json, text/plain, */*",
25
+ "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
26
+ "Connection": "keep-alive",
27
+ "User-Agent": (
28
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
29
+ "AppleWebKit/537.36 (KHTML, like Gecko) "
30
+ "Chrome/129.0.0.0 Safari/537.36"
31
+ ),
32
+ }
33
+
34
+ def __init__(
35
+ self,
36
+ session: Optional[requests.Session] = None,
37
+ timeout: int = None,
38
+ ):
39
+ self.session = session or requests.Session()
40
+ self.timeout = timeout or self.DEFAULT_TIMEOUT
41
+ self.headers = self.DEFAULT_HEADERS.copy()
42
+ self.cookies: Dict[str, str] = {}
43
+
44
+ # ==================== 通用工具方法 ====================
45
+
46
+ def _get(
47
+ self,
48
+ url: str,
49
+ params: Dict[str, Any] = None,
50
+ **kwargs
51
+ ) -> requests.Response:
52
+ """封装 GET 请求"""
53
+ return self.session.get(
54
+ url,
55
+ params=params,
56
+ headers=self.headers,
57
+ cookies=self.cookies,
58
+ timeout=self.timeout,
59
+ **kwargs
60
+ )
61
+
62
+ def _get_json(self, url: str, params: Dict[str, Any] = None) -> Dict:
63
+ """GET 请求并解析 JSON"""
64
+ resp = self._get(url, params)
65
+ resp.raise_for_status()
66
+ return resp.json()
67
+
68
+ def _get_jsonp(self, url: str, params: Dict[str, Any] = None) -> Optional[Dict]:
69
+ """GET 请求并解析 JSONP"""
70
+ resp = self._get(url, params)
71
+ resp.raise_for_status()
72
+ return self._parse_jsonp(resp.text)
73
+
74
+ @staticmethod
75
+ def _parse_jsonp(text: str) -> Optional[Dict]:
76
+ # 允许末尾有分号
77
+ match = re.search(r'^\w+\((.*)\);?$', text.strip(), re.DOTALL)
78
+ if not match:
79
+ return None
80
+ try:
81
+ return json.loads(match.group(1))
82
+ except json.JSONDecodeError:
83
+ return None
84
+
85
+ @staticmethod
86
+ def _generate_callback() -> str:
87
+ """生成 jQuery 风格的 JSONP callback 名称"""
88
+ rand_part = random.randint(10 ** 19, 10 ** 20 - 1)
89
+ ts = int(time.time() * 1000)
90
+ return f"jQuery{rand_part}_{ts}"
91
+
92
+ @staticmethod
93
+ def _timestamp_ms() -> int:
94
+ """当前时间戳(毫秒)"""
95
+ return int(time.time() * 1000)
96
+
97
+ @staticmethod
98
+ def format_secid(stock_code: str) -> str:
99
+ """
100
+ 将股票代码转换为东方财富的 secid 格式
101
+
102
+ 支持格式:
103
+ - "000977" -> "0.000977" (深市)
104
+ - "600000" -> "1.600000" (沪市)
105
+ - "000977.SZ" -> "0.000977"
106
+ - "600000.SH" -> "1.600000"
107
+ - "0.000977" -> "0.000977" (已是 secid)
108
+ - "00977.HK" -> "116.00977" (H股)
109
+ - "116.00977" -> "116.00977" (已是 secid)
110
+ - "01810" -> "116.01810" (港股)
111
+ - "01810.HK" -> "116.01810" (港股)
112
+
113
+ :param stock_code: 股票代码
114
+ :return: secid 格式字符串
115
+ """
116
+ code = stock_code.strip().upper()
117
+
118
+ if "." in code:
119
+ left, right = code.split(".", maxsplit=1)
120
+
121
+ # 已经是 secid 格式
122
+ if left in {"0", "1", "116"} and right.isdigit():
123
+ return f"{left}.{right}"
124
+
125
+ # 带后缀格式:000977.SZ
126
+ if right in {"SZ", "SH"}:
127
+ market = "0" if right == "SZ" else "1"
128
+ return f"{market}.{left}"
129
+
130
+ # H股格式:00977.HK 或 01810.HK
131
+ if right == "HK":
132
+ return f"116.{left.zfill(5)}" # 港股代码补齐为5位
133
+
134
+ # 纯数字代码
135
+ if code.isdigit():
136
+ # 6 开头沪市,其他深市
137
+ if code.startswith("6"):
138
+ return f"1.{code}"
139
+ # 5位数港股代码(通常以0开头)
140
+ elif len(code) == 5:
141
+ return f"116.{code}"
142
+ # 其他情况为深市
143
+ else:
144
+ return f"0.{code}"
145
+
146
+ raise ValueError(f"无法解析股票代码: {stock_code}")
147
+
148
+
149
+
150
+
151
+
152
+
153
+