金十数据 Websocket 接口

目标地址

金十数据中心-行情中心

接口描述

该接口为 websocket 接口,主要用于获取:股市、外汇、商品、工行、农行的行情数据

过程分析

pic_1

上图中有个 sid 是需要分析获取的

pic_2

分析出可以通过上述地址来获取 sid,但是随着而来的问题是其中的 t 表面上应该是时间,但是却是字符串的形式,应该是加密导致的。

那么就需要分析 t 是怎么生成的,因为发现 t=NB 经常出现,所以

pic_3

发现其中的 this.uri,那么就搜 uri 这个参数

pic_4

把 c() 在 console 中运行,发现是相关的参数,则查找 c 的生成方法

pic_5

然后查找 r,发现

pic_6

找出 s 后,利用 execjs 来执行本段代码,可以模拟出 t 这个参数值。

pic_7

用 session = requests.Session() 来获取对话 session,再依次访问上述的连接。其中

pic_8

中的 Request Payload 直接使用字符串 post 上去就可以了,注意不用有空格,返回 ok 就成功。

最后连接用 websocket 来访问就好了,下面附上源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
import json
import time
from threading import Timer, Event, Thread

import requests
import websocket
import execjs


quotes_js = """
t = +new Date
function n(t) {
var e = "";
var a = 64;
var s = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "-", "_"];
do {
e = s[t % a] + e,
t = Math.floor(t / a)
} while (t > 0);return e
}
function j() {return n(t)}
"""

js_code = execjs.compile(quotes_js)
js_code.call("j", "") # 执行js解密代码


def _get_sid() -> str:
"""
XHR 监听 sid
需要动态获取sid, 拼接后访问
https://www.jb51.net/article/149738.htm
用轮询获取 sid 用 sid 请求
:return: sid 内容
:rtype: str
"""
session = requests.Session()
url = "https://dc-quote-old.jin10.com/socket.io/"
params = {
"EIO": "3",
"transport": "polling",
"t": js_code.call("j", ""),
}
headers = {
"accept": "*/*",
"accept-encoding": "gzip, deflate, br",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8",
"cache-control": "no-cache",
"origin": "https://datacenter.jin10.com",
"pragma": "no-cache",
"referer": "https://datacenter.jin10.com/price_wall",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-site",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
}
r = session.get(url, params=params, headers=headers)
data_text = r.text
data_json = json.loads(data_text[data_text.find("{"):])

url = "https://dc-quote-old.jin10.com/socket.io/"
params = {
"EIO": "3",
"transport": "polling",
"t": js_code.call("j", ""),
"sid": data_json["sid"],
}
session.get(url, params=params)

url = "https://dc-quote-old.jin10.com/socket.io/"
params = {
"EIO": "3",
"transport": "polling",
"t": js_code.call("j", ""),
"sid": data_json["sid"],
}
headers = {
"content-type": "text/plain;charset=UTF-8",
}
data = """1203:42["setAdvSubscription",{"list":["SH1A0001","SZ399001","SH000300","SZ399006","DJI","SPX","GSPTSE","BVSP","MXX","GDAXI","FTSE","FCHI","AEX","IBEX","FTMIB","SSMI","MCX","IRTS","XU100","TA25","TASI","N225","AXJO","HSI","TWII","KS11","JKSE","NSEI","BSESN","DXY","AUDJPY","AUDNZD","AUDUSD","EURAUD","EURCAD","EURCHF","EURGBP","EURJPY","EURNZD","EURUSD","GBPCHF","GBPJPY","GBPUSD","NZDJPY","NZDUSD","USDCAD","USDCHF","USDHKD","USDJPY","AUDCAD","AUDCHF","CADCHF","CADJPY","CHFJPY","EURNOK","EURSEK","EURTRY","GBPAUD","GBPCAD","GBPNZD","NZDCAD","NZDCHF","TRYJPY","USDCNH","USDMXN","USDNOK","USDSEK","USDTRY","USDZAR","ZARJPY","XAUUSD","XAGUSD","USOIL","UKOIL","COPPER","NGAS","BUND","AUTD","AGTD","XPTUSD","XPDUSD","ICNYXAU","ICNYXAG","ICNYXPT","ICNYXPD","IUSDXAU","IUSDXAG","IUSDXPT","IUSDXPD","ICNYWTI","ICNYBRENT","IUSDWTI","IUSDBRENT","ICNYGAS","IUSDGAS","IUSDBRENT1703","ICNYBRENT1703","IUSDWTI1703","ICNYWTI1703","ICNYSOYBEAN1703","IUSDSOYBEAN1703","IUSDCOPPER1703","ICNYCOPPER1703","IEUR","IGBP","IAUD","ICAD","ICHF","IJPY","INZD","ISGD","INOK","ISEK","IGBPUSD","IUSDHKD","IUSDCHF","IUSDSGD","IUSDSEK","IUSDNOK","IUSDJPY","IUSDCAD","IAUDUSD","IEURUSD","INZDUSD","ACNYXAU","ACNYXAG","AUSDXAU","AUSDXAG"]}]"""
# data = """1203:42["setAdvSubscription",{"list":["SH1A0001","SZ399001","SH000300","SZ399006"]}]"""
session.post(url, params=params, data=data, headers=headers)

url = "https://dc-quote-old.jin10.com/socket.io/"
params = {
"EIO": "3",
"transport": "polling",
"t": js_code.call("j", ""),
"sid": data_json["sid"],
}
session.get(url, params=params)

url = "https://dc-quote-old.jin10.com/socket.io/"
params = {
"EIO": "3",
"transport": "polling",
"t": js_code.call("j", ""),
"sid": data_json["sid"],
}
session.get(url, params=params)

return data_json["sid"]


class HeartbeatThread(Thread):
"""
心跳
"""
def __init__(self, event, ws):
super(HeartbeatThread, self).__init__()
self.event = event
self.ws = ws

def run(self):
while True:
# 发送ping包
self.ws.send("2")
self.event.wait(timeout=2)


def on_message(ws, message):
"""
接收信息, 如果要存数据需要在这里处理
:param ws:
:type ws:
:param message:
:type message:
:return:
:rtype:
"""
print(message)


def on_error(ws, error):
"""

:param ws:
:type ws:
:param error:
:type error:
:return:
:rtype:
"""
print(error)


def on_close(ws):
"""
:param ws:
:type ws:
:return:
:rtype:
"""
print("### closed ###")


def on_open(ws):
"""
请求连接
:param ws:
:type ws:
:return:
:rtype:
"""
ws.send("2probe")
time.sleep(0.5) # 发送第二次需要短暂暂停
ws.send("5") # 发送字符串 5 来完成握手


def on_emit(ws):
"""
创建心跳线程
:param ws: object
:type ws: websocket object
:return: None
:rtype: None
"""
event = Event()
heartbeat = HeartbeatThread(event, ws)
heartbeat.start()


def watch_jinshi():

websocket.enableTrace(False)
ws = websocket.WebSocketApp(
f"wss://dc-quote-old.jin10.com/socket.io/?EIO=3&transport=websocket&sid={_get_sid()}",
on_message=on_message,
on_error=on_error,
on_close=on_close
)
ws.on_open = on_open
t = Timer(20, on_emit, args=(ws,))
t.start()
ws.run_forever()


if __name__ == "__main__":
watch_jinshi()

How to publish my personal website on coding.net

Login Page

jindaxiang.coding.net

Find Item

项目 -> jindaxiang -> 持续部署 -> 静态网页 -> 设置 -> 自定义域名 -> Warning -> 申请 -> 在阿里云重启 GitHub 的解析

Warning

阿里云 -> 域名 -> 解析 -> 暂停 GitHub 的解析

Frequency

每月一次

Attention

If you are old customer of coding.net, so you have to update _config.yml file with conding site object

bind www.jfds.xyz

  1. 先在阿里云添加主机记录,按照 coding 绑定 www.jfds.xyz 域名那块的提示
  2. 再次绑定 www.jfds.xyz 域名
  3. Https 勾选 -> 保存 -> 部署网站

《HelloGitHub》第 47 期

兴趣是最好的老师,HelloGitHub 就是帮你找到兴趣!

简介

分享 GitHub 上有趣、入门级的开源项目。

这是一个面向编程新手热爱编程对开源社区感兴趣 人群的月刊,月刊的内容包括:各种编程语言的项目让生活变得更美好的工具书籍、学习笔记、教程等,这些开源项目大多都是非常容易上手,而且非常 Cool。主要是希望大家能动手用起来,加入到开源社区中。

  • 会编程的可以贡献代码
  • 不会编程的可以反馈使用这些工具中的 Bug
  • 帮着宣传你觉得优秀的项目
  • Star 项目⭐️

在浏览、参与这些项目的过程中,你将学习到更多编程知识提高编程技巧找到编程的乐趣

🎉 最后 HelloGitHub 这个项目就诞生了 🎉

目录

Tips:如果文中的图刷不出来,可以向我们反馈。也可以访问 官网 获取更好的阅读体验。


欢迎关注 HelloGitHub 公众号

内容

以下为本期内容|每个月 28 号发布最新一期

C++ 项目

1、modern-cpp-features:该项目介绍了现代 C++(C++11 以及之后的版本)语言和库的新特性。它能够帮助大家更快地入手新时代的 C++

2、CPlusPlusThings:这是一个适合 C++ 初学者从入门到进阶的教程。解决了面试者想要深入 C++ 及如何入坑 C++ 的问题。除此之外,该仓库拓展了更加深入的语法分析、多线程并发等的知识,是一个比较全面的 C++ 从入门学习到进阶提升的项目

🔙 返回目录 🔙


Go 项目

3、7days-golang:用 Go 在 7 天时间内实现 Web 框架、分布式缓存等应用的实战教程

4、cli:GitHub 官方基于 Go 语言开发的命令行 GitHub 工具。用它可以在终端中执行 GitHub 的常用的管理 Issue、切分支、Clone 等操作

🔙 返回目录 🔙


Java 项目

5、FXGLGames:此项目包含 FXGL 框架构建的游戏示例。该游戏框架无需安装或设置开箱即用,游戏可以轻松打包到单个可执行文件.jar。示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
public class BasicGameApp extends GameApplication {
@Override
protected void initSettings(GameSettings settings) {
settings.setWidth(800);
settings.setHeight(600);
settings.setTitle("Basic Game App");
}

public static void main(String[] args) {
launch(args);
}
}

6、quarkus-quickstarts:Quarkus 开源的 Java 多种框架 demo 项目集合。这些示例项目可以快速启动、结构清晰,初学者可用作 Java 的实战项目,老手可以当作项目脚手架。启动示例:

1
2
3
mvn quarkus:dev
mvn clean package -Pnative
./target/amqp-quickstart-1.0-SNAPSHOT-runner

🔙 返回目录 🔙


JavaScript 项目

7、showdoc:一款基于 JavaScript 实现的开源在线文档工具。支持:多端编辑查看、权限管理、文档导出、Markdown 语法等,功能虽不多但已足够用了。推荐自建自用、小团队内部使用

8、qier-progress:这是一个用于缓解用户焦虑,给予用户请求回馈的顶部进度条。该项目使用 ts 重构了万星 star 的 nprogress 项目,打包体积更小、且支持了多彩模式、自定义高度和颜色等,最重要的是有良好的类型注解。该项目结构简单、代码量也比较少,非常利于学习 ts 相关用法和作为实战项目。示例代码:

1
2
3
const qprogress = new QProgress()
qprogress.start()
qprogress.finish()

9、image-compress-without-backend:一个纯前端在线图片压缩小工具。即无需上传照片到服务器,一切都在浏览器端完成,快速而高效。非常适用于图片压缩后质量要求不是很高的场景,比如:移动端图片展示等

10、breathe-relaxer:一个在线放松网站的项目。带上耳机,点开网站然后深呼吸

11、wx-promise-pro:支持 finnaly、typescript 的微信小程序异步解决方案。特性:

  • 方便集成:一处引用,处处使用
  • 把微信小程序所有异步 API promise 化并挂在到 wx.pro 对象下
  • 支持 ES2018 finally 特性
  • 支持 TypeScript 开发
1
2
3
4
5
import { promisifyAll, promisify } from 'wx-promise-pro'
// promisify all wx‘s api
promisifyAll()
// promisify single api
promisify(wx.getSystemInfo)().then(console.log)

🔙 返回目录 🔙


Objective-C 项目

12、simplenote-macos:一款 macOS 上免费开源的记事本应用

🔙 返回目录 🔙


PHP 项目

13、clean-code-php:PHP 代码的整洁之道,整理了一系列整洁代码实操。小到变量细道 SOLID 都有涉猎,中文译版

14、ext-collections:一个 C 语言实现的 PHP 扩展库。提供了类似 Java stream API 和 kotlin.collections 的一系列库函数,方便开发者优雅、快速地操作 PHP 数组。

  • 提供了丰富的 PHP 数组操作函数,有助于提高开发效率和代码的可读性
  • 使用 C 语言实现,比同类 PHP 实现性能更高
  • 初学者可以通过阅读此项目代码帮助自己入门 PHP 扩展开发
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$employees = [
['name' => 'Alice', 'sex' => 'female', 'age' => 35],
['name' => 'Bob', 'sex' => 'male', 'age' => 29],
['name' => 'David', 'sex' => 'male', 'age' => 40],
['name' => 'Benjamin', 'sex' => 'male', 'age' => 32]
];
// Trying to get an array of names of male employees,
// sorted by the descending order of their age.
$names = Collection::init($employees)
->filter(function ($value) {
return $value['sex'] == 'male';
})
->sortedByDescending(function ($value) {
return $value['age'];
})
->map(function ($value) {
return $value['name'];
})
->toArray();
// You got $names == ['David', 'Benjamin', 'Bob'].

🔙 返回目录 🔙


Python 项目

15、wttr.in:一个 Python 实现的命令行查看天气工具

16、activitywatch:一个记录你的时间都花在那的 Python 项目。支持 Web 可视化,效果如下

17、akshare:一款基于 Python 的开源金融数据接口库。提供了股票、期货、期权、基金、数字货币等金融产品的基本数据、实时和历史行情数据、衍生数据,包含数据采集、数据清洗、到数据落地的一套开源工具。满足了金融数据科学家、数据科学爱好者在金融数据获取方面的需求。示例代码:

1
2
3
4
5
6
7
8
9
10
import akshare as ak
bond_df = ak.bond_spot_deal()
print(bond_df)

债券简称 成交净价(元) 最新收益率(%) 涨跌(BP) 加权收益率(%) 交易量(亿)
0 19国开15 98.97 3.5750 1.00 3.5826 None
1 19附息国债03 99.82 2.7714 0.14 2.7772 None
2 19附息国债11 99.87 2.8000 0.25 2.7963 None
3 19附息国债04 100.82 2.9832 -1.54 2.9747 None
4 15附息国债05 102.95 3.0359 -1.41 3.0359 None

18、repoll:基于 Django 开发的 redis 集群管理、监控工具。功能包括:标准化申请流程、管理配置、监控接口等,减轻了运维人员的痛苦

🔙 返回目录 🔙


Swift 项目

19、Mos:一个用于在 macOS 上平滑鼠标滚动效果或单独设置滚动方向的小工具。让你的滚轮爽如触控板般丝滑

🔙 返回目录 🔙


其它

20、devops-exercises:这个仓库包含了 DevOps(开发运维)常见、流行服务相关的面试问题和回答,推荐给从事运维的同学

21、book:《Rust 编程语言》这是官方出品的关于 Rust 的入门书籍

22、OnlineToolsBook:该项目收集了一些有趣、实用的在线工具网站,点开即用

23、my-mac-os:该项目罗列了作者自用、收集的 macOS 上实用、炫酷的软件。我从中找到好几个炫酷、实用提高工作的工具,你也赶快来挑挑吧

24、structured-text-tools:用于处理结构化文本数据(日志、JSON、YAML 等)的命令行工具列表

25、incubator-apisix:一个云原生、高性能、可扩展的微服务 API 网关。它是基于 Nginx 和 etcd 来实现,和传统 API 网关相比,APISIX 具备动态路由和插件热加载,适合微服务体系下的 API 管理

26、app-ideas:该收集了各类应用的想法,并按照易学程度把应用进行划分。你可以通过这个项目提高编程技术、学习新技术

🔙 返回目录 🔙


开源书籍

27、cookbook-2nd:《IPython Cookbook 第二版》

🔙 返回目录 🔙


机器学习

28、google-research:非官方整理的 Google AI Research 集合项目

29、Retinanet-Pytorch:一个以 Pytorch 深度学习库实现的 retinanet 目标检测模型。项目拥有清晰的结构、完善的注释以及详细的使用说明。适用于有些许深度学习基础的初学者进行学习或在实际的目标检测项目中使用

🔙 返回目录 🔙


『上一期』 | 反馈和建议 | 『下一期』


看完了,还不够?<科技爱好者周刊>。还不过瘾,那就看看 <往期内容>吧。
点击分享发现的有趣项目

声明

知识共享许可协议
本作品采用 署名-非商业性使用-禁止演绎 4.0 国际 进行许可。