万方 protobuf 反序列化

news2024/11/25 5:48:04

protobuf 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。
在网络传输方面,相比传统的json,有着更快、更小,且加密性好的特点。


在实际应用中,万方数据库官网发送的请求,就用到了这。
一般网站,比如cnki,我们检索内容,只需要拼接一个http请求,便能获取到数据。
在这里插入图片描述



但是,万方数据库,却是这样的,看不到请求body都是一些乱码一样的数据,连返回的数据也是。
在这里插入图片描述
在这里插入图片描述



这正是由于其使用了protobuf序列化,我们通过它发送请求头中也可以看到有 “application/grpc-web+proto” 这样的字样。
在这里插入图片描述




其大致流程:实例化一个proto格式对象(长得类似c的结构体),将检索式塞到该对象属性中,对其进行序列化为二进制,发送请求,对接收到的数据进行反序列化。
因此我们重点就在于拿到这个proto对象的结构。



有关万方protobuf发送请求的大部分内容,可以参考大佬的文章: https://blog.csdn.net/qq_35491275/article/details/111721639



这里就只对拿到数据,将其反序列化的大致步骤,进行讲解。
本人是通过python发送请求,根据上面参考文章说的,要将数据反序列化,便需要获取到proto格式,比如有哪些变量和变量类型。
而这都需要通过在浏览器F12,打断点,一步步调试js函数才能获得。本人由于对js不了解,也不太会调试js,所以也是变相换个方法去实现。



F12------》Source------》XHR/fetch Breakpoints,将接口请求地址复制进去,这样调试的时候就会自动在相关位置断点了。
在这里插入图片描述



在Call Stack调用栈中,看到了SearchService字样,点击进去。
在这里插入图片描述
在这里插入图片描述



后面通过打断点,一步步调试,便能在一些方法名中找到需要的变量和类型。
本人这里就不做调试,我说说自己当时的思路。

