RPC技术 学习目标:
了解 websocket
协议
熟悉 websocket
实现原理
掌握 RPC
启用和注入方式
RPC,英文 RangPaCong,中文让爬虫,旨在为爬虫开路,秒杀一切,让爬虫畅通无阻!
WebSocket的出现,使得浏览器具备了实时双向通信的能力。
参考:https://blog.csdn.net/zyym9009/article/details/104203995
参考:https://www.cnblogs.com/chyingp/p/websocket-deep-in.html
一. websocket 1. 什么是websocket
WebSocket是HTML5下一种新的协议(websocket协议本质上是一个基于tcp的协议)
它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的
Websocket是一个持久化 的协议
2. websocket的原理
websocket约定了一个通信的规范,通过一个握手的机制,客户端和服务器之间能建立一个类似tcp的连接,从而方便它们之间的通信
在websocket出现之前,web交互一般是基于http协议的短连接或者长连接
websocket是一种全新的协议,不属于http无状态协议,协议名为”ws”
总结(总体过程):
首先,客户端发起http请求,经过3次握手后,建立起TCP连接;http请求里存放WebSocket支持的版本号等信息,如:Upgrade、Connection、WebSocket-Version等;
然后,服务器收到客户端的握手请求后,同样采用HTTP协议回馈数据;
最后,客户端收到连接成功的消息后,开始借助于TCP传输信道进行全双工通信。
3. websocket实现方式 1. 客户端 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 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > <input id ="box" type ="text" > <button onclick ="ps()" > 发送</button > <script > const websocket = new WebSocket('ws://127.0.0.1:8080/' ) websocket.onerror = () => { console .log("WebSocket连接发生错误" ); }; websocket.onopen = function ( ) { console .log("WebSocket连接成功" ); } websocket.onmessage = function (event ) { console .log(event.data); } websocket.onclose = function ( ) { console .log("WebSocket连接关闭" ); } function ps ( ) { var text = document .getElementById('box' ).value websocket.send(text) } </script > </body > </html >
2.服务端 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 import asyncioimport websocketsasync def echo (websocket ): message = 'hello world' await websocket.send(message) return True async def recv_msg (websocket ): while 1 : recv_text = await websocket.recv() print (recv_text) async def main_logic (websocket, path ): await echo(websocket) await recv_msg(websocket) start_server = websockets.serve(main_logic, '127.0.0.1' , 8080 ) loop = asyncio.get_event_loop() loop.run_until_complete(start_server) loop.run_forever()
3. 实际案例 1. 案例目标
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 !(function () { if (window.flag) { } else { const websocket = new WebSocket('ws://127.0.0.1:8080') // 创建一个标记用来判断是否创建套接字 window.flag = true; // 接收服务端发送的信息 websocket.onmessage = function (event) { var data = event.data // 调用js解密 var res = b(data) console.log(res) // 发送解密数据给服务端 websocket.send(res) } } }())
2. 解析思路
定位到加密位置
将我们写的websocket
命令注入到代码当中(通过替换的方式实现)
注入之后需要刷新页面才能把js 执行起来
python执行代码
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 import asyncioimport websocketsimport requestsimport timeimport jsondef get_data (page ): headers = { "v" : "231012" , "Referer" : "https://jzsc.mohurd.gov.cn/data/company" , "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36" , } url = "https://jzsc.mohurd.gov.cn/APi/webApi/dataservice/query/comp/list" params = { "pg" : page, "pgsz" : "15" , "total" : "450" } response = requests.get(url, headers=headers, params=params) print (response.text) return response.text async def echo (websocket ): for i in range (1 , 4 ): data = get_data(i) await websocket.send(data) async def recv_msg (websocket ): while 1 : recv_text = await websocket.recv() print (json.loads(recv_text)) async def main_logic (websocket, path ): await echo(websocket) await recv_msg(websocket) start_server = websockets.serve(main_logic, '127.0.0.1' , 8080 ) loop = asyncio.get_event_loop() loop.run_until_complete(start_server) loop.run_forever()
二. RPC 1. RPC 简介
为什么要使用RPC技术呢?我们在使用websocket时候可以发现,python在操作的时候,需要创建连接,还需要不断去接受传递数据,非常的麻烦, 那这个时候rpc技术可以帮助到我们,简单来说就是网页直接和rpc服务器进行交互,我们python可以直接调用,rpc暴露的接口,不需要关心,创建连接这一块的问题.
RPC 技术是非常复杂的,叫做远程调用方法,简而言之就是我在一个进程当中想调用另外一个进程的方法,就可以通过网络通讯方式,也被称为rpc(应用场景,微服务,分布式,远程调用),对于我们搞爬虫、逆向的来说,不需要完全了解,只需要知道这项技术如何在逆向中应用就行了。
RPC 在逆向中,简单来说就是将本地和浏览器,看做是服务端和客户端,二者之间通过 WebSocket
协议进行 RPC
通信,在浏览器中将加密函数暴露出来,在本地直接调用浏览器中对应的加密函数,从而得到加密结果,不必去在意函数具体的执行逻辑,也省去了扣代码、补环境等操作,可以省去大量的逆向调试时间。
2.Sekiro-RPC
1. 使用方法 1. 执行方式
2.客户端环境
3.使用参数说明
使用原理:客户端注入到浏览器环境,然后通过SekiroClient
和 Sekiro
服务器通信,即可直接 RPC
调用浏览器内部方法,官方提供的 SekiroClient
代码样例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 function guid ( ) { function S4 ( ) { return (((1 +Math .random())*0x10000 )|0 ).toString(16 ).substring(1 ); } return (S4()+S4()+"-" +S4()+"-" +S4()+"-" +S4()+"-" +S4()+S4()+S4()); } var client = new SekiroClient("ws://127.0.0.1:5620/business-demo/register?group=ws-group&clientId=" +guid());client.registerAction("登陆" ,function (request, resolve, reject ) { resolve("" +new Date ()); })
group :业务类型(接口组),每个业务一个 group
,group
下面可以注册多个终端(SekiroClient
),同时group
可以挂载多个 Action
;
clientId :指代设备,多个设备使用多个机器提供 API
服务,提供群控能力和负载均衡能力;
SekiroClient :服务提供者客户端,主要场景为手机/浏览器等。最终的 Sekiro
调用会转发到 SekiroClient
。每个 client
需要有一个惟一的 clientId
;
registerAction :接口,同一个 group
下面可以有多个接口,分别做不同的功能;
resolve :将内容传回给服务端的方法;
request :服务端传过来的请求,如果请求里有多个参数,可以以键值对的方式从里面提取参数然后再做处理。
2. 测试使用 1. 前端代码 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 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > <script src ="http://file.virjar.com/sekiro_web_client.js?_=123" > </script > <script > function guid ( ) { function S4 ( ) { return (((1 + Math .random()) * 0x10000 ) | 0 ).toString(16 ).substring(1 ); } return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4()); } var client = new SekiroClient("ws://127.0.0.1:5620/business-demo/register?group=rpc-test&clientId=" + guid()); client.registerAction("clientTime" , function (request, resolve, reject ) { resolve("" + new Date ()); }) </script > </body > </html >
2. SK API Sekiro
为我们提供了一些 API
3.python
调用代码 1 2 3 4 5 6 7 8 9 import requestsparams = { "group" : "rpc-test" , "action" : "clientTime" , } res = requests.get("http://127.0.0.1:5620/business-demo/invoke" , params=params) print (res.text)
三.项目实战 1. 替换文件注入案例1 1. 逆向目标
2.定位cookie加密位置 1 2 3 4 5 6 7 8 9 10 11 (function () { Object.defineProperty(document, 'cookie', { set: function (val) { if (val.indexOf('v') != -1) { debugger; } console.log('Hook捕获到cookie设置->', val); return val; } }); })();
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 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 (function ( ) { function SekiroClient (wsURL ) { this .wsURL = wsURL; this .handlers = {}; this .socket = {}; this .base64 = false ; if (!wsURL) { throw new Error ('wsURL can not be empty!!' ) } this .webSocketFactory = this .resolveWebSocketFactory(); this .connect() } SekiroClient.prototype.resolveWebSocketFactory = function ( ) { if (typeof window === 'object' ) { var theWebSocket = window .WebSocket ? window .WebSocket : window .MozWebSocket; return function (wsURL ) { function WindowWebSocketWrapper (wsURL ) { this .mSocket = new theWebSocket(wsURL); } WindowWebSocketWrapper.prototype.close = function ( ) { this .mSocket.close(); }; WindowWebSocketWrapper.prototype.onmessage = function (onMessageFunction ) { this .mSocket.onmessage = onMessageFunction; }; WindowWebSocketWrapper.prototype.onopen = function (onOpenFunction ) { this .mSocket.onopen = onOpenFunction; }; WindowWebSocketWrapper.prototype.onclose = function (onCloseFunction ) { this .mSocket.onclose = onCloseFunction; }; WindowWebSocketWrapper.prototype.send = function (message ) { this .mSocket.send(message); }; return new WindowWebSocketWrapper(wsURL); } } if (typeof weex === 'object' ) { try { console .log("test webSocket for weex" ); var ws = weex.requireModule('webSocket' ); console .log("find webSocket for weex:" + ws); return function (wsURL ) { try { ws.close(); } catch (e) { } ws.WebSocket(wsURL, '' ); return ws; } } catch (e) { console .log(e); } } if (typeof WebSocket === 'object' ) { return function (wsURL ) { return new theWebSocket(wsURL); } } throw new Error ("the js environment do not support websocket" ); }; SekiroClient.prototype.connect = function ( ) { console .log('sekiro: begin of connect to wsURL: ' + this .wsURL); var _this = this ; try { this .socket = this .webSocketFactory(this .wsURL); } catch (e) { console .log("sekiro: create connection failed,reconnect after 2s" ); setTimeout (function ( ) { _this.connect() }, 2000 ) } this .socket.onmessage(function (event ) { _this.handleSekiroRequest(event.data) }); this .socket.onopen(function (event ) { console .log('sekiro: open a sekiro client connection' ) }); this .socket.onclose(function (event ) { console .log('sekiro: disconnected ,reconnection after 2s' ); setTimeout (function ( ) { _this.connect() }, 2000 ) }); }; SekiroClient.prototype.handleSekiroRequest = function (requestJson ) { console .log("receive sekiro request: " + requestJson); var request = JSON .parse(requestJson); var seq = request['__sekiro_seq__' ]; if (!request['action' ]) { this .sendFailed(seq, 'need request param {action}' ); return } var action = request['action' ]; if (!this .handlers[action]) { this .sendFailed(seq, 'no action handler: ' + action + ' defined' ); return } var theHandler = this .handlers[action]; var _this = this ; try { theHandler(request, function (response ) { try { _this.sendSuccess(seq, response) } catch (e) { _this.sendFailed(seq, "e:" + e); } }, function (errorMessage ) { _this.sendFailed(seq, errorMessage) }) } catch (e) { console .log("error: " + e); _this.sendFailed(seq, ":" + e); } }; SekiroClient.prototype.sendSuccess = function (seq, response ) { var responseJson; if (typeof response == 'string' ) { try { responseJson = JSON .parse(response); } catch (e) { responseJson = {}; responseJson['data' ] = response; } } else if (typeof response == 'object' ) { responseJson = response; } else { responseJson = {}; responseJson['data' ] = response; } if (typeof response == 'string' ) { responseJson = {}; responseJson['data' ] = response; } if (Array .isArray(responseJson)) { responseJson = { data : responseJson, code : 0 } } if (responseJson['code' ]) { responseJson['code' ] = 0 ; } else if (responseJson['status' ]) { responseJson['status' ] = 0 ; } else { responseJson['status' ] = 0 ; } responseJson['__sekiro_seq__' ] = seq; var responseText = JSON .stringify(responseJson); console .log("response :" + responseText); if (responseText.length < 1024 * 6 ) { this .socket.send(responseText); return ; } if (this .base64) { responseText = this .base64Encode(responseText) } var segmentSize = 1024 * 5 ; var i = 0 , totalFrameIndex = Math .floor(responseText.length / segmentSize) + 1 ; for (; i < totalFrameIndex; i++) { var frameData = JSON .stringify({ __sekiro_frame_total : totalFrameIndex, __sekiro_index : i, __sekiro_seq__ : seq, __sekiro_base64 : this .base64, __sekiro_is_frame : true , __sekiro_content : responseText.substring(i * segmentSize, (i + 1 ) * segmentSize) } ); console .log("frame: " + frameData); this .socket.send(frameData); } }; SekiroClient.prototype.sendFailed = function (seq, errorMessage ) { if (typeof errorMessage != 'string' ) { errorMessage = JSON .stringify(errorMessage); } var responseJson = {}; responseJson['message' ] = errorMessage; responseJson['status' ] = -1 ; responseJson['__sekiro_seq__' ] = seq; var responseText = JSON .stringify(responseJson); console .log("sekiro: response :" + responseText); this .socket.send(responseText) }; SekiroClient.prototype.registerAction = function (action, handler ) { if (typeof action !== 'string' ) { throw new Error ("an action must be string" ); } if (typeof handler !== 'function' ) { throw new Error ("a handler must be function" ); } console .log("sekiro: register action: " + action); this .handlers[action] = handler; return this ; }; SekiroClient.prototype.encodeWithBase64 = function ( ) { this .base64 = arguments && arguments .length > 0 && arguments [0 ]; }; SekiroClient.prototype.base64Encode = function (s ) { if (arguments .length !== 1 ) { throw "SyntaxError: exactly one argument required" ; } s = String (s); if (s.length === 0 ) { return s; } function _get_chars (ch, y ) { if (ch < 0x80 ) y.push(ch); else if (ch < 0x800 ) { y.push(0xc0 + ((ch >> 6 ) & 0x1f )); y.push(0x80 + (ch & 0x3f )); } else { y.push(0xe0 + ((ch >> 12 ) & 0xf )); y.push(0x80 + ((ch >> 6 ) & 0x3f )); y.push(0x80 + (ch & 0x3f )); } } var _PADCHAR = "=" , _ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" , _VERSION = "1.1" ; var i, b10, y = [], x = [], len = s.length; i = 0 ; while (i < len) { _get_chars(s.charCodeAt(i), y); while (y.length >= 3 ) { var ch1 = y.shift(); var ch2 = y.shift(); var ch3 = y.shift(); b10 = (ch1 << 16 ) | (ch2 << 8 ) | ch3; x.push(_ALPHA.charAt(b10 >> 18 )); x.push(_ALPHA.charAt((b10 >> 12 ) & 0x3F )); x.push(_ALPHA.charAt((b10 >> 6 ) & 0x3f )); x.push(_ALPHA.charAt(b10 & 0x3f )); } i++; } switch (y.length) { case 1 : var ch = y.shift(); b10 = ch << 16 ; x.push(_ALPHA.charAt(b10 >> 18 ) + _ALPHA.charAt((b10 >> 12 ) & 0x3F ) + _PADCHAR + _PADCHAR); break ; case 2 : var ch1 = y.shift(); var ch2 = y.shift(); b10 = (ch1 << 16 ) | (ch2 << 8 ); x.push(_ALPHA.charAt(b10 >> 18 ) + _ALPHA.charAt((b10 >> 12 ) & 0x3F ) + _ALPHA.charAt((b10 >> 6 ) & 0x3f ) + _PADCHAR); break ; } return x.join("" ); }; function startRpc ( ) { if (window .flag) { } else { function guid ( ) { function S4 ( ) { return (((1 + Math .random()) * 0x10000 ) | 0 ).toString(16 ).substring(1 ); } return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4()); } window .flag = true ; var client = new SekiroClient("ws://127.0.0.1:5620/business-demo/register?group=rpc-test&clientId=" + guid()); client.registerAction("ths" , function (request, resolve, reject ) { resolve(rt.update()); }) } } setTimeout (startRpc, 1000 ) })()
1 2 3 4 5 6 7 8 9 import requestsdata = { "group" : "rpc-test" , "action" : "ths" , } res = requests.get("http://127.0.0.1:5620/business-demo/invoke" , params=data) print (res.text)
2. 替换文件注入案例2 1. 逆向目标
3. 实现代码
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 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 (function ( ) { function SekiroClient (wsURL ) { this .wsURL = wsURL; this .handlers = {}; this .socket = {}; this .base64 = false ; if (!wsURL) { throw new Error ('wsURL can not be empty!!' ) } this .webSocketFactory = this .resolveWebSocketFactory(); this .connect() } SekiroClient.prototype.resolveWebSocketFactory = function ( ) { if (typeof window === 'object' ) { var theWebSocket = window .WebSocket ? window .WebSocket : window .MozWebSocket; return function (wsURL ) { function WindowWebSocketWrapper (wsURL ) { this .mSocket = new theWebSocket(wsURL); } WindowWebSocketWrapper.prototype.close = function ( ) { this .mSocket.close(); }; WindowWebSocketWrapper.prototype.onmessage = function (onMessageFunction ) { this .mSocket.onmessage = onMessageFunction; }; WindowWebSocketWrapper.prototype.onopen = function (onOpenFunction ) { this .mSocket.onopen = onOpenFunction; }; WindowWebSocketWrapper.prototype.onclose = function (onCloseFunction ) { this .mSocket.onclose = onCloseFunction; }; WindowWebSocketWrapper.prototype.send = function (message ) { this .mSocket.send(message); }; return new WindowWebSocketWrapper(wsURL); } } if (typeof weex === 'object' ) { try { console .log("test webSocket for weex" ); var ws = weex.requireModule('webSocket' ); console .log("find webSocket for weex:" + ws); return function (wsURL ) { try { ws.close(); } catch (e) { } ws.WebSocket(wsURL, '' ); return ws; } } catch (e) { console .log(e); } } if (typeof WebSocket === 'object' ) { return function (wsURL ) { return new theWebSocket(wsURL); } } throw new Error ("the js environment do not support websocket" ); }; SekiroClient.prototype.connect = function ( ) { console .log('sekiro: begin of connect to wsURL: ' + this .wsURL); var _this = this ; try { this .socket = this .webSocketFactory(this .wsURL); } catch (e) { console .log("sekiro: create connection failed,reconnect after 2s" ); setTimeout (function ( ) { _this.connect() }, 2000 ) } this .socket.onmessage(function (event ) { _this.handleSekiroRequest(event.data) }); this .socket.onopen(function (event ) { console .log('sekiro: open a sekiro client connection' ) }); this .socket.onclose(function (event ) { console .log('sekiro: disconnected ,reconnection after 2s' ); setTimeout (function ( ) { _this.connect() }, 2000 ) }); }; SekiroClient.prototype.handleSekiroRequest = function (requestJson ) { console .log("receive sekiro request: " + requestJson); var request = JSON .parse(requestJson); var seq = request['__sekiro_seq__' ]; if (!request['action' ]) { this .sendFailed(seq, 'need request param {action}' ); return } var action = request['action' ]; if (!this .handlers[action]) { this .sendFailed(seq, 'no action handler: ' + action + ' defined' ); return } var theHandler = this .handlers[action]; var _this = this ; try { theHandler(request, function (response ) { try { _this.sendSuccess(seq, response) } catch (e) { _this.sendFailed(seq, "e:" + e); } }, function (errorMessage ) { _this.sendFailed(seq, errorMessage) }) } catch (e) { console .log("error: " + e); _this.sendFailed(seq, ":" + e); } }; SekiroClient.prototype.sendSuccess = function (seq, response ) { var responseJson; if (typeof response == 'string' ) { try { responseJson = JSON .parse(response); } catch (e) { responseJson = {}; responseJson['data' ] = response; } } else if (typeof response == 'object' ) { responseJson = response; } else { responseJson = {}; responseJson['data' ] = response; } if (typeof response == 'string' ) { responseJson = {}; responseJson['data' ] = response; } if (Array .isArray(responseJson)) { responseJson = { data : responseJson, code : 0 } } if (responseJson['code' ]) { responseJson['code' ] = 0 ; } else if (responseJson['status' ]) { responseJson['status' ] = 0 ; } else { responseJson['status' ] = 0 ; } responseJson['__sekiro_seq__' ] = seq; var responseText = JSON .stringify(responseJson); console .log("response :" + responseText); if (responseText.length < 1024 * 6 ) { this .socket.send(responseText); return ; } if (this .base64) { responseText = this .base64Encode(responseText) } var segmentSize = 1024 * 5 ; var i = 0 , totalFrameIndex = Math .floor(responseText.length / segmentSize) + 1 ; for (; i < totalFrameIndex; i++) { var frameData = JSON .stringify({ __sekiro_frame_total : totalFrameIndex, __sekiro_index : i, __sekiro_seq__ : seq, __sekiro_base64 : this .base64, __sekiro_is_frame : true , __sekiro_content : responseText.substring(i * segmentSize, (i + 1 ) * segmentSize) } ); console .log("frame: " + frameData); this .socket.send(frameData); } }; SekiroClient.prototype.sendFailed = function (seq, errorMessage ) { if (typeof errorMessage != 'string' ) { errorMessage = JSON .stringify(errorMessage); } var responseJson = {}; responseJson['message' ] = errorMessage; responseJson['status' ] = -1 ; responseJson['__sekiro_seq__' ] = seq; var responseText = JSON .stringify(responseJson); console .log("sekiro: response :" + responseText); this .socket.send(responseText) }; SekiroClient.prototype.registerAction = function (action, handler ) { if (typeof action !== 'string' ) { throw new Error ("an action must be string" ); } if (typeof handler !== 'function' ) { throw new Error ("a handler must be function" ); } console .log("sekiro: register action: " + action); this .handlers[action] = handler; return this ; }; SekiroClient.prototype.encodeWithBase64 = function ( ) { this .base64 = arguments && arguments .length > 0 && arguments [0 ]; }; SekiroClient.prototype.base64Encode = function (s ) { if (arguments .length !== 1 ) { throw "SyntaxError: exactly one argument required" ; } s = String (s); if (s.length === 0 ) { return s; } function _get_chars (ch, y ) { if (ch < 0x80 ) y.push(ch); else if (ch < 0x800 ) { y.push(0xc0 + ((ch >> 6 ) & 0x1f )); y.push(0x80 + (ch & 0x3f )); } else { y.push(0xe0 + ((ch >> 12 ) & 0xf )); y.push(0x80 + ((ch >> 6 ) & 0x3f )); y.push(0x80 + (ch & 0x3f )); } } var _PADCHAR = "=" , _ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" , _VERSION = "1.1" ; var i, b10, y = [], x = [], len = s.length; i = 0 ; while (i < len) { _get_chars(s.charCodeAt(i), y); while (y.length >= 3 ) { var ch1 = y.shift(); var ch2 = y.shift(); var ch3 = y.shift(); b10 = (ch1 << 16 ) | (ch2 << 8 ) | ch3; x.push(_ALPHA.charAt(b10 >> 18 )); x.push(_ALPHA.charAt((b10 >> 12 ) & 0x3F )); x.push(_ALPHA.charAt((b10 >> 6 ) & 0x3f )); x.push(_ALPHA.charAt(b10 & 0x3f )); } i++; } switch (y.length) { case 1 : var ch = y.shift(); b10 = ch << 16 ; x.push(_ALPHA.charAt(b10 >> 18 ) + _ALPHA.charAt((b10 >> 12 ) & 0x3F ) + _PADCHAR + _PADCHAR); break ; case 2 : var ch1 = y.shift(); var ch2 = y.shift(); b10 = (ch1 << 16 ) | (ch2 << 8 ); x.push(_ALPHA.charAt(b10 >> 18 ) + _ALPHA.charAt((b10 >> 12 ) & 0x3F ) + _ALPHA.charAt((b10 >> 6 ) & 0x3f ) + _PADCHAR); break ; } return x.join("" ); }; if (window .flag) { } else { function guid ( ) { function S4 ( ) { return (((1 + Math .random()) * 0x10000 ) | 0 ).toString(16 ).substring(1 ); } return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4()); } window .flag = true ; var client = new SekiroClient("ws://127.0.0.1:5620/business-demo/register?group=rpc-test&clientId=" + guid()); client.registerAction("jz" , function (request, resolve, reject ) { e = request['data' ]; n = b(e); resolve(n); }) } })()
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 import requestsimport jsonimport timeclass JianZhu (): def __init__ (self ): self.url = "https://jzsc.mohurd.gov.cn/APi/webApi/dataservice/query/comp/list?pg={}&pgsz=15&total=450" self.headers = { "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0" , 'Referer' :'https://jzsc.mohurd.gov.cn/data/company' , 'V' :'231012' } def get_Data (self, page ): res = requests.get(self.url.format (page), headers=self.headers) return res.text def parse_Data (self, data ): data = { "group" : "rpc-test" , "action" : "jz" , 'data' : data } res = requests.post(url="http://127.0.0.1:5620/business-demo/invoke" , data=data, verify=False ) if res.json().get('data' ): print (res.json()['data' ]) else : print ('连接问题' ) def main (self ): for i in range (1 , 30 ): data = self.get_Data(i) self.parse_Data(data) if __name__ == '__main__' : jz = JianZhu() jz.main()