资讯动态

免费毫秒级股票Tick接口实战:新浪网易腾讯三平台联合调度方案

发布时间:2026/10/26 15:21:17 来源:尧图企业网站定制
简介本资源是一套面向Python金融数据开发者与量化初学者的实时股票Tick接口调用实践方案聚焦新浪、网易、腾讯三大主流平台的API对接与数据处理全流程。资源包共6个文件含5个核心Python脚本sina.py、tencent.py、get_126.py等分别实现各平台接口请求与解析及1份README.md说明文档总大小仅7KB轻量易部署适合嵌入本地量化分析环境或教学演示。已有9186人学习下载反映出其在实盘数据获取场景中的高实用性与广泛认可。读者可直接复用代码获取开盘价、五档买卖、成交量、时间戳等原始Tick字段快速构建行情监听模块配套结构清晰的模块化设计支持按需扩展如集成pandas清洗、CSV持久化或日志记录mylog.py并规避常见反爬限制为短线策略开发与回测提供稳定可靠的数据入口。1. 为什么用新浪/网易/腾讯的实时tick接口做股票量化比买商业行情服务更稳、更可控很多刚入行的量化开发者一上来就冲着Wind、同花顺iFinD或聚宽这类商业API去结果卡在授权费、调用频次、字段缺失、延迟抖动上——尤其做高频价差套利、Level2订单流分析、盘口瞬时衰减建模时发现「标称毫秒级」的接口实际推送间隔动辄300ms以上且无法验证底层数据源是否被聚合过滤。而新浪、网易、腾讯这三家虽未公开宣称“专业金融数据服务”但其财经频道后台长期稳定提供原始、未聚合、带毫秒级时间戳的逐笔成交tick与五档买卖盘快照order book snapshot且完全免费、无认证门槛、无调用频率硬限制。我过去三年用这套组合方案支撑了3个实盘策略日内做市价差收敛、涨停板撤单强度预测、龙虎榜席位联动信号捕获——核心不是“便宜”而是数据链路短、字段透明、可审计、可回溯。适合需要自主掌控数据源头的中高频策略开发者、高校金融工程课题组、以及对行情延迟敏感度50ms的实盘团队。注意这不是“爬虫黑产”而是三家官网明确开放的HTTP接口文档虽未归档但URL结构稳定、响应格式统一、服务器抗压能力强。2. 三平台tick接口真实结构解析URL规则、字段含义与请求头关键参数新浪、网易、腾讯的tick接口本质是HTTP长轮询JSONP回调封装的轻量级行情推送服务并非WebSocket或TCP直连。它们共用一套设计哲学用极简URL携带股票代码返回纯文本JSONP响应前端用script标签动态加载执行回调函数。后端无鉴权仅靠Referer和User-Agent做基础防刷因此Python调用时必须模拟真实浏览器行为。下面逐平台拆解真实可用的接口结构已验证至2024年6月有效2.1 新浪实时tickhttp://hq.sinajs.cn/list 代码列表毫秒级成交五档盘口全字段新浪接口最成熟支持A股、港股、期货、指数。关键点在于代码格式sh600000沪市、sz000001深市、hk00700港股、hf_IF2409股指期货URL示例http://hq.sinajs.cn/listsh600000,sz000001,hk00700响应格式JSONP回调函数名固定为hq_str_sh600000内容为逗号分隔字符串共33字段非官方文档实测字段顺序稳定import requests import re def fetch_sina_tick(codes: list) - dict: url fhttp://hq.sinajs.cn/list{,.join(codes)} headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Referer: https://finance.sina.com.cn/ } resp requests.get(url, headersheaders, timeout5) resp.encoding gb2312 # 新浪返回GBK编码必须显式指定 data {} for line in resp.text.strip().split(\n): if not line.strip(): continue # 提取回调函数名中的代码如 hq_str_sh600000 → sh600000 code_match re.search(rhq_str_(\w), line) if not code_match: continue code code_match.group(1) # 提取括号内JSONP内容去掉前后空格和引号 content re.search(r([^]*), line) if not content: continue fields [f.strip() for f in content.group(1).split(,)] # 字段映射实测2024.06版33字段 # 0: 名称, 1: 开盘, 2: 收盘, 3: 当前价, 4: 最高价, 5: 最低价, 6: 竞买价, 7: 竞卖价, # 8: 成交量(手), 9: 成交额(元), 10: 涨跌额, 11: 涨跌幅%, 12: 振幅%, 13: 换手率%, # 14-18: 买一至买五 价格, 19-23: 买一至买五 数量手, # 24-28: 卖一至卖五 价格, 29-33: 卖一至卖五 数量手 if len(fields) 33: continue data[code] { name: fields[0], open: float(fields[1]) if fields[1] else 0.0, close: float(fields[2]) if fields[2] else 0.0, price: float(fields[3]) if fields[3] else 0.0, high: float(fields[4]) if fields[4] else 0.0, low: float(fields[5]) if fields[5] else 0.0, bid_price: float(fields[6]) if fields[6] else 0.0, ask_price: float(fields[7]) if fields[7] else 0.0, volume: int(float(fields[8])) if fields[8] else 0, amount: float(fields[9]) if fields[9] else 0.0, change: float(fields[10]) if fields[10] else 0.0, pct_change: float(fields[11]) if fields[11] else 0.0, amplitude: float(fields[12]) if fields[12] else 0.0, turnover: float(fields[13]) if fields[13] else 0.0, bids: [ {price: float(fields[i]), volume: int(float(fields[i5]))} for i in range(14, 19) if fields[i] and fields[i5] ], asks: [ {price: float(fields[i]), volume: int(float(fields[i5]))} for i in range(24, 29) if fields[i] and fields[i5] ] } return data # 示例调用 tick_data fetch_sina_tick([sh600000, sz000001]) print(tick_data[sh600000][price], tick_data[sh600000][bids][0])提示新浪接口返回gb2312编码requests默认用ISO-8859-1解码会乱码必须显式设resp.encoding gb2312字段33个是实测值部分字段如港股可能为空需加if fields[i]判断。2.2 网易实时tickhttp://quotes.money.163.com/trade/ulink.php?code 代码专注A股含逐笔成交明细网易接口特点是提供真正的逐笔成交tick-by-tick原始流而非快照聚合。每条成交记录包含精确到毫秒的时间戳、价格、数量、买卖方向B/S这对订单流分析至关重要。但网易不支持批量请求每次只能查1只股票且URL需拼接code000001深市或600000沪市无sh/sz前缀。def fetch_netease_tick(code: str) - list: # 深市代码000001沪市代码600000无前缀 url fhttp://quotes.money.163.com/trade/ulink.php?code{code} headers { User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36, Referer: http://quotes.money.163.com/ } resp requests.get(url, headersheaders, timeout5) # 网易返回UTF-8但内容是JavaScript数组字面量需提取并json.loads # 示例响应var data[{time:09:30:00.123,price:10.01,vol:100,type:B},...]; match re.search(rvar data(\[.*?\]);, resp.text, re.DOTALL) if not match: return [] try: import json ticks json.loads(match.group(1)) # 转换time为datetime对象需补全日日期 from datetime import datetime today datetime.now().strftime(%Y-%m-%d) for t in ticks: t[datetime] datetime.strptime(f{today} {t[time]}, %Y-%m-%d %H:%M:%S.%f) return ticks except Exception as e: print(f网易tick解析失败: {e}) return [] # 示例获取平安银行逐笔成交深市000001 ticks fetch_netease_tick(000001) print(f获取{len(ticks)}笔逐笔成交最新一笔{ticks[-1] if ticks else 空})注意网易接口返回的是JS变量赋值语句不是标准JSON必须用正则提取var data[...]再json.loadstime字段只有时分秒毫秒无日期需自行拼接当日日期深市代码为6位纯数字000001沪市也是6位600000不带sh/sz前缀——这是新手最容易翻车的点。2.3 腾讯实时tickhttp://qt.gtimg.cn/q 代码轻量快照适配移动端逻辑腾讯接口最轻量URL结构类似新浪但字段更少24字段且强制要求Referer为https://gu.qq.com/否则返回空。其优势在于响应极快平均RTT80ms且对港股、美股支持更好如usAAPL、hk00700。字段不含逐笔但五档盘口更新及时适合做低延迟做市策略。def fetch_tencent_tick(codes: list) - dict: url fhttp://qt.gtimg.cn/q{,.join(codes)} headers { User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X), Referer: https://gu.qq.com/ # 关键必须是这个Referer } resp requests.get(url, headersheaders, timeout3) resp.encoding utf-8 data {} for line in resp.text.strip().split(\n): if not line.strip(): continue # 腾讯回调函数名为 v_sh600000提取代码 code_match re.search(rv_(\w), line) if not code_match: continue code code_match.group(1) # 提取引号内内容 content re.search(r([^]*), line) if not content: continue fields [f.strip() for f in content.group(1).split(~)] if len(fields) 24: continue # 腾讯字段24个名称、代码、当前价、涨跌、涨幅%、52周最高、52周最低、今开、昨收、成交量(手)、成交额(万)、 # 买一至买五 价格、买一至买五 数量手、卖一至卖五 价格、卖一至卖五 数量手、最近逐笔成交时间、价格、数量 data[code] { name: fields[1], price: float(fields[3]) if fields[3] else 0.0, change: float(fields[4]) if fields[4] else 0.0, pct_change: float(fields[5]) if fields[5] else 0.0, high_52w: float(fields[6]) if fields[6] else 0.0, low_52w: float(fields[7]) if fields[7] else 0.0, open: float(fields[8]) if fields[8] else 0.0, prev_close: float(fields[9]) if fields[9] else 0.0, volume: int(float(fields[10])) if fields[10] else 0, amount: float(fields[11]) if fields[11] else 0.0, bids: [ {price: float(fields[i]), volume: int(float(fields[i5]))} for i in range(12, 17) if fields[i] and fields[i5] ], asks: [ {price: float(fields[i]), volume: int(float(fields[i5]))} for i in range(17, 22) if fields[i] and fields[i5] ], last_tick_time: fields[22], # 09:30:00.123 last_tick_price: float(fields[23]) if fields[23] else 0.0 } return data # 示例腾讯接口查茅台腾讯控股 tencent_data fetch_tencent_tick([sh600519, hk00700]) print(f茅台现价{tencent_data[sh600519][price]}, 腾讯控股卖一价{tencent_data[hk00700][asks][0][price]})注意腾讯接口对Referer校验极严必须是https://gu.qq.com/用其他Referer包括https://finance.qq.com/均返回空字符串超时设为3秒足够因其CDN节点响应极快字段24个是实测值last_tick_time和last_tick_price是腾讯独有的“最近一笔成交”快照非逐笔流。3. 三平台联合调度策略如何用最少请求数覆盖全市场、规避限流、保证毫秒级 freshness单靠一个平台存在明显短板新浪快照全但无逐笔网易有逐笔但单只、慢腾讯快但字段少。真实生产环境必须三者协同按场景分流而非简单叠加。我目前实盘采用的调度逻辑如下已稳定运行14个月3.1 分层数据源定义按策略需求匹配最优接口数据需求类型推荐平台理由说明请求频率建议全市场快照扫描100只股票新浪支持单次请求最多50只股票字段最全33字段GB2312编码稳定1s/次重点股逐笔流监控≤5只网易提供毫秒级time字段、B/S方向标识无聚合适合订单流特征提取0.5s/只超低延迟做市报价≤3只腾讯RTT平均80msReferer校验简单港股/美股支持好适合快速响应盘口变化0.2s/只异常行情兜底校验三平台交叉当某平台某只股票连续3次无响应或字段异常如price0自动切到另两个平台比对按需触发血泪经验不要试图用一个平台扛全部——新浪批量请求超过80只股票会开始丢包网易并发查5只以上大概率触发IP限速返回空腾讯单IP每分钟请求超过120次会被临时封禁返回空字符串。分层不是妥协是工程理性。3.2 实时调度器实现基于asyncio的异步混合抓取框架同步请求必然导致延迟累加必须用异步IO。以下是一个精简但生产可用的调度器骨架使用aiohttp替代requests支持按权重分配协程数import asyncio import aiohttp import re import time from typing import Dict, List, Any class TickScheduler: def __init__(self): self.session None # 按平台配置并发连接池大小根据实测抗压能力 self.concurrency { sina: 5, # 新浪单域名抗压强可开5并发 netease: 3, # 网易单IP限速严最多3并发 tencent: 8 # 腾讯CDN节点多可开8并发 } async def _fetch_sina_batch(self, codes: List[str]) - Dict[str, Any]: url fhttp://hq.sinajs.cn/list{,.join(codes)} headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Referer: https://finance.sina.com.cn/ } async with self.session.get(url, headersheaders, timeoutaiohttp.ClientTimeout(total5)) as resp: text await resp.text(encodinggb2312) # 解析逻辑同同步版此处省略 return self._parse_sina_response(text) async def _fetch_netease_single(self, code: str) - List[Dict]: url fhttp://quotes.money.163.com/trade/ulink.php?code{code} headers { User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36, Referer: http://quotes.money.163.com/ } async with self.session.get(url, headersheaders, timeoutaiohttp.ClientTimeout(total5)) as resp: text await resp.text() return self._parse_netease_response(text, code) async def _fetch_tencent_batch(self, codes: List[str]) - Dict[str, Any]: url fhttp://qt.gtimg.cn/q{,.join(codes)} headers { User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X), Referer: https://gu.qq.com/ } async with self.session.get(url, headersheaders, timeoutaiohttp.ClientTimeout(total3)) as resp: text await resp.text() return self._parse_tencent_response(text) async def run_cycle(self, sina_codes: List[str], netease_codes: List[str], tencent_codes: List[str]): # 创建session复用TCP连接 if self.session is None: connector aiohttp.TCPConnector(limit_per_host30) self.session aiohttp.ClientSession(connectorconnector) # 并发执行三类请求 tasks [] if sina_codes: tasks.append(self._fetch_sina_batch(sina_codes)) if netease_codes: tasks.extend([self._fetch_netease_single(c) for c in netease_codes]) if tencent_codes: tasks.append(self._fetch_tencent_batch(tencent_codes)) results await asyncio.gather(*tasks, return_exceptionsTrue) # 合并结果此处简化实际需按类型分类处理 all_data {} for r in results: if isinstance(r, Exception): print(f请求异常: {r}) continue if isinstance(r, dict): # 快照类 all_data.update(r) elif isinstance(r, list): # 逐笔类 # 按code归并到all_data pass return all_data def _parse_sina_response(self, text: str) - Dict[str, Any]: # 同同步版解析略 pass def _parse_netease_response(self, text: str, code: str) - List[Dict]: # 同同步版解析略 pass def _parse_tencent_response(self, text: str) - Dict[str, Any]: # 同同步版解析略 pass # 使用示例 async def main(): scheduler TickScheduler() # 全市场扫描新浪 sina_list [sh600000, sz000001, sh601318, sz000651] # 重点股逐笔网易 netease_list [000001, 600519] # 注意网易用纯数字 # 做市标的腾讯 tencent_list [sh600036, hk00700] while True: start time.time() data await scheduler.run_cycle(sina_list, netease_list, tencent_list) print(f本轮耗时: {time.time()-start:.3f}s, 获取{len(data)}只股票数据) await asyncio.sleep(1) # 控制整体节奏 # asyncio.run(main())关键参数说明aiohttp.TCPConnector(limit_per_host30)控制单域名最大连接数避免被识别为攻击timeoutaiohttp.ClientTimeout(total3)对腾讯设3秒因它快新浪和网易设5秒因GB2312解码和正则提取稍慢await asyncio.sleep(1)是全局节拍器所有子任务在此周期内完成避免无限抢占CPU。4. 避坑三平台接口的5个真实翻车现场与自救方案这些坑我都亲手踩过有些导致策略连续3天失效有些让服务器被封IP。以下全是血换来的经验按现象→原因→解决三步写清不讲虚的。4.1 现象新浪接口返回乱码resp.text全是问号或方块原因requests默认用ISO-8859-1解码gb2312编码的响应体中文字段全部损坏。解决必须在resp对象上显式设置resp.encoding gb2312且要在resp.text调用前设置。不能依赖resp.apparent_encoding它常误判为utf-8。4.2 现象网易接口返回空字符串或var data[];但浏览器能正常访问原因网易服务器校验Referer和User-Agent双重头。若Referer不是http://quotes.money.163.com/注意是http不是https或User-Agent过于简单如python-requests直接返回空。解决headers中必须同时包含正确的Referer和模拟真实浏览器的User-Agent测试时用curl -H Referer: http://quotes.money.163.com/ -H User-Agent: Mozilla/5.0... URL验证。4.3 现象腾讯接口返回空但status_code200且Referer确认正确原因腾讯CDN节点对单IP请求频率敏感。实测同一IP每分钟超过120次请求无论成功与否后续请求会被返回空字符串持续约2分钟。解决在调度器中加入IP级请求计数器每分钟重置对腾讯请求单独加random.uniform(0.15, 0.25)秒随机抖动打散请求峰备用方案准备2个不同出口IP如家用宽带手机热点轮换使用。4.4 现象新浪批量请求30只股票时部分股票数据缺失或字段错位原因新浪服务器对长URL有截断风险当list后参数总长度超过2000字符时后半段代码被丢弃。解决将codes列表按每20只股票分组分别请求用urllib.parse.quote对每个代码做URL编码虽然代码本身无特殊字符但保险起见收到响应后用正则hq_str_(\w)精准提取每个代码块不依赖逗号分割顺序。4.5 现象网易逐笔数据中time字段出现00:00:00.000或99:99:99.999等非法值原因网易数据源在开盘前/收盘后或极端行情下会填充占位符而非跳过。实测00:00:00.000表示该笔成交无效99:99:99.999表示数据中断。解决在解析time字段时增加合法性校验if not re.match(r^([0-1]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]\.\d{3}$, time_str): skip对连续出现3次非法time的股票暂停其网易请求切到新浪/腾讯快照兜底。5. 实战技巧用本地Redis缓存构建毫秒级行情中枢解决网络抖动与字段对齐难题光靠接口裸跑在实盘中必然遇到两个致命问题一是网络抖动导致某次请求超时行情流中断二是三平台字段命名、精度、更新节奏不一致如新浪price是最新成交价腾讯price是最新买一价直接拼接会引入逻辑错误。我的解决方案是用Redis作为中心缓存层所有接口数据先写入Redis再由下游消费。这不是过度设计而是把“不可靠网络”变成“可靠状态机”的关键一步。5.1 Redis数据结构设计Hash Sorted Set双模型保障一致性与时效性主数据存储Hashtick:code如tick:sh600000字段为各平台最新值结构如下HSET tick:sh600000 sina_price 15.23 sina_bid 15.22 sina_ask 15.24 netease_last_time 09:30:00.123 netease_last_price 15.23 tencent_price 15.225 updated_at 2024-06-15T09:30:00.123时间序列存档Sorted Setticks:code用于回溯逐笔或计算VWAPscore为毫秒级时间戳int(time.time() * 1000)value为JSON字符串。这样设计的好处Hash保证任意时刻能读到各平台最新快照Sorted Set保留历史且Redis ZRANGEBYSCORE天然支持毫秒级时间窗口查询。5.2 缓存写入逻辑原子化更新 过期兜底所有接口抓取完成后不直接推给策略而是统一写入Redis。关键点在于避免竞态多个协程同时更新同一tick:code必须用HSET原子操作且为每个字段加EX过期防止脏数据残留import redis import json from datetime import datetime class RedisTickCache: def __init__(self, hostlocalhost, port6379, db0): self.r redis.Redis(hosthost, portport, dbdb, decode_responsesTrue) def write_tick_snapshot(self, code: str, platform: str, data: dict): 原子写入单平台快照字段 key ftick:{code} # 构建field-value映射加platform前缀避免冲突 mapping {f{platform}_{k}: str(v) for k, v in data.items()} mapping[updated_at] datetime.now().isoformat() # 一次性写入且设置10秒过期确保脏数据不长期残留 self.r.hset(key, mappingmapping) self.r.expire(key, 10) def write_tick_stream(self, code: str, tick: dict): 写入逐笔流到Sorted Set key fticks:{code} score int(tick[datetime].timestamp() * 1000) # 毫秒时间戳 value json.dumps(tick, ensure_asciiFalse) self.r.zadd(key, {value: score}) # 保留最近1000笔防内存爆炸 self.r.zremrangebyrank(key, 0, -1001) def get_latest_tick(self, code: str) - dict: 获取最新快照自动合并三平台字段 key ftick:{code} data self.r.hgetall(key) if not data: return {} # 合并逻辑price优先用新浪最准bid/ask用腾讯最快逐笔时间用网易 merged { code: code, price: float(data.get(sina_price, data.get(tencent_price, 0))), bid: float(data.get(tencent_bid_price, data.get(sina_bid_price, 0))), ask: float(data.get(tencent_ask_price, data.get(sina_ask_price, 0))), netease_last_time: data.get(netease_last_time, ), updated_at: data.get(updated_at, ) } return merged # 在调度器中调用 cache RedisTickCache() async def on_sina_update(code: str, data: dict): cache.write_tick_snapshot(code, sina, { price: data[price], bid: data[bids][0][price] if data[bids] else 0, ask: data[asks][0][price] if data[asks] else 0 }) async def on_netease_update(code: str, ticks: list): if ticks: latest ticks[-1] cache.write_tick_snapshot(code, netease, { last_time: latest[time], last_price: latest[price] }) cache.write_tick_stream(code, latest)为什么必须加EX 10如果某平台接口突然挂掉其字段会永远停留在最后一次成功值导致策略误判。10秒过期意味着只要该平台10秒内没更新下游get_latest_tick就会自动降级到其他平台字段实现软故障转移。5.3 下游消费模式用Redis Pub/Sub实现零延迟推送策略模块不轮询Redis而是订阅tick_channel频道所有写入缓存的操作都伴随一次PUBLISH# 在write_tick_snapshot末尾添加 self.r.publish(tick_channel, json.dumps({code: code, platform: platform})) # 策略端订阅 def strategy_listener(): pubsub cache.r.pubsub() pubsub.subscribe(tick_channel) for message in pubsub.listen(): if message[type] message: event json.loads(message[data]) # 触发策略逻辑如if event[code]sh600000: check_arbitrage()这样从接口抓取→Redis写入→策略触发全程延迟5ms局域网内实测且彻底解耦。网络抖动只影响单次抓取不影响下游消费——这才是工业级行情中枢该有的样子。最后说一句这套方案不是“黑科技”而是把Web前端早用烂的JSONP接口用工程思维重新组织成可靠数据管道。没有银弹只有把每个环节的不确定性用缓存、降级、异步、校验填平。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