thread_indent

本文详细解读了优快云上的一篇技术文章,涵盖了多个信息技术领域的核心概念与应用实例,旨在为读者提供深入的技术洞察与创新思维。文章内容包括但不限于前端开发、后端开发、移动开发、游戏开发、大数据开发、开发工具等多个方面,通过丰富的实例与案例分析,阐述了现代信息技术领域的最新趋势与实践方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://blog.youkuaiyun.com/justlinux2010/article/details/10269033

转载于:https://www.cnblogs.com/zengkefu/p/4977434.html

import xml.etree.ElementTree as ET from xml.dom import minidom import json from urllib.parse import urlparse def safe_load_har(file_path): """安全加载 HAR 文件,支持非法字符和大文件""" try: with open(file_path, 'r', encoding='utf-8') as f: return json.load(f) except json.JSONDecodeError: print("⚠️ 文件不是合法的 JSON,尝试忽略非法字符...") with open(file_path, 'r', encoding='utf-8', errors='ignore') as f: content = f.read() return json.loads(content) def parse_har(file_path): har_data = safe_load_har(file_path) entries = har_data.get('log', {}).get('entries', []) static_extensions = ('.js', '.css', '.jpg', '.jpeg', '.png', '.gif', '.ico', '.svg', '.woff', '.ttf') requests = [] for entry in entries: request = entry.get('request', {}) response = entry.get('response', {}) url = request.get('url') if not url or any(url.lower().endswith(ext) for ext in static_extensions): continue # 过滤掉静态资源或无效 URL req_info = { 'method': request.get('method'), 'url': url, 'headers': {h.get('name'): h.get('value') for h in request.get('headers', [])}, 'postData': request.get('postData', {}).get('text', '') if request.get('postData') else '', 'mimeType': response.get('content', {}).get('mimeType', '') } requests.append(req_info) return requests def set_post_data_urlencoded(http_sampler, post_data): """ 添加 application/x-www-form-urlencoded 类型的 POST 请求体数据 示例:username=admin&password=123456 """ # 表单数据无需设置 postBodyRaw,JMeter 自动处理 args_element = ET.SubElement(http_sampler, 'elementProp', name='HTTPSampler.Arguments', elementType='Arguments', guiclass='HTTPArgumentsPanel', testclass='Arguments') collection = ET.SubElement(args_element, 'collectionProp', name='Arguments.arguments') if not post_data.strip(): return pairs = post_data.split('&') for pair in pairs: if '=' in pair: key, value = pair.split('=', 1) else: key, value = pair, '' add_argument(collection, key, value) def add_argument(collection, key, value): element = ET.SubElement(collection, 'elementProp', name='', elementType='HTTPArgument') ET.SubElement(element, 'stringProp', name='Argument.name').text = key ET.SubElement(element, 'stringProp', name='Argument.value').text = value ET.SubElement(element, 'stringProp', name='Argument.metadata').text = '=' ET.SubElement(element, 'boolProp', name='HTTPArgument.use_equals').text = 'true' ET.SubElement(element, 'boolProp', name='HTTPArgument.always_encode').text = 'false' def prettify(elem): rough_string = ET.tostring(elem, encoding='utf-8', method='xml') reparsed = minidom.parseString(rough_string) return reparsed.toprettyxml(indent=" ") def generate_jmx(requests, output_file='test_plan.jmx'): root = ET.Element('jmeterTestPlan', version="1.2", properties="5.6.3", jmeter="5.6.3") hash_tree = ET.SubElement(root, 'hashTree') # TestPlan test_plan = ET.SubElement(hash_tree, 'TestPlan', guiclass="TestPlanGui", testclass="TestPlan", testname="Test Plan", enabled="true") test_plan_hash_tree = ET.SubElement(hash_tree, 'hashTree') # ThreadGroup thread_group = ET.SubElement(test_plan_hash_tree, 'ThreadGroup', guiclass="ThreadGroupGui", testclass="ThreadGroup", testname="Thread Group", enabled="true") # Loop Controller main_controller = ET.SubElement(thread_group, 'elementProp', name='ThreadGroup.main_controller', elementType='LoopController', guiclass='LoopControlPanel', testclass='LoopController') ET.SubElement(main_controller, 'stringProp', name='LoopController.loops').text = '1' ET.SubElement(main_controller, 'boolProp', name='LoopController.continueForever').text = 'false' ET.SubElement(thread_group, 'stringProp', name='ThreadGroup.num_threads').text = '1' ET.SubElement(thread_group, 'stringProp', name='ThreadGroup.ramp_time').text = '1' ET.SubElement(thread_group, 'boolProp', name='ThreadGroup.scheduler').text = 'false' ET.SubElement(thread_group, 'stringProp', name='ThreadGroup.duration').text = '' ET.SubElement(thread_group, 'stringProp', name='ThreadGroup.delay').text = '' thread_group_hash_tree = ET.SubElement(test_plan_hash_tree, 'hashTree') # CookieManager cookie_manager = ET.SubElement(thread_group_hash_tree, 'CookieManager', guiclass="CookiePanel", testclass="CookieManager", testname="HTTP Cookie Manager", enabled="true") ET.SubElement(cookie_manager, 'boolProp', name='CookieManager.clearEachIteration').text = 'false' ET.SubElement(cookie_manager, 'stringProp', name='CookieManager.policy').text = 'default' ET.SubElement(thread_group_hash_tree, 'hashTree') for i, req in enumerate(requests): url = req['url'] method = req['method'] request_name = f"{i + 1}-{url}" parsed_url = urlparse(url) protocol = parsed_url.scheme host = parsed_url.netloc path = parsed_url.path or '/' # HTTPSamplerProxy http_sampler = ET.SubElement(thread_group_hash_tree, 'HTTPSamplerProxy', guiclass="HttpTestSampleGui", testclass="HTTPSamplerProxy", testname=request_name, enabled="true") ET.SubElement(http_sampler, 'stringProp', name='HTTPSampler.name').text = request_name ET.SubElement(http_sampler, 'stringProp', name='HTTPSampler.protocol').text = protocol ET.SubElement(http_sampler, 'stringProp', name='HTTPSampler.domain').text = host ET.SubElement(http_sampler, 'stringProp', name='HTTPSampler.port').text = '' ET.SubElement(http_sampler, 'stringProp', name='HTTPSampler.path').text = path ET.SubElement(http_sampler, 'stringProp', name='HTTPSampler.method').text = method ET.SubElement(http_sampler, 'boolProp', name='HTTPSampler.follow_redirects').text = 'true' ET.SubElement(http_sampler, 'boolProp', name='HTTPSampler.auto_redirects').text = 'false' ET.SubElement(http_sampler, 'stringProp', name='HTTPSampler.use_keepalive').text = 'true' ET.SubElement(http_sampler, 'stringProp', name='HTTPSampler.DO_MULTIPART_POST').text = 'false' http_hash_tree = ET.SubElement(thread_group_hash_tree, 'hashTree') # HeaderManager header_manager = ET.SubElement(http_hash_tree, 'HeaderManager', guiclass="HeaderPanel", testclass="HeaderManager", testname="HTTP Header Manager", enabled="true") headers_collection = ET.SubElement(header_manager, 'collectionProp', name='HeaderManager.headers') for name, value in req['headers'].items(): header = ET.SubElement(headers_collection, 'elementProp', name='', elementType='Header') ET.SubElement(header, 'stringProp', name='Header.name').text = name ET.SubElement(header, 'stringProp', name='Header.value').text = value ET.SubElement(http_hash_tree, 'hashTree') # 处理 POST 请求数据(关键修复) if method == 'POST' and req['postData']: content_type = req['headers'].get('Content-Type', req.get('mimeType', '')) if 'application/x-www-form-urlencoded' in content_type: set_post_data_urlencoded(http_sampler, req['postData']) else: # 原始 POST 数据(JSON/XML 等) # 关键修复:设置 postBodyRaw 和 postBodyRawValue ET.SubElement(http_sampler, 'boolProp', name='HTTPSampler.postBodyRaw').text = 'true' ET.SubElement(http_sampler, 'stringProp', name='HTTPSampler.postBodyRawValue').text = req['postData'] # 写入文件 with open(output_file, 'w', encoding='utf-8') as f: f.write('<?xml version="1.0" encoding="UTF-8"?>\n') rough_string = ET.tostring(root, encoding='utf-8', method='xml') reparsed = minidom.parseString(rough_string) f.write(reparsed.toprettyxml(indent=" ")[23:]) # 去除重复的 xml 声明 print(f"✅ JMeter 测试计划已生成:{output_file}") if __name__ == '__main__': requests = parse_har("tt.har") print(f"共解析到 {len(requests)} 个非静态请求") for i, req in enumerate(requests): print(f"\n--- 请求 {i + 1} ---") print("URL:", req['url']) print("Method:", req['method']) print("Headers:", req['headers']) if req['postData']: print("PostData:", req['postData']) generate_jmx(requests, "test_plan3C-v1.jmx") 问题:解决JMeter UI 中 POST 请求体实际不显示,将har文件中属于post 请求体信息补全显示到jmeter。提供完整代码
07-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值