因为整个检索流程,就主要经过了两份js,所以我直接ctrl+F,搜索SearchService字样,发现都在api.1f9fdaa9.js这一份当中。
然后我再ctrl+F,搜索 “toObject = function(e, t) {” 字样,一般每个message结构对应的变量名和序号就在这个函数中,变量类型则一般在 “serializeBinaryToWriter = function(e, t) {” 函数中,大概有90多个匹配的。这一步不清楚可以看上面参考博客,便知道为什么这样找这些message结构。将他们列出来,写入一份.proto文件中。
这里变量名好像可以自己命名,主要是序号需要保持一致,但为了解析数据方便,这里变量名也尽量保持了和js中的一致,最终得到右边的proto文件。
在这里插入图片描述


在这里插入图片描述


在这里插入图片描述




然后通过protoc.exe编译器,输入命令 protoc proto文件名 --python_out=./ 得到相关py文件。

在这里插入图片描述




新建一个python工程,将刚刚生成的py文件丢入工程中。便可成功反序列化出数据。

在这里插入图片描述


这里请求时使用了blackboxprotobuf模块,可以减少去获取请求的proto结构这一步骤。具体一些点的可以参考他人博客。

参考代码:main.py

# This is a sample Python script.

# Press Shift+F10 to execute it or replace it with your code.
# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.


import blackboxprotobuf
import urllib
from urllib import parse
import requests
import tkinter
import asyncio
import os
import wf_proto_pb2 as wf_proto_pb2


def intToBytes(value, length):
  result = []
  for i in range(0, length):
    result.append(value >> (i * 8) & 0xff)
  result.reverse()
  return result


def prowfdata(response):
    # 转码
    response = str(response.encode('latin1').decode('unicode-escape').encode('latin1').decode('utf-8'))
    return response


def searchw(searchkey):
    searchkey = urllib.parse.unquote(searchkey)
    json = eval(searchkey)
    url = json["url"]
    headers = json["headers"]
    deserialize_data = json["deserialize_data"]
    message_type = json["message_type"]
    unwanted_bytes = json["unwanted_bytes"]

    proxies = {'http': 'http://127.0.0.1:8888', 'https': 'http://127.0.0.1:8888'}
    form_data = bytes(blackboxprotobuf.encode_message(deserialize_data, message_type))
    bytes_head = bytes(intToBytes(len(form_data), 5))

    requests.packages.urllib3.disable_warnings()
    try:
        response = requests.post(url=url, headers=headers,data=bytes_head + form_data, timeout=10, verify=False)
    except Exception as e:
        response = requests.post(url=url, headers=headers,data=bytes_head + form_data, timeout=10, verify=False, proxies=proxies)



    search_response2 = wf_proto_pb2.SearchService_SearchResponse()
    search_response2.ParseFromString(response.content[5:])
    return prowfdata(str(search_response2))





if __name__ == '__main__':
    searchkey = '{"url":"https://s.wanfangdata.com.cn/SearchService.SearchService/search","headers":{"accept":"*/*","Referer":"https://s.wanfangdata.com.cn","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36","Content-Type":"application/grpc-web+proto",},"deserialize_data":{"1":{"1":"paper","2":"(题名:(dna))","4":{"1":"Type","2":"(Periodical OR Thesis OR Conference)"},"5":1,"6":10,"8":"\\u0000"},"2":3},"message_type":{"1":{"type":"message","message_typedef":{"1":{"type":"bytes", "name":""}, "2":{"type":"bytes", "name":""},"4":{"type":"message","message_typedef":{"1":{"type":"bytes", "name":""},"2":{"type":"bytes", "name":""}},"name":""}, "5":{"type":"int", "name":""},"6":{"type":"int", "name":""}, "8":{"type":"bytes", "name":""}},"name":""}, "2":{"type":"int", "name":""}},"unwanted_bytes":"0"}'
    print(searchw(searchkey))

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/596434.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

03 【数据代理 事件处理】

03 【数据代理 事件处理】 1.数据代理 了解数据代理需要js的一些知识:Object.defineProperty(),属性标志,属性描述符,getter,setter。。。 1.1数据代理 建议学习文章地址: https://zh.javascript.info/p…

MathType7.4永久中文Mac+Win全平台版本

MathType7.4版是一款功能强大、专业实用、应用范围广的数学公式编辑器软件,这款软件采用了简体中文操作界面并且完美兼容office、wps等一系列常见办公工具,这样就能够很好的为相关用户省去了许多繁琐的操作步骤,用户在这里可以轻轻松松进行公…

最小编译器和 UI 框架「GitHub 热点速览」

作者:HelloGitHub-小鱼干 如果有一个关键词来概述本周的 GitHub 热门项目的话,大概就是 van 和 sectorc 都用到的 smallest。只不过一个是前端的响应式框架,一个是搞编译的 C 编译器。它们除了轻量化这个共同特点之外,还有好用&am…

解决无法ssh命令登录wsl问题

本地主机ssh登录wsl报错被拒绝访问 C:\Users\jiangcheng> ssh rootxxx.xx.xxx.xx -p 22 ssh: connect to host xxx.xx.xxx.xx port 22: Connection refused 解决步骤如下: 1,解决密码不对的问题 wsl默认用户名root的密码是随机的,需要…

【深度学习】yolov7 pytorch模型转onnx,转ncnn模型和mnn模型使用细节

文章目录 前言1.前置1.1 安装必要的库1.2 .pt 权重转ncnn 和mnn所需要的权重 2、编码C项目1.ncnn2.mnn 总结 前言 yolov7 pytorch模型转onnx,转ncnn模型和mnn模型使用细节,记录一下 git仓库: yolov7 https://github.com/WongKinYiu/yolov7 n…

如何基于G6进行双树流转绘制? | 京东云技术团队

1. 背景 业务背景:CRM系统随着各业务条线对线索精细化分配的诉求逐渐增加,各个条线的流向规则会越来越复杂,各个条线甚至整个CRM的线索流转规则急需一种树形的可视化的图来表达。 技术背景:在开发之前考虑了三种方案,…

选什么样的软件平台开发能让办公效率得到提升?

在当今快节奏的时代中,办公自动化发展已成为趋势,采用什么样的软件平台开发能让办公效率得到大大提升?面对众多粉丝朋友提出的问题,作为低代码开发平台服务商,流辰信息有责任有义务与大家分享好产品。因为这是能提升办…

GPT现状终于有人讲清楚了!OpenAI大牛最新演讲爆火,还得是马斯克钦点的天才

量子位 | 公众号 QbitAI 继Windows Copilot发布后,微软Build大会热度又被一场演讲引爆。 前特斯拉AI总监Andrej Karpathy在演讲中认为思维树(tree of thoughts)与AlphaGo的蒙特卡洛树搜索(MCTS)有异曲同工之妙&#…

MySQL数据库 4.SQL通用语法及分类

目录 🤔SQL通用语法: 😊语句: 😊注释: 🤔SQL语句分类: 😊1.DDL语句: 😊2.DML语句: 😊3.DQL语言: &…

springboot+vue+element-ui在线招投标系统

本在线招投标系统管理员管理个人中心,投标人管理,招标人管理,评标人管理,招标信息管理,投标信息管理,评标信息管理,中标信息管理,系统管理。管理员负责所有的管理信息,招…

DAY06_Mybatis

目录 1 MyBatis1.1 快速入门1.1.1 创建user表,添加数据1.1.2 创建模块,导入坐标1.1.3 编写 MyBatis 核心配置文件1.1.4 编写 SQL 映射文件1.1.5 编码 1.2 解决SQL映射文件的警告提示1.3 Mapper代理开发1.3.1 定义与SQL映射文件同名的Mapper接口&#xff…

NFS网络文件挂载【虚拟机到开发板】

注意:首先要确保虚拟机和开发板之间可以互相访问,即配置桥接网卡,如果在同一个网段下但是无法ping通可能是防火墙的问题。可以查看博文解决:vmware虚拟机设置双网卡 注意:当前虚拟机版本为18.04,若虚拟机版…

焊接铁件的一些常识

焊接整体过程 简单来说就是通过各种方式将金属熔化后冷却结合。而焊接过程中一般会有保护气体,例如氩气,二氧化碳。就是常听到的氩弧焊和二保焊。而最常见的是药皮包裹着金属心的焊条,而焊条的药皮就是加热后产生了保护气。弧光是焊条和焊件…

UnaBiz与纵行科技签署战略合作协议 为海量物联共建“融合的LPWAN全球网络”

新加坡、法国、中国,2023年5月30日,UnaBiz和纵行科技签署了战略合作协议,致力于促进“融合的LPWAN全球网络”的发展以实现全球大规模物联网。根据协议,UnaBiz和纵行科技将充分利用各自的网络资源,其中ZETA网络覆盖中国…

走进Linux编程的大门

随着Linux的不断普及,使用Linux的人也越来越多了。然而在Linux中如何进行程序设计,用什么样的开发工具好呢?本文就以我初学Linux编程的一点心得体会,和大家共同探讨。 在Linux中进行程序设计,可以使用各种编程语言和开发工具,以下是一些常用的方法&…

eBay如何实现多账号登录以及防关联?

随着跨境电商的快速发展,亚马逊,eBay已成为人们熟知的电商平台。“不把鸡蛋放在同一个篮子里”,多账号运营店铺有许多显而易见的好处。 但由于亚马逊平台封号状况愈演愈烈,不少卖家把战线转移到了eBay平台。随着入驻人数的增加&a…

windows安装minio

官方下载地址: MinIO | Code and downloads to create high performance object storage 官方快速入门文档: MinIO Object Storage for Windows — MinIO Object Storage for Windows 概述 最近熟悉公司框架,有使用到MinIO,故学习并记录总…

软考A计划-网络规划设计师-核心考点解密

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资源分享&am…

性能测试设计阶段

性能测试设计阶段 性能测试是软件测试中的关键环节,它可以帮助我们评估软件系统在压力下的运行稳定性和性能表现。性能测试设计阶段是性能测试的基础,只有经过充分的设计,才能保证性能测试的有效性和准确性。 在性能测试设计阶段,…

C++STL之vector与list

文章目录 关于vector的用法关于List的用法vector和list的区别 关于vector的用法 #include<stdio.h> #include<iostream> #include<string.h> #include<vector> using namespace std;class PtrInt {int* ptr; public:PtrInt(int x 0) :ptr(new int[x]…