jck28 - 小柒 - python处理 http+pb 协议

定义pb文件

syntax = "proto3";

package oppo.ads.search.gsearch;

message ReqApp
{
    uint64  app_id              =   1[json_name = "appId"];
    string  pkg_name            =   3; 
};


enum NetworkType
{
    NETWORK_UNKOWN          = 0;    
    NETWORK_ETH             = 1;     
    NETWORK_WIFI            = 2;   
    NETWORK_2G              = 3;     
    NETWORK_X_G             = 7;   
};


message AdRequest
{
    // header info
    string req_id           = 1;   
    string exp_id           = 2;     
    uint64 server_time_s    = 4;    

    // machine info
    string brand            = 5;     
    string app_version      = 11;   
    NetworkType network_id  = 13;   

    // user info
    string du_id			= 17;   
    string client_ip_v4     = 18;   
    string client_ip_v6     = 19;   


    // query info
    string keyword          = 23;    
    int32  number           = 24;   
    uint32 offset           = 25;    

    map<string, bytes> extensions=  28; 
    repeated ReqApp normal_apps =   32[json_name = "normalApps"];
    string os_version_code     = 33;   
    string is_media_new_arc =36; 
    map<string, string> mediaExpParams = 37;  
};

enum AdContentType
{
    AD_CONTENT_TYPE_UNKOWN  = 0;    // unexpected error type
    AD_CONTENT_LINK         = 1;     
    AD_CONTENT_INSTANT      = 3;    
};


enum AdFormatType
{
    AD_FORMAT_TYPE_UNKOWN   = 0;    
    AD_FORMAT_BIG_IMG       = 6;   
    AD_FORMAT_IMG_TEXT      = 7;    
    AD_FORMAT_TYPE_LIST     = 70;    
};

enum GlobalSpecId {
    SEARCH_APP_TYPE_UNKOWN   = 0;   
    SEARCH_APP_BIG_IMG_1     = 1;  
    SEARCH_APP_THREE_VERTICAL_IMG_37 = 37; 
}


enum TrackingEventType
{
    EVENT_TYPE_UNKOWN       = 0;    
    EVENT_EXPOSE_START      = 1;     
};

message TrackingInfo
{
    TrackingEventType event_type    = 1;  
    repeated string   url           = 2;  
};


enum JumpType
{
    JUMPTYPE_UNKOWN             =   0;  
    JUMPTYPE_URL                =   1;  
    JUMPTYPE_INSTANT            =   3;  
}


message AdCreative
{
    string  creative_id         =   1;  
    int32   creative_type       =   2; 
    string  title               =   3;  
    map<string, bytes> extensions=  7;  
    reserved    8 to 20;               //预留8-20

    // 跳转类型
    JumpType jump_type          =   21;  
    string  jump_url            =   22; 
    string  instant_url         =   24;  

    repeated TrackingInfo tracks =  25; 

    // app 详情信息
    string app_name             =   26; 
    uint64 cat_lev1             =   27; 

};

// app标签
message AppLabel{
    uint32 type     = 1; 
    string color    = 2;  
}
// 内容
message AdItem
{
    AdContentType  content_type =   1;  
    AdFormatType   format_type  =   2;  
    string  transparent         =   6;  
    string  ref1                =   7;  
    string  trackId             =   8; 
    int64   channelId           =   10;
};

message AdResponse
{
    uint32              code                =   1;  // 0 成功 其他:失败
    string              msg                 =   2;  // error message if failed
    uint32              ad_size             =   3;  // 广告数
    repeated AdItem     ads                 =   4;  // 广告列表
};

脚本生成pb文件:

  • 安装依赖包 : pip install grpcio
  • proto文件生成py文件(需切换到proto文件目录,-I. proto文件在当前目录)
    • python -m grpc_tools.protoc --python_out=. -I. ads_cpd_store_base_request.proto
    • python -m grpc_tools.protoc --python_out=. -I. ads_cpd_store_base_response.proto

代码示例(http+pb):

from google.protobuf.json_format import ParseDict,MessageToJson
from search.searchAPI.quanju_n1.ad_search_pb2 import *
import requests
import json
import time
import re


url="http://10.177.119.13:25201/ads/search/globaldone"

//这里请求参数有做删减,与pb文件不匹配,防止泄密
class QJN1():
    def __init__(self, **kwargs):
        self.url = url
        self.body = {
            "req_id": "1emiju9470000111111111",
            "exp_id": "search_test",
            "client_ip_v6": "AD80::ABAA:0000:00C2:0002",
            "client_time_s": int(time.time()),
            "lon": 12.0,
            "lat": 25.6,
            "request_type":1,                   
            "keyword": '购物',
            "number": 18,
            "offset": '10',  # 暂不生效
            "biz_type": 2,
            "resource_type": 0,
            "extensions": {}

        }
        self.body.update(kwargs)

    def send_request(self):
        header = {
            "Content-Type": "application/x-protobuf",
            "Accept-Encoding": "gzip",
            "User-Agent": "Dalvik/2.1.0 (Linux; U; Android 7.1.1; Build/NMF26X)",
            "Accept": "application/x-protobuf"
        }

        pb_obj = AdRequest()
        ParseDict(js_dict=self.body,message=pb_obj) #json转message
        # body_byte = pb_obj.SerializeToString()      #message转byte
        req_obj = json.loads(MessageToJson(pb_obj)) #将str转化为dict
        print("发送请求",json.dumps(req_obj))
        pb_str = pb_obj.SerializeToString()         #message转byte
        resp = requests.post(self.url, data=pb_str, headers=header, verify=False)
        time.sleep(0.2)

        b_resp = resp.content       #将response转化为二进制数据
        resp_pb_obj =AdResponse()
        resp_pb_obj.ParseFromString(b_resp)

        res_obj = json.loads(MessageToJson(resp_pb_obj))
        print('请求url',self.url)
        print("响应结果", json.dumps(res_obj))

        return res_obj



if __name__ == '__main__':
        qjn1_request_data = QJN1(imei="8800000000014666", brand="oppo", source=29, request_type=2, keyword="应用",reqId="1emiju94700geutriky6tiy",mediaExpParams={"all_search_deeplink_operation_exp": "true"},normal_apps=[{"install_status": True, "pkg_name": "com.tencent.weishi"}])

        res = qjn1_request_data.send_request()
        print(json.dumps(res))