将httpcanary导出的request转换为postman可识别导入的格式

查看 137|回复 9
作者:mumuki   
最近在抓包分析数据的过程中,因为Android7以后对用户证书做了进一步限制,导致charles无法再抓取https的数据,无奈只能通过虚拟机和httpcanary在手机上抓包。
但在分析请求的时候还是在pc上比较方便,并且通过postman方便统一管理接口。但是httpcanary导出的request.json无法被postman识别,于是便写了一个脚本来方便转化数据格式。
(贴下项目的github地址:https://github.com/LaytonLee/hc2pm ,欢迎大家star~~)
使用示例:
python hc2pm.py -i ~/Downloads/hc-req -c postman_collection -o ~/Downloads/b.json
参数:
  • -h: 查看帮助
  • -i: 待转换文件/目录,必须
  • -c: postman中的collection名称,必须
  • -o: 结果输出文件,必须

    下面直接贴代码:
    #! /usr/bin/python3
    # -*- coding: UTF-8 -*-
    """hc2pm.
    @Project   : 将 HttpCanary App 导出的request.json转换为Postman可识别导入的json格式
    @Author    : layton
    """
    import os
    import logging
    import json
    from urllib.parse import unquote
    import argparse
    parser = argparse.ArgumentParser(
            prog="hc2pm",
            description="transform HttpCanary export request json format into postman import reqest format")
    parser.add_argument("--input", "-i", help="待转换的文件或目录", required=True)
    parser.add_argument("--collection", "-c", help="postman的collection名称", required=True)
    parser.add_argument("--output", "-o", help="输出文件名(*.json)", required=True)
    args = parser.parse_args()
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s %(levelname)s %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S')
    log = logger = logging
    SCHEMAS = {
        "v2": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
    }
    class PostmanData():
        class PMRequest():
            class HeaderItem():
                def __init__(self, key:str = None, value:str = None, type:str = None):
                    self.key = key
                    self.value = value
                    self.type = type
                def __repr__(self) -> str:
                    return f"{{ key={self.key}, value={self.value}, type={self.type} }}"
            class Url():
                def __init__(self, raw:str = None):
                    self.raw = raw
                    self.protocal = raw.split("://")[0]
                    self.host = raw.split("://")[1].split("/")[0].split(".")
                    self.path = raw.split("://")[1].split("?")[0].split("/")[1:]
                    self.query = list(map(lambda x: {"key": x.split("=")[0], "value": x.split("=")[1]}, raw.split("?")[1].split("&")))
                def __repr__(self) -> str:
                    return f"{{ raw={self.raw}, protocal={self.protocal}, host={self.host}, path={self.path}, query={self.query} }}"
            def __init__(self, name:str = None, method:str = None, headers:list[HeaderItem] = None, url:Url = None):
                self.name = name
                self.request: dict() = {}
                self.request["method"] = method
                self.request["header"] = headers
                self.request["url"] = url
                self.response = list()
            def __repr__(self) -> str:
                return f"name={self.name}, request={self.request}, url={self.request['url']}"
        def __init__(self, collection_name:str = None, scheme_version:str = "v2", items:list[PMRequest] = None):
            self.info: dict() = {}
            self.info["_postman_id"] = "aaa"
            self.info["name"] = collection_name
            self.info["schema"] = SCHEMAS.get(scheme_version)
            self.item = items
        def __repr__(self) -> str:
            return f"{{ info={self.info}, item={self.item} }}"
        def to_json(self):
            return json.dumps(self, default=lambda o: o.__dict__, sort_keys=False, indent=4)
    def hc2pm_file(file_path: str, request_name: str) -> PostmanData.PMRequest:
        if not os.path.exists(file_path):
            raise IOError(f"No such file: {file_path}")
            return
        hc_str = ""
        with open(file_path, 'r') as f:
            hc_str = f.read()
        hc_json = json.loads(hc_str)
        headers: list[PostmanData.PMRequest.HeaderItem()] = []
        for i_key, i_value in hc_json.get("headers").items():
            header_item = PostmanData.PMRequest.HeaderItem(i_key, unquote(i_value), "default")
            headers.append(header_item)
        url = PostmanData.PMRequest.Url(unquote(hc_json.get("url")))
        method = hc_json.get("method")
        return PostmanData.PMRequest(request_name, method, headers, url)
    def hc2pm_dir(dir):
        pm_reqs: list[PostmanData.PMRequest] = []
        for item in os.listdir(dir):
            sub_path = os.path.join(dir, item)
            tmp_item: dict() = {}
            if os.path.isdir(sub_path):
                tmp_item["name"] = item
                tmp_item["item"] = hc2pm_dir(sub_path)
                pm_reqs.append(tmp_item)
            if sub_path[-4:] == "json":
                pm_req = hc2pm_file(sub_path, item.split(".")[0])
                pm_reqs.append(pm_req)
        return pm_reqs
    def hc2pm_collection(collection_name, hc_path):
        if not os.path.exists(hc_path):
            raise IOError(f"No such path: {hc_path}")
        pm_req_data:list = None
        if os.path.isfile(hc_path):
            file_path, file_fullname = os.path.split(hc_path)
            file_name, file_ext = os.path.splitext(file_fullname)
            pm_req_data = hc2pm_file(hc_path, file_name)
        if os.path.isdir(hc_path):
            pm_req_data = hc2pm_dir(hc_path)
        pm_coll_data = PostmanData(collection_name, "v2", pm_req_data)
        return pm_coll_data
    if __name__ == "__main__":
        try:
            pm_coll_data = hc2pm_collection(args.collection, args.input)
            with open(args.output, 'w') as f:
                f.write(pm_coll_data.to_json())
        except Exception as e:
            logger.error(e)
    效果展示:


    截屏2023-03-15 下午10.31.17.png (66.11 KB, 下载次数: 0)
    下载附件
    2023-3-15 22:46 上传

    转换为, 格式

  • xixicoco   

    非常不错的项目,实际出发的小工具
    asd124689   

    谢谢 这样就方便多了 省很多时间
    cxs203   

    感谢分享了,
    vvo168861   

    感谢楼主分享
    mainblog   

    我更喜欢直接导出curl哈哈,不错的方案,谢谢楼主分享
    zhuimengby   

    非常不错的小工具,mark一下,应该用的到
    amtf0614   

    只会在PC端F12 进行抓包 ,手机端的 不会
    lingwushexi   

    不错的方法,感谢分享
    mumuki
    OP
      


    amtf0614 发表于 2023-3-16 09:29
    只会在PC端F12 进行抓包 ,手机端的 不会

    有些网页为了隐藏接口,直接返回的html,对这些网页抓取数据就会很麻烦
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部