先说我自己的体验:以前网页看盘和本地股软是两套系统,网页上自选股里点的股票,本地软件完全不知道,反过来本地软件里切换股票,网页也没反应。直到用了 Wzslinker 这个网页股软联动助手,才把这层窗户纸捅破。它最核心的使用方式是围绕东方财富网页版来做联动,底层依赖的是东方财富公开的行情接口,其中最关键的参数就是 secid2。这篇文章会把它的工作原理、secid2 的格式拆解、联动配置和踩坑经历全盘托出,适合喜欢折腾工具的股民、量化自学者,也适合想把网页数据和本地行情工具打通的技术型投资者。
1. 网页看盘与本地股软的“割裂”问题
1.1 为什么网页和本地软件对不上
东方财富网页版几乎能做所有看盘操作:加入自选、切分时图、看主力资金、翻 F10 资料。但网页也有明显的短板,它占着内存不说,频繁切换页面还会导致数据刷新变慢,热键响应也谈不上爽快。很多老股民都习惯用本地股软,比如通达信、同花顺 PC 端,界面流畅、指标公式随便写、自定义板块灵活。
问题就出在这里:网页上看的股票和本地软件里的股票,是两个完全独立的状态。你上午在网页上盯贵州茅台,下午想切到本地软件接着看走势,本地软件默认停在上次关闭时的页面,你不得不再敲一遍代码或者翻自选股列表。自选股更是如此,网页里加了一堆股票进自选,本地股软里还得手动重加一次,这种重复劳动干久了特别消磨耐心。
Wzslinker 解决的正是这个“信息孤岛”。它的思路是让网页端的事件(比如你在网页上点击某只股票)通过一个本地中转服务,主动推送到股软客户端,让股软跟着网页走。反方向也能做:本地股软的自选股列表,可以被网页端捕获并同步进来。这两条链路一旦打通,网页是遥控器,股软是显示器。我实际用下来,最大的感受是“顺手”,少了很多无效操作。
1.2 联动场景到底有多刚需
举几个我平时高频使用的场景。
第一个是盘口跟单场景:我经常在网页端盯龙虎榜、涨停板池,看到一只票封板了想立刻切换到本地软件看筹码分布、资金流。没有联动的时候,我得记代码,再去本地软件里输入代码,等它加载,前后至少十秒钟,封板速度快的票根本等不起。有了联动,我网页上一点,本地软件几乎同步就切过去了,效率完全不一样。
第二个是自选股同步场景:晚上复盘的时候,我习惯用网页版把第二天重点关注的票加入自选。以前还要手工在通达信里重新归类,现在 Wzslinker 把我网页自选股列表里的股票代码都读出来,再按照本地软件的板块文件格式写入,本地自选和网页自选保持一致,第二天开盘直接打开本地软件就能按板块看。
第三个是条件选股联动场景:我用网页版跑一些简单的指标排序,排序结果里选出前二十名,需要把这些票快速导入到本地软件画线分析。通过 Wzslinker 的联动接口,可以直接把这一批代码推送过去,省掉了复制粘贴再导入的过程。
这些场景背后都有一个共同要求:网页端和市场端的数据必须有一一对应的关系。而建立这个对应关系的关键,就落在 secid2 这个参数上。
1.3 为什么数据源选东方财富
市面上有行情数据的平台很多,同花顺、新浪财经、腾讯证券都提供了网页接口,但东方财富的接口有一个很突出的优势:接口稳定、字段丰富、对开发者友好。
东方财富网页版本身就依赖内部的 HTTPS 接口来获取行情,只要网页能打开,这些接口基本都能访问。我实测过它的 push2 行情接口,响应速度快,字段命名规则清晰,而且不需要付费 token。相比之下,有些平台要么接口不稳定,要么需要签名验证,对个人折腾来说门槛高了不少。
用东方财富还有一个额外的好处:它的自选股数据结构比较清晰,网页版里展示的自选股列表,底层就是一组 secid 数组。Wzslinker 可以直接从页面结构里把这些 secid 抓出来,省去了自行映射市场前缀和代码的麻烦。所以说,围绕东方财富做联动,是当下网页股软联动方案中投入产出比比较高的选择。
2. 核心数据基础:secid2 与东方财富接口
2.1 secid2 到底是什么格式
secid2 这个名字在东方财富的接口体系里其实就是“secid”,后面加个 2 只是社区里为了区分股票和市场 ID 的通俗叫法。它由两部分组成:市场前缀 + 证券代码,中间用点号连接。
- 1 表示上海市场(沪市)
- 0 表示深圳市场(深市)
举个例子,贵州茅台的代码是 600519,属于上海市场,所以完整 secid 就是1.600519。平安银行的代码是 000001,属于深圳市场,那就是0.000001。
这个格式在东方财富的行情接口里是通用的,不管是单只股票查询、批量行情、还是 k 线获取,都要用同样的 secid 作为参数。你在网页上看到一只股票的详情地址,地址里通常会带上 secid 信息;打开浏览器开发者工具看清请求,也能在请求参数里直接看到它。
搞懂 secid 是联动的前提。因为无论网页端怎么展示股票,最终落到接口层面都是用 secid 来唯一定位。Wzslinker 要把“网页上点击的这只票”告诉本地软件,中间传递的信息本质上就是一个 secid,本地软件再根据 secid 反解出市场和代码,完成跳转。
2.2 常用行情接口与字段含义
东方财富行情接口最常用的是push2.eastmoney.com系列的/api/qt/stock/get和/api/qt/stock/quote。我这里以单只股票实时行情为例,接口参数大致如下:
https://push2.eastmoney.com/api/qt/stock/get?secid=1.600519&fields=f43,f44,f45,f46,f57,f58,f60secid:目标股票的定位符fields:需要返回的字段编号,多个字段用逗号分隔
常用字段编号我整理成一张表,方便你对照使用:
| 字段编号 | 含义 | 说明 |
|---|---|---|
| f43 | 最新价 | 通常需要除以 100 得到真实价格 |
| f44 | 最高价 | 接口返回的数值一般是整数形式 |
| f45 | 最低价 | 同上 |
| f46 | 今开价 | 同上 |
| f57 | 股票代码 | 纯代码字符串 |
| f58 | 股票名称 | 比如“贵州茅台” |
| f60 | 昨收价 | 用于计算涨跌幅 |
| f107 | 市场类型 | 1=沪市,0=深市 |
| f162 | 市盈率动态 | 部分字段需要权限或不一定返回 |
注意,f43 这类价格字段返回的往往是整数,而不是小数。真实价格等于接口值除以 100。这个细节特别重要,如果你忘了做缩放,本地软件收到的价格就会差一百倍,整个联动就失真了。我在最开始写联动脚本时就踩过这个坑,还以为是接口坏了,后来才发现是字段值需要缩放。
stock/get适用于单只股票查询,quote接口则适用于批量行情。批量查询时 secid 用逗号拼接多个值,例如1.600519,0.000001。Wzslinker 在同步自选股时,通常用的就是这种批量模式。
2.3 解析返回数据时要注意的细节
接口返回的数据是 JSON 格式,外层有rc、data等字段,真正的行情信息都在data对象里。解析时最关键的一步是:判断data是否为空。如果 secid 写错或者市场前缀配错,data会直接返回null。
另一个细节是字段值的单位。除了价格要除以 100,部分成交量字段也可能以“手”为单位,需要对照文档换算。做联动时我们最关心的其实只有代码、名称、最新价这三个字段,把它们的解析逻辑写稳定就够了。
还有一点值得注意:接口请求需要带一个正常浏览器的 User-Agent,否则偶尔会被网关拦截。我用 Python 请求时习惯伪装成 Chrome 的 UA,实测能显著降低请求失败的概率。如果你只是本地调试,加上这一行就够了。
我在本地写了一个简单的验证脚本,用来确认 secid 解析是否正常:
import requests secid = "1.600519" url = "https://push2.eastmoney.com/api/qt/stock/get" params = { "secid": secid, "fields": "f43,f44,f46,f57,f58,f60", } headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" } resp = requests.get(url, params=params, headers=headers, timeout=5) data = resp.json().get("data") if not data: print("secid 无效:", secid) else: print(data["f58"], data["f57"], data["f43"] / 100)这个脚本输出股票名称、代码和真实价格。拿到这一步,等于打通了股市数据的基本通道,接下来进入联动层面的配置。
3. 联动引擎拆解:Wzslinker 是怎么工作的
3.1 网页端如何捕获点击行为
网页与本地软件联动的第一步,是从网页里把用户行为提取出来。Wzslinker 在浏览器端通常以扩展或者注入脚本的形式运行,在东方财富的页面上监听用户操作。
具体来说,它会在网页的股票列表容器中绑定事件监听器。当用户点击某一行时,脚本会向上追溯 DOM 结构,找到该行元素上存储的 secid 属性。东方财富网页版的列表行元素通常带有自定义属性或者 class 名称,其中就包含股票代码信息。脚本把这些信息提取出来后,再组织成一个标准的联动消息。
这里有一个比较关键的设计决策:到底用点击事件还是用 DOM 变化监听。单纯用点击事件,会出现漏听的问题,比如用户用键盘方向键在列表里上下切换,或者通过自选股分组切换股票时,不一定会触发点击。所以更稳妥的方案是两者结合:监听点击的同时,也监听列表容器内部 DOM 的变化,捕获当前高亮行的变化。
我拆解过的联动实现里,大多数采用了“事件 + 轮询”的方式:事件负责即时反馈,轮询负责兜底。轮询的间隔一般控制在 500 毫秒到 1 秒之间,既不会太耗资源,也能保证联动不丢。
3.2 本地股软的切换链路
网页端捕获到 secid 之后,接下来是从浏览器到本地的传输。这一步通常会借助一个本地代理服务,用 WebSocket 或者 HTTP 端口来接收网页端发过来的消息。
本地代理服务的任务有两个:解析消息中的 secid,并把它转换成目标股软能识别的操作。转换方式取决于股软支持什么外部接口,常见的路径有以下几种:
- 如果本地股软支持 DDE,代理服务可以直接把 secid 通过 DDE 指令发送给行情窗口。
- 如果本地股软支持公式系统里的外部数据接口,代理服务可以调用公式函数触发切换。
- 如果股软没有开放接口,代理服务最粗暴的方式是模拟键盘输入,比如先激活股软窗口,然后发送“代码 + 回车”。
我自己用的通达信版本,对外部联动不算开放得特别彻底,所以选择的是模拟键盘输入的路线。为了让模拟输入不抢焦点、不误触其他窗口,代理服务会先找到目标窗口句柄,激活它,再发送按键序列。这个过程要做到又快又稳,需要对 Windows 消息循环有一些基础了解,不过现成的开源库已经封装好了,直接调用就好。
这里推荐第二种思路:如果只做自选股同步,其实不一定要走键盘模拟。本地软件的自选股通常是一组文本文件,比如通达信的自选板块文件是特定的文本格式,代理服务直接把 secid 列表改写成板块文件,再触发软件重新加载就够了。这种方式更稳定,不容易出错。
3.3 消息队列与联动状态管理
当网页端同时发生多个操作,比如你快速点了十只股票,本地代理如果每个都实时响应,股软还没切到第一只,新的指令又来了,画面会变得非常混乱。因此 Wzslinker 内部必须有一层节流和队列控制。
节流的思路是:在很小的时间窗口内,只保留最后一次联动请求。比如 300 毫秒内连续来了多个 secid,代理只处理最后一个。这个设计在实际看盘时非常有用,因为人眼根本捕捉不到那么快的切换,只要保证最终状态一致就行。
队列的思路则是用于自选股同步这种大批量场景。同步过程中包含数十甚至上百只股票,如果请求一个接一个地立刻执行,本地软件会卡住。把任务放进队列,按一定频率逐个处理,再在最后做一次汇总刷新,体验会好很多。我自己的配置是把队列频率设置为每秒处理三到五只股票,这样既不会让本地软件卡顿,也不会等太久。
联动状态管理还包括一个很重要的边界条件处理:当网页端从一只股票切换到另一只股票后,本地软件还没完成切换,用户却直接关闭了网页,这时代理应该立即终止当前任务,避免下一次打开网页时出现残留切换。好的联动工具都会在前端监测到关闭动作时发一个清理指令。
3.4 联动延迟的测量与优化
延迟是联动体验中最重要的指标。延迟太高,联动就成了摆设。我实测过自己搭的一套链路,从网页点击事件发生到本地股软弹窗切换完成,延迟大概在 250 毫秒左右。这个数值包含了 DOM 捕获、网络传输、本地命令执行、股软响应四段耗时。
其中占比最大的往往不是网络,而是本地股软的响应。如果你用的是机械硬盘,股软加载新页面需要时间;换成固态硬盘之后,延迟能明显降下来。另外,本地代理服务的语言也有影响,用 Node 或者 Go 写的服务,启动和响应速度相对更轻量,Python 虽然写起来方便,但初次调用时偶尔会有 Python 解释器层面的轻微延迟,不过对于 300 毫秒级的需求来说,完全够用。
我在优化时做了几件小事:把代理服务常驻内存而不是每次动态启动;把浏览器和代理之间的连接设计成长连接,避免反复握手;把 secid 解析结果在代理层做缓存,对于重复出现的股票直接走快捷通道。这几步做下来,延迟基本稳定在 200 毫秒左右。
4. 实操:从零配置一套网页联动环境
4.1 前置条件与软件准备
在开始配置之前,先确认你的电脑环境满足下面这些条件:
- 操作系统:Windows 10 或 Windows 11,本地股软的自动激活在 Windows 下最方便。
- 浏览器:Chrome 或 Edge,支持扩展脚本注入。
- 本地股软:建议先用通达信或同花顺练习,它们对板块文件、窗口激活的兼容性比较好。
- 运行环境:如果你打算直接跑社区提供的联动程序,需要 Python 3.8 以上;如果打算用 Node 版本,则准备 Node 14 以上。
我最初是用 Python 版本的联动脚本起手的,因为它的依赖库最直观,requests 和 pyautogui 就能覆盖大部分功能。等熟悉了整个链路之后,再迁移到 Node 版本,主要是为了让内存占用更低、启动更快。
4.2 第一步:验证 secid 与行情接口连通性
不要急着配置股软,先把数据源打通。打开一个终端,执行下面这段 Python 代码,验证你的电脑能不能拿到东方财富行情数据。
import requests def fetch_quote(secid): url = "https://push2.eastmoney.com/api/qt/stock/get" params = { "secid": secid, "fields": "f57,f58,f43", } headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" } resp = requests.get(url, params=params, headers=headers, timeout=5) data = resp.json().get("data") if data: return data return None if __name__ == "__main__": test_secid = "1.600519" result = fetch_quote(test_secid) if result: print("名称:", result["f58"]) print("代码:", result["f57"]) print("价格:", result["f43"] / 100) else: print("接口异常或 secid 错误")如果这一步能正常输出贵州茅台的名称和价格,说明你的网络环境畅通,接口连通性没有问题。如果没有输出,先检查 UA 是否设置,再检查电脑时间是否同步。
4.3 第二步:在浏览器端注入联动脚本
网页端捕获行为是最容易出现环境影响的地方,因为东方财富网页的结构随时可能调整。一个稳妥的做法是手动注入脚本,而不是依赖一个固定的扩展。
打开浏览器开发者工具,在 Console 面板里粘贴下面这段简化版的捕获代码:
function getSecidFromRow(row) { const elem = row.querySelector('[class*="stockcode"]'); if (!elem) return null; const code = elem.textContent.trim(); if (!/^\d{6}$/.test(code)) return null; const market = code.startsWith('6') ? '1' : '0'; return market + '.' + code; } document.addEventListener('click', (e) => { const row = e.target.closest('tbody tr'); if (!row) return; const secid = getSecidFromRow(row); if (secid) { // 发送到本地代理服务 fetch('http://127.0.0.1:8765/notify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ secid: secid }), }); } });这段代码的意图是:在页面点击事件发生时,向上查找被点击元素所在的表格行,从行内文本提取六位股票代码。这里做了一个简化判断,以 6 开头当作沪市,其他当作深市。真实场景中,东方财富网页的行元素上可能带有更准确的 market 标识,所以更推荐优先从属性里读取,而不是靠代码前缀去猜。
把这段代码注入 Console 后,点击任意一行股票,观察 Network 面板里是否出现了发送到 127.0.0.1:8765 的请求。如果看到了,说明网页端捕获链路已经就绪。
4.4 第三步:起动本地代理服务
本地代理服务的写法有很多,核心是一个 HTTP 服务,接收/notify请求,解析 secid,然后触发股软动作。下面是一个极简的 Python 实现,只负责接收和解析:
from http.server import BaseHTTPRequestHandler, HTTPServer import json class Handler(BaseHTTPRequestHandler): def do_POST(self): if self.path == "/notify": length = int(self.headers.get("Content-Length", 0)) payload = json.loads(self.rfile.read(length)) secid = payload.get("secid", "") print("收到联动请求:", secid) # 这里后续接入切换股软的逻辑 self.send_response(200) self.end_headers() self.wfile.write(b"ok") server = HTTPServer(("127.0.0.1", 8765), Handler) print("本地联动服务已启动,端口 8765") server.serve_forever()把上面的代码保存为wzl_linker.py,在终端里运行python wzl_linker.py。然后回到浏览器,再点击一只股票,观察终端是否输出了对应的 secid。到这一步,说明网页到本地的通路已经完全打通。
真正接入股软时,你只需要把# 这里后续接入切换股软的逻辑这一行替换成具体的股软操作代码。比如,调用一个switch_to_stock(secid)函数,内部通过 pyautogui 输入代码并回车,或者通过封装好的窗口消息接口发送指令。
4.5 第四步:配置自选股同步模块
如果你也需要网页自选和本地自选保持一致,可以再加一个定时同步线程。我在工程里是这样设计的:每 30 秒判断一次网页自选列表是否变化,如果变化,就把最新的 secid 列表整体同步到本地板块文件。
本地股软的自选股文件格式各不相同,拿通达信来说,自选股板块通常在安装目录T0002\blocknew下,文件结构是一组文本行。每一行包含代码和名称。同步的逻辑也很简单:读取网页自选 secid 列表,按格式写入板块文件,然后触发通达信重新加载。
这里有个很重要的细节:写文件前一定要备份原来的板块文件。我吃过一次亏,同步脚本有一个市场前缀判断写错了,导致深市股票全部写成了沪市前缀,差点把自选股列表搞乱。从那以后,我在每次写板块文件前都会自动复制一份带时间戳的备份,这个习惯帮我挽回过好几次。
4.6 验证联动是否真正生效
配置完成后,最后验证一下真实效果。我的验证步骤固定是这三步:
- 打开东方财富网页版,进入任意自选股分组。
- 用鼠标点击分组里的第一只股票。
- 观察本地股软窗口是否自动切换到对应股票,并显示正确名称和最新价。
如果切换成功,再快速点击第二只、第三只,确认股软能跟上节奏。注意观察是否存在掉帧、卡死或者切到一半停止的情况。如果有,大概率是本地股软窗口没有获得焦点,或者注入脚本里的代码匹配规则出了偏差。
我在一次实测里遇到的情况是:点击第一只股票后本地软件切换成功,点击第二只却完全没有反应。排查后发现是页面里第二只股票所在表格行被外层容器遮挡,导致点击事件的目标不是预期的tbody tr,而是其他元素。修正选择器的匹配逻辑之后,问题才解决。
5. 常见问题与排查实录
5.1 网页端捕获不到股票代码
这个问题的表现是:浏览器点击股票没有产生任何网络请求。我用过的排查思路是,先在页面任意一行股票上右键,“检查”打开元素面板,看看这一行里到底有没有包含股票代码的文本节点。
如果行内根本没有可识别的代码文本,说明网页结构已经更新,原来的定位选择器失效了。这时候需要重新查看 DOM 结构,寻找带有>curl -X POST http://127.0.0.1:8765/notify -H "Content-Type: application/json" -d '{"secid":"1.600519"}'
如果 curl 发送之后股软切换了,说明代理逻辑没问题,问题在网页端数据没有正确传过来;如果 curl 发送之后股软也没反应,那问题就在代理服务调用股软的部分。
股软没反应还有一个被忽略的高频原因:窗口标题匹配失败。很多本地股软的窗口标题会包含版本号或用户自定义名称,代理服务在查找窗口句柄时如果只按固定标题匹配,就会扑空。建议改为按进程名匹配主窗口,或者简单粗暴一点,用软件主窗口的类名来定位。
5.3 secid2 解析后价格不对
价格不对,最常见的原因就是整数与小数之间的换算。接口返回的价格字段经常是整数,真实价格需要除以 100。但注意,不同接口的缩放系数可能不同,有的接口返回 100 倍,有的返回 1000 倍,甚至有的字段直接返回字符串类型,不能混用。
我在做联动时,对价格字段的处理原则是:只用于展示,不用于策略计算。如果联动时只需要切换股票,那么价格不是关键信息,可以先忽略单位换算。只有在做自选股同步这类不涉及价格的操作时,反而少了换算的烦恼。如果后续要扩展实时价格展示功能,再根据接口文档逐一确认字段缩放。
5.4 自选股同步后本地软件里顺序错乱
这个问题的根源在于,网页自选股的排序逻辑和本地股软板块文件的排序逻辑不一致。网页端通常按加入时间排序,或者按自定义排序;本地软件则是按文件行顺序读取。同步工具如果只做“覆盖式写入”,很容易丢失原有顺序。
我的解决方案是:同步时保留本地板块文件已有的基础顺序,新增的股票追加在文件尾部,然后再刷新页面。这样一来,旧股票的排序不动,新股票只出现在末尾,整个自选股列表的观感会好很多。
如果遇到极端情况需要完全按照网页排序替换本地列表,可以先在板块文件里写入一个临时排序序号字段,观察本地软件是否支持按序号排序。不支持的话,就只能接受本地软件自己的排序逻辑,毕竟板块文件格式是股软固定的,能做的是“尽量对齐”。
5.5 联动服务频繁挂掉
本地代理服务挂掉,通常有两个原因:一是端口被占用,二是长时间运行后内存泄漏。端口被占用很好解决,换一个端口或在启动前检查端口占用情况。内存泄漏则需要留意代码里是否反复创建连接对象却不释放。
我推荐在本地代理服务里加一个简单的看门狗:每隔一分钟检查一次主进程是否存活,如果进程退出就自动重新拉起。Windows 下可以用计划任务实现,也可以用 supervisor 这类工具。虽然量级很小,但对每天都要用的工具来说,稳定性比花哨功能更重要。
写在最后的小总结
按我自己的实际体验来说,Wzslinker 这类网页股软联动助手最大的价值不在于某个单一功能,而是把两个原本互不相通的工具真正串成了一条流水线。整个过程中,secid2 的解析其实只是入门,真正花时间的是适配本地软件的个性差异。我在通达信上能用的方案,换到同花顺上可能就要重新调窗口激活和板块文件格式。如果你是第一次接触联动,建议先把“网页点击到本地代理收到 secid”打穿,再用最小代价验证“代理到股软切换”,不要一上来就追求全流程完美。还有一个小技巧:本地代理服务最好设置成开机自启,保存好端口和备份,这样你每天打开电脑就能直接用,不需要重新折腾配置。这套东西后续还可以扩展的方向很多,比如把自选股联动换成板块联动,把单向推送改成双向同步,甚至把网页端筛选出来的股票批量写入本地公式选股池。这些扩展都建立在今天提到的同一套联动框架上,先把地基打稳,后面加什么功能都不难。