camelot pdf提取表格实践(记录)

参考: 巧用Python的camelot库批量提取PDF发票信息 关于文本pdf的表格抽取 AttributeError: module ‘camelot‘ has no attribute ‘read_pdf‘及类似问题解决办法 camelot 参数 报错解决: ModuleNotFoundError: No module named ‘Workbook’ xlwt,是版本太低,升级版本即可。 pip install --upgrade xlwt 介绍: camelot方法有两种解析模式:流解析(stream)、格子解析(lattice),其中格子解析能够保留表格完整的样式,对于复杂表格来说要优于流解析模式。同时,camelot方法默认格子解析(lattice),而采用这种解析方式,需要安装ghostscript。 下载ghostscript https://www.ghostscript.com/releases/gsdnld.html import camelot import pandas as pd # 使用Camelot读取PDF文件中的表格 tables = camelot.read_pdf('pdf.pdf', pages='all', flavor='lattice') # 将所有表格转换为 DataFrame 并合并 all_data = pd.concat([table.df for table in tables], ignore_index=True) all_data.to_excel('all_data.xlsx',index=False) 识别效果:不太理想,文本排序有问题。pdfplumber提取表格效果会更好,但是也有少部分数据可能错行

http模块 之 如何创建一个http服务?

一、如何创建一个http服务: (1)导入http模块 const http=require('http'); (2)创建一个 HTTP 服务器对象 const server=http.createServer((request,response)=>{ // createServer接收一个实参,该实参是一个函数。函数可以是箭头函数匿名函数function等等。 // 该函数包含两个行参。第一个request(请求),接收请求报文的封装对象,借助与它可以获取到请求报文的封装内容。第二个response(响应),是对响应报文的封装对象,可以为浏览器设置响应结果。 // 使用createServer指定每次服务器收到请求时要执行的函数。此函数用于处理来自用户的请求以及返回给用户的响应。 response.end('Hello HTTP Server'); //设置响应内容 end设置响应体 response.setHeader('content-type','text/html;charset=utf-8'); //解决如下哈哈哈文字乱码问题 response.end('哈哈哈'); //设置响应内容 end设置响应体 }) (3)监听端口,启动服务 server.listen(9000,()=>{ console.log('服务已启动...'); }); // listen有两个参数,第一个是端口号,第二个是回调函数,当服务启动成功后执行 二、注意事项 (1)命令行ctrl+c停止服务 (2)当服务启动后,更新代码必须重启服务才能生效 (3)响应内容中文乱码的解决办法 response.setHeader('content-type','text/html;charset=utf-8'); (4)端口号被占用(Error:listen EADDRINUSE: address already in use :::9000) 解决办法:1》关闭当前运行监听窗口的服务 2》修改其他端口号 (5)HTTP协议默认端口号是80,HTTPS协议默认端口号是443,HTTP服务开发常用端口号有3000,8080,8090,9000等等 (6)如果端口被其他程序占用,可以使用资源监视器点击侦听端口,找到占用端口程序,打开任务管理器按照pid排序找到对应的就关闭对应的程序

TCP的三次握手和4次挥手

一、首先讲一下TCP的由来 最开始,人们考虑到将网络信息的呼唤与回应进行规范,达成一种公认的协议,就好像没有交通规则的路口设定交通规则。 人们设计出完美的OSI协议,这个协议包含七个层次由下到上分别是: 物理层,数据链路层,网络层,传输层,会话层,表示层,应用层。 大家都觉得很完美但是现实总是会打破理想,十分现实。 人们发现在使用过程中,没有必要这么繁琐,很多层次也分的不必太清晰可以合并,于是在实践过程中,人们逐渐演变出更实用的TCP/IP协议。 二、三次握手连接,四次挥手断开 画图解释吧更形象 三、总结 3次握手的过程是双方都在准备资源,4次挥手的过程是让之前准备的资源释放。 这个时候可能会产生疑问为什么连接是三次挥手就要四次? 这是因为套接字是全双工的(同时收发数据无影响),所以关的时候要收发都关掉。 不知道有没有同学会跟我一样产生一个疑惑,为什么要客户端先调用close而不是服务器先调用close? 我经过查阅资料学习我们先来追溯一下收发信息原理的源头:TCP为了保证数据的可靠性,一般接收方在收到一个数据“请求断开连接”之后才会给发出方回应一个“收到,这边准备妥当不再接收”信息,但如果一直不回应,发送方就会一直等待回应,为了避免陷入这样一个循环,引入了超时时间机制,谁先调用close,发完消息之后等待一定时间,如果没有收到回应,发送方就再发送一次。但这个时候又出现一个问题,如果接收方给的回应迟了,超出了等待期限范畴,一边已经回应“收到,已准备妥当不再接收”,另一边因为等待时间内没有等到这条消息,会继续发送“请求断开连接”-等待(对方已经关闭接收了)-发-等待-发-等待…这就又陷入了一个循环,为了解决这个问题,我们引入了延时机制,也就是接收方接到断开请求,回复“收到,这边准备妥当不再接收”之后,让它等待约2MSL(MSL就是一个数据包在网络上传输的时间),确定收不到发送方再次发来的断开请求,再真正执行关闭接收操作。现实这段过程大概耗时为两分钟左右,在这段时间内接收方是不被允许释放资源的,这也就意味着这段时间内它所占用的端口不可以被其他程序所调用(程序虽然关了但是端口仍被占用,不利于资源的最大化利用)。这个时候,我们再来想,如果是服务器先调用close,这就意味着服务器先发出断开连接请求,也就意味着它要保留两分钟左右的资源的同时占用这个端口,但我们知道,服务端要绑定固定的端口,客户端不用呀,所以如果是客户端先调用close,它在等待保留资源的时候,操作系统再执行其他操作,分配资源时,端口是自由的,可以紧接着继续分配,达到对资源的最大化利用,刚刚好。所以客户端先调用close而不是服务器先调用close。 上码 import socket def service_client(new_socket): """为这个客户端返回数据""" #1.接收浏览器发送过来的请求,即HTTP发送来的请求 #GET /HTTP/2.0 #... request=new_socket.recv(1024)#一般来说应该空间是够了 print(request) #2.返回HTTP格式的数据给浏览器 #2.1准备发送给浏览器的数据--head就是HTML那些 response="http/2.0 200 OK\r\n"#浏览器不能解析换行符/n,必须使用/r/n的方式 response+="\r\n"#不可或缺的换行符,代表着body即将到来 #2.2准备一些--body部分内容,准备给浏览器送去 #response+="<h1>xixizi</h1>" response+="xixizi" new_socket.send(response.encode("utf-8")) #关闭套接字 new_socket.close() def main(): "用来完成整体的控制" #1.创建套接字 tcp_server_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #2.绑定 tcp_server_socket.bind(("",65534)) #3.变为监听套接字 tcp_server_socket.listen(128) while True: #4.等待新客户端的链接 new_socket,client_addr=tcp_server_socket.accept() #5.为这个客户端服务 service_client(new_socket) #关闭监听套接字 tcp_server_socket.close() if __name__=="__main__": main() 最近很努力在找实习,把尘封已久的知识重新翻出来再温习温习,不问前程,但行脚下

nicetool--替代hutool和fastjson的工具库

前言 如果你被hutool坑过、被fastjson坑过,nicetool帮你解脱! 如果你想用稳定、Spring原生的工具类,nicetool已帮你封装! nicetool不生产工具,只是JDK和Spring的封装侠! 介绍 nicetool:超好用的Java工具类:稳定、方便。最大程度利用SpringBoot原生工具。 官网:https://www.yuque.com/knifeblade/opensource/nicetool gitee:https://gitee.com/knifeedge/nicetool github:https://github.com/knife-blade/nicetool 功能 基本 BeanUtil:Bean工具。功能:对象浅拷贝、对象深拷贝等。(基于Spring原生)JsonUtil:Json工具。功能:JSON字符串转对象、对象转JSON字符串等。(基于Spring原生)PropertyUtil:属性工具。功能:获得值为null的属性名;把对象中的 String 类型的空字段,转换为指定字符串;等。StackTraceUtil:栈追踪工具。功能:获得栈追踪(字符串)等。(基于Java原生)ThrowableUtil:异常工具。功能:获得异常的栈追踪(字符串)等。(基于Java原生)ValidateUtil:校验工具。功能:手动校验对象,等同于@Valid功能。(基于Spring原生) 日期 DateTimeUtil:日期时间工具。功能:格式化LocalDateTime、Date;解析时间字符串为Date;将LocalDateTime转为Date;等等。(基于Java原生) 反射 MethodUtil:方法工具。功能:解析方法详情;将参数解析为Map等。 Spring AopUtil:AOP工具。功能:获得目标类;获得代理Bean;ApplicationContextHolder:持有Spring的ApplicationContext,可以静态调用。例如:ApplicationContextHolder.getContext().getBean(Xxx.class);。(基于Spring原生) web HttpUrlUtil:Url工具。功能:将URL片段拼接为完整URL;将URL转化为参数字符串;将Map参数转为URL等;ClientIpUtil:IP工具。功能:获得调用方IP;获得客户端真实IP等; 快速使用 1.引入依赖 <dependency> <groupId>com.suchtool</groupId> <artifactId>nicetool-spring-boot-starter</artifactId> <version>{newest-version}</version> </dependency> 2.使用 String jsonString = JsonUtil.toJsonString(obj);

三、贪心算法

三、贪心算法 文章目录 三、贪心算法1、找零钱2、求一个数列的极差3、将真分数用埃及分数之和表示4、找到出现最多次数的数5、将给定的整数去掉任意个数字后重新组成最小整数 1、找零钱 #include <stdio.h> int a[7]={100,50,20,10,5,2,1},ns[7]; void main() { /********** Begin **********/ int n;scanf("%d",&n); while(n){ for(int i=0;i<7;i++){ if(n>=a[i]){ n=n-a[i]; ns[i]++; break; } } } for(int i=0;i<7;i++){ printf("%d元 %d张\n",a[i],ns[i]); //cout<<a[i]<<"元 "<<ns[i]<<"张\n"; } /********** End **********/ } 2、求一个数列的极差 #include <stdio.h> void sort(int *a, int n, int asc) { for (int i = 0; i < n - 1; i++) { for (int j = 0; j < n - 1 - i; j++) { if (asc && a[j] > a[j + 1]) { a[j]=a[j+1]^a[j]; a[j+1]=a[j]^a[j+1]; a[j]=a[j+1]^a[j]; } else if (!

蓝桥杯算法基础(20):(快速排序的其他优化)java版

三点中值法 选主元 三点中值法 左,中,右,三个位置,取中间值作为主元,与第一个元素交换 public static int partition(int[] A,int p,int r){ int pivot=A[p]; //优化,在p,r,mid之间,选一个中间作为主元 int midIndex=p+((r-p)<<1);//中间下标 int midValueIndex=-1;//中值的下标 if(A[p]<=A[midIndex]&&A[p]>=A[r]){ midValueIndex=p; }else if(A[r]<A[midIndex]&&A[r]>=A[p]){ midValueIndex=r; }else{ midValueIndex=midIndex; } Util.swap(A,p,midValueIndex)//java中的交换方法 int pivot=A[p]; int left=p+1; int right=r; while(left<=right){ while(left<=right&&A[left]<=pivot)left++; swap(left,right); right--; } } 绝对中值法 //绝对中值:分组,每5个一组,最后一组可能不足5个,每组都排序然后取中间值,再在所有的中间值中再次取中值 //工程中不常用 //获取绝对的中值数,o(N)的样子 public static int getMedian(int[] arr,int p,int r){ int size=r-p+1;//数组长度 //每五个元素一组 int groupSize=(size%5==0)?(size/5):(size/5+1);//每五个一组,最后一组小于等于五 //存储各小组的中值 int medians[]=new int[groupSize]; int indexOfMedains=0; //对每一组进行插入排序 for(int j=0;j<groupSize;j++){ //单独处理最后一组,因为最后一组可能不满5个元素 if(j==groupSize-1){ _3InsertionSort.sort(arr,p+j*5,r);//自己定义的包和sort方法,插入排序,排序最后一组 medians[indexOfMedians++]=arr[(p+j*5+r)/2];//最后一组的中间那个,对最后一组找中间值 }else{ _3InsertionSort.

Java文件大小转换的两种方式

小伙伴们好,欢迎关注,一起学习,无限进步 在程序开发的过程中,文件的大小在视图呈现和数据库存储的过程不一致怎么转换呢 文件大小的单位,在计算机中,文件大小通常使用字节(byte)作为基本单位进行表示。字节是计算机存储最小的单位,每个字节表示8个二进制位(bit)。除了字节,还有一些常用的文件大小单位,如下所示: 千字节(KB):1 KB = 1024 字节 兆字节(MB):1 MB = 1024 KB 吉字节(GB):1 GB = 1024 MB 太字节(TB):1 TB = 1024 GB 方式一 使用第三方依赖库 Apache Commons IO 提供的方法 添加以下依赖 <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-io</artifactId> <version>1.3.2</version> </dependency> 代码示例 import org.apache.commons.io.FileUtils; public class TestFileSize { public static void main(String[] args) { long fileSize = 33931L; String fileSizeStr = FileUtils.byteCountToDisplaySize(fileSize); System.out.println("文件大小:" + fileSizeStr); } } 方式二 自己添加代码写,以下几种转换方式的不同写法,基本都一样,可根据自己需求删减 import java.text.DecimalFormat; import org.apache.commons.io.FileUtils; public class TestFileSize { public static void main(String[] args) { long bytes = 33931L; String fileSizeStr = FileUtils.

同城预约上门服务APP小程序开发 打造快捷便利生活

随着移动互联网的快速发展,人们的生活方式正在发生深刻的变化。特别是在城市生活中,人们越来越依赖移动应用来解决日常生活中的各种问题。其中,同城预约上门服务APP正成为一种新型的生活服务平台,为人们提供了更加便利和快捷的服务。 一、同城预约上门服务APP的发展趋势 随着城市生活节奏的加快,人们对便利性和快捷性的需求越来越高。同城预约上门服务APP正是基于这种需求而产生的。通过APP,用户可以预约各类服务,如家政、美容、维修、教育、医疗等,服务提供者则可以接收到用户的订单信息,并提供上门服务。这种新型的服务模式具有以下几个发展趋势: 上门服务APP 1. 服务内容多样化:随着用户需求的不断增加,同城预约上门服务APP提供的服务内容也越来越多样化。除了传统的家政、美容等服务,还增加了医疗、教育、宠物服务等更多领域。 2. 服务质量标准化:为了提高用户体验和服务质量,同城预约上门服务APP开始注重服务的标准化和规范化。例如,制定服务流程、培训服务人员、建立评价系统等。 3. 数据驱动的个性化服务:通过对用户行为和需求的深度挖掘,同城预约上门服务APP可以为用户提供更加个性化的服务推荐。这不仅可以提高用户满意度,还可以增加服务的销售量。 4. 社交化:未来,同城预约上门服务APP将更加注重用户的社交需求。用户可以发布自己的服务需求和经验,与其他用户进行互动和交流,形成社区化的服务体验。 同城上门服务小程序 二、市场需求与功能特点 同城预约上门服务APP的市场需求主要来自于以下几个方面: 1. 便利性:用户可以随时随地预约所需服务,无需亲自前往实体店或等待特定的服务时间。 2. 快捷性:用户可以快速找到附近的服务提供者,缩短等待时间和服务时间。 3. 优质服务:用户可以通过评价系统和服务流程筛选优质的服务提供者,提高服务质量。 4. 个性化需求:用户可以根据自己的需求选择不同的服务项目和服务级别,满足个性化需求。 基于市场需求,同城预约上门服务APP的功能特点主要包括以下几个方面: 上门服务APP 1. 服务分类与筛选:提供多种分类方式,方便用户查找所需服务,同时支持关键词搜索和筛选功能。 2. 地图定位:支持地图定位功能,方便用户查找附近的服务提供者。 3. 服务评价与反馈:建立完善的评价系统,方便用户对服务提供者进行评价和反馈。 4. 在线支付:支持多种支付方式,方便用户进行在线支付。 5. 消息通知:及时向用户推送订单状态和服务提供者的联系信息。 6. 用户社区:建立用户社区,方便用户进行交流和分享经验。 7. 个性化推荐:根据用户历史数据和行为,为用户推荐个性化的服务项目和优惠活动。 8. 数据统计与分析:对用户行为和订单数据进行统计和分析,为服务提供者提供数据支持。

面向未来的融合:产品管理和 DevOps 如何重新绘制数字蓝图

技术格局正在以惊人的速度发展。组织必须驾驭这种动态环境,以满足不断变化的客户期望和业务挑战。这需要对数字产品的设想、构建和管理方式进行根本性转变。有鉴于此,产品管理和 DevOps 的集成已成为一个关键趋势。这种融合有望加快创新周期,增强以客户为中心,并为团队提供在数字时代蓬勃发展所需的敏捷性。 在本文中,我们分析了这种集成的深度和广度。我们探讨了产品管理和 DevOps 的不同角色、将它们结合在一起所释放的协同效应、经过验证的实施策略,以及这种融合功能的未来。 产品管理:战略愿景和客户拥护 产品管理的角色已逐渐从专注于执行的传统项目经理演变为负责基于客户和市场洞察的产品愿景的战略职能。如今,产品经理深入参与识别市场机会、分析客户痛点以及定义路线图,以便在正确的时间将正确的解决方案推向市场。 一项关键能力是沉浸在客户反馈中,以推动创造愉悦的改进。领先的产品经理还通过阐明产品价值主张来支持销售团队。总之,他们在产品生命周期的每个阶段充当客户倡导者和产品大脑。 DevOps 的兴起:改变软件交付 DevOps 运动从敏捷社区兴起,是对软件开发团队和 IT 运营团队的孤立性质的回应。DevOps 通过桥接开发和运营的实践打破了这些孤岛,以实现更快的发布周期和持续的价值交付。 DevOps 的关键推动因素包括持续集成(频繁地将代码提交到共享存储库)、基础设施即代码(通过代码配置基础设施)、持续部署(自动发布到生产环境)和全面监控。如果有效实施,DevOps 可以大大加快上市速度,同时提高质量、可靠性和快速迭代的能力。 释放集成的力量 随着 DevOps 在整个行业的发展势头,与产品管理的集成释放了一些引人注目的协同效应。 增强协作:将 DevOps 流程与产品管理相结合,促进推动战略优先事项的产品领导者与将功能推向市场的技术团队之间的紧密协作。这增加了对客户最重要的功能与增加技术债务的功能的一致性。更快的创新周期:将客户反馈循环与持续开发/部署相结合,大大加快了从概念到发布的周期。产品创新更快地到达客户手中。更高的业务敏捷性:融合产品和 DevOps 团队拥有工具,可以随着业务条件和竞争威胁的变化快速重新调整优先级并调整产品。 虽然集成带来了巨大的好处,但实现这种协同作用需要克服语言、工具和工作流程差异等障碍。组织必须有目的地构建流程和系统,以实现无摩擦的协作。如果执行得当,这种融合将改写数字剧本。 实施策略 产品管理和 DevOps 的融合需要新的工作方式,并得到正确的文化支柱和实践的支持。 建立一致的团队:在共同任务中统一产品和技术贡献者是关键。灌输整合团队如何更快地取悦客户的愿景,从而促进文化变革。领导者应提高透明度,展示共同所有权,庆祝集体胜利,并投资于跨职能技能建设以实现协同效应。嵌入以客户为中心的实践:通过发现冲刺获取早期产品反馈并将这些见解快速纳入敏捷仪式至关重要。这种由外而内的观点平衡了客户价值与技术观点,确保产品市场契合。通过自动化进行操作: 标准化工具可实现从策略到工作软件的可追溯性,从而减少偏差。CI/CD 自动化与可观察性平台相结合,为业务影响提供了客观的衡量标准。自动化使团队能够专注于创造性的解决方案而不是重复性的任务。 用战略指标评估影响 清晰的 KPI 可以让您持续了解进度,例如: 客户 NPS 分数缩短新功能的上市时间代码部署频率测试覆盖率和质量门正确的措施肯定了客户和业务的利益,同时指出了持续改进的机会。 真实世界的成功故事 行业领导者展示了战略性融合产品管理、软件工程和 IT 运营的积极成果。 在 HubSpot,产品和开发团队之间的紧密合作将产品创意推向市场的平均时间从 9 个多月缩短到不到 3 个月。季度 NPS 分数始终超过 50,表明客户满意度很高。 对于 Microsoft Azure,将闭环客户反馈和指标可见性与快速构建-测量-学习周期相结合,有助于快速发展云平台以对抗竞争对手的产品。Azure 目前占据超过 50% 的市场份额。 第一资本利用产品运营模型,允许产品经理参与日常站立会议,通过其卓越云中心将功能交付与功能交付保持一致。创新步伐的加快和可靠性的提高已经获得了行业的认可。 产品管理 + DevOps 的未来 随着技术创新日益成为竞争差异化的核心,产品管理和 DevOps 的整合将继续加强。

9-sql注入之json注入

文章目录 SQL注入之json注入1.什么是json?json的数据类型: 2.json注入3.案例演示1.php源码:2.进行注入 SQL注入之json注入 本章学习目的: 1.了解什么json数据格式 2.了解json注入的方式 3.了解什么场景下会使用json进行注入 1.什么是json? JSON(JavaScript Object Notation, JS对象简谱)是一种轻量级的数据交换格式。它基于 ECMAScript(European Computer Manufacturers Association, 欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。 json的数据类型: 创建一个json对象 const jsonStr ='{"name":"mc","age":18,"sex":"男"}' const jsonObject = JSON.parse(jsonStr); 输出解析json数据 Object.keys(jsonObject).forEach(item=>{console.log(item,":",jsonObject[item])}) 转换成json字符串 const toJSON = JSON.stringify(jsonObject);console.log(toJSON); 2.json注入 原理:JSON注入是指应用程序所解析的JSON数据来源于不可信赖的数据源,程序没有对这些不可信赖的数据进行验证、过滤,如果应用程序使用未经验证的输入构造JSON,则可以更改JSON 数据的语义。 危害: 攻击者可以利用JSON注入漏洞在JSON数据中插入元素,从而允许JSO数据对业务非常关键的值执行恶意操作,获取管理权限等 严重的可能导致XSS和动态解析代码 防御: 检查程序逻辑,根据实际需求对数据进行合理过滤和安全校验,以避免产生JSON注使用JSON标准对JSON 数据进行处理,防止JSON注入 3.案例演示 1.php源码: <?php // php防止中文乱码 header('content-type:text/html;charset=utf-8'); if(isset($_POST['json'])){ $json_str=$_POST['json']; $json=json_decode($json_str); if(!$json){ die('JSON文档格式有误,请检查'); } $username=$json->username; //$password=$json->password; // 建立mysql连接,root/root连接本地数据库 $mysqli=new mysqli(); $mysqli->connect('localhost','root','root'); if($mysqli->connect_errno){ die('数据库连接失败:'.$mysqli->connect_error); } // 要操作的数据库名,我的数据库是security $mysqli->select_db('security'); if($mysqli->errno){ dir('打开数据库失败:'.

Jmeter进行http接口测试

🍅 视频学习:文末有免费的配套视频可观看 🍅 关注公众号【互联网杂货铺】,回复 1 ,免费获取软件测试全套资料,资料在手,涨薪更快 本文主要针对http接口进行测试,使用 jmeter工具实现。 Jmeter工具设计之初是用于做性能测试的,它在实现对各种接口的调用方面已经做的比较成熟,因此,本次直接使用Jmeter工具来完成对Http接口的测试。 一、开发接口测试案例的整体方案 第一步:我们要分析出测试需求,并拿到开发提供的接口说明文档;第二步:从接口说明文档中整理出接口测试案例,里面要包括详细的入参和出参数据以及明确的格式和检查点。第三步:和开发一起对接口测试案例进行评审。第四步:结合开发库,准备接口测试案例中的入参数据和出参数据,并整理成csv格式的文件。第五步:结合接口测试案例文档和csv格式的数据文档,做接口测试案例的自动化案例开发。 二、接口自动化适用场景 目前设计的自动化接口测试案例有两个运行场景: 1. 测试前置、开发自测:一个新的自动化接口测试案例开发完成后,直接发给接口对应的开发,安排在开发本地环境执行,一旦开发确认完成接口开发,就开始执行接口测试案例,基本上可以实时拿到测试结果,方便开发快速做出判断。【开发本地运行的方式就是打开JMeter工具,导入JMX文件,开始执行可。】 2. 回归测试:开发本地测试通过后,或整个需求手工测试通过后,把自动化的接口测试案例做分类整理,挑选出需要纳入到回归测试中的案例,在持续集成环境重新准备测试数据,并把案例纳入到持续集成的job中来,这些用于回归的接口测试案例需要配置到持续集成平台自动运行。 三、接口测试环境准备 Jdk1.6或以上:Java Downloads | Oracle Jmeter,下载址址:Apache JMeter - Download Apache JMeter 插件的下载安装地址:JMeter Plugins :: JMeter-Plugins.org 四、创建工程 1、打开Jmeter:下载好Jmeter后,双击bin目录下的jmeter.bat文件: 2、添加线程组:在“测试计划”上点击鼠标右键-->添加-->threads(Users)-->线程组,添加测试场景设置组件,接口测试中一般设置为1个“线程数”,根据测试数据的个数设定“循环次数”。 3、添加“HTTP Cookie管理器”: 4、添加“Http请求默认值”组件,当被测系统有唯一的访问域名和端口时,这个组件很好用: 5、在“HTTP 请求默认值”组件配置页面,填写被测系统的域名和端口,http请求的实现包版本以及具体协议类型,线程组里的所有“HTTP Sampler”可默认使用此设置。 6、在“线程组”里添加“HTTP 请求”的Sampler 7、在HTTP请求设置页面,录入被测接口的详细信息,包括请求路径,对应的请求方法,以及随请求一起发送的参数列表: 8、设置检查点:在被测接口对应的“HTTP 请求”上,添加“响应断言” 9、在设置页面上添加对相应结果的正则表达式存在性判断即可: 10、添加监听器:方便查看运行后的结果 运行结果: 上述步骤完成了一个简单测试案例的创建,复杂测试案例均在此基础上扩展完成。使用Jmeter工具开发的接口测试案例,一个子系统建议放在同一个 “测试计划”中,流程测试可以通过“线程组”来区分,这样也便于设定不同的测试数据个数。比较独立的接口,可以统一放在一个线程组内,顺序完成测试。 流程性接口的测试:如果要测试的接口可以组成一个流程,只需要顺序添加多个“HTTP 请求”的Sampler,各请求之间可以提取需要在上下文传递的数据作为参数,以保证流程中数据的一致性。 同时,在这我也准备了一份软件测试视频教程(含接口、自动化、性能等),需要的可以直接在下方观看就行,希望对你有所帮助! 7天Python自动化测试速成课,小白也能快速上手(项目实战)

自动化测试Allure报告使用详解

🍅 视频学习:文末有免费的配套视频可观看 🍅 关注公众号【互联网杂货铺】,回复 1 ,免费获取软件测试全套资料,资料在手,涨薪更快 这一节主要是记录allure的内容以及用法,怎么让他生成一个完整的想要的报告。 allure生成的报告和其他五花八门的报告对比了一下,它的可读性是最好、最直观的。这不仅仅是我想要的效果,也是很多小伙伴想要的结果,毕竟这是给领导看,而且也算是自己老大成果的汇总。 一、Allure相关的内容 Allure用例描述使用方法参数值参数说明@allure.epic()epic描述定义项目、当有多个项目是使用。往下是feature@allure.feature()模块名称用例按照模块区分,有多个模块时给每个起名字 @allure.story()用例名称一个用例的描述@allure.title(用例的标题)用例标题一个用例标题@allure.testcase()测试用例的连接地址自动化用例对应的功能用例存放系统的地址@allure.issue()缺陷地址对应缺陷管理系统里边的缺陷地址@allure.description()用例描述对测试用例的详细描述@allure.step()操作步骤测试用例的操作步骤@allure.severity()用例等级blocker 、critical 、normal 、minor 、trivial@allure.link()定义连接用于定义一个需要在测试报告中展示的连接@allure.attachment()附件添加测试报告附件 总共主要的就以上这些,常用的大概有一半吧 。 二、对于这其中常用的做一些使用实例 代码结构: 登录是一个前置操作 ,拿出来后单独存放,loging.py文件内容: conftest.py这个文件主要放一些公共的内容 # __*__coding:utf-8 __*__ import allure @allure.step("操作步骤: 登录") def longin(): '''登录操作''' print("这个是登录的接口") case----test_case.py文件主要存放一些测试用例,内容如下: # __*__coding:utf-8 __*__ import pytest import allure from common_contion.dome_Interface import * @allure.severity("blocker") @allure.epic("项目名称: 会所资源管理系统") @allure.issue("http://149.335.82.12:8080/zentao/bug-view-1.html") # 禅道bug地址 @allure.testcase("http://149.335.82.12:8080/zentao/testcase-view-5-1.html") # 禅道用例连接地址 @allure.feature("房间管理模块") class Testdome1(object): def test_dome_1(self,login_fixture): '''用例一的用例描述: 我是第一个用例,我只有一个步骤''' print("第一个测试用例") jieko_dome_1() def test_dome_2(self,login_fixture): '''用例二的用例描述: 我是第二个用例,我只有一个步骤''' print("第二个测试用例") jieko_dome_2() @allure.

Java中的 “==” 与 equals 的区别

Java中的 “==” 与 equals 的区别 1.“==” 在Java中有两大类数据类型,一类是基础数据类型共有八种分别是byte、 short、 int、 long、 float、 double、 char、boolean,另一类则是引用数据类型,例如String、Integer等等。 “ == ” 作为比较运算符,是用于比较两个值是否相等的,但是在比较基础数据类型和引用数据类型时是不一样的。 例如以下代码,两个基本类型作比较: int a = 1; int b = 1; System.out.println(a == b); 我们可以看到返回结构为true,说明 a 和 b的值是相同的 那如果比较两个引用数据类型呢? String s1 = new String("abc"); String s2 = new String("abc"); System.out.println(s1 == s2); 我们可以看到,s1 和 s2的值明明都是abc,但比较出来结果确是false,为什么呢? 我们这里new了两个String对象,两个对象存储的地址是不同的,就算是值相同比较出来的结果也一定是false,因为 “==”在比较引用数据类型时比较的是引用(地址)是否相同 综上所述: “ == ” 在比较基本数据类型比较的是值是否相同,而在比较引用数据类型的时候则是比较引用是否相同。 equals equals被定义在了Object类中,Object类是所有类的父类,也就是说所有类都继承于Object,这也是为什么所有类都是可以调用或重写Object中的方法的。 我们通过Object的源码可以看到,equals方法的底层实现仍然是 “ == ”,但我们需要注意一点,equals不能比较两个基本数据类型。 可为什么我们去比较字符串时用equals比较的是两个值是否相等呢,我们可以从String源码中获得答案。 前面说到,所有类都继承于Object类,那也就是说所有的Object子类都是可以重写Object中定义的方法的。这里String就是重写了父类的equals方法从而实现了值得比较,可以看到,进入到这个方法时会先比较引用(地址)是否相同,若地址相同值一定是相同得,随后进行类型判断,若传入得参数类型是String,则继续比较,否则会返回false,若为ture进入判断中将参数转为String类型,比较长度,长度一致则会去遍历字符数组(String底层实现是字符数组,这里就不过多赘述了),若字符串中每个字符都相等则返回true.这样就实现了值得比较。 接下来我们看在Integer中得equals方法是这样的 若参数类型一致则调用intValue方法将参数转为int类型进行比较。 综上所述: equals方法在Object中定义,其底层还是用得“==”去实现的,但是有些对象,例如String、Integer等等,则是重写了equals方法实现了值得比较。

html5播放flv视频

参考:flv-h265 - npmHTML5 FLV Player. Latest version: 1.7.0, last published: 6 months ago. Start using flv-h265 in your project by running `npm i flv-h265`. There are no other projects in the npm registry using flv-h265.https://www.npmjs.com/package/flv-h265 本地安装也可以: npm i -S flv.js <!doctype html> <html> <head> <meta charset="utf-8"> <title> flvjs Demo</title> </head> <body> <video id="videoElement" class="video-js" controls muted autoplay> </video> <script src="https://cdn.bootcdn.net/ajax/libs/flv.js/1.6.2/flv.js"></script> <script> if (flvjs.isSupported()) { var videoElement = document.getElementById('videoElement'); var flvPlayer = flvjs.

每日五道java面试题之springMVC篇(三)

目录: 第一题. @Controller注解的作用第二题. @RequestMapping注解的作用第三题. @ResponseBody注解的作用第四题. @PathVariable和@RequestParam的区别第五题. Spring MVC与Struts2区别 第一题. @Controller注解的作用 在Spring MVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ,然后再把该Model 返回给对应的View 进行展示。在Spring MVC 中提供了一个非常简便的定义Controller 的方法,你无需继承特定的类或实现特定的接口,只需使用@Controller 标记一个类是Controller ,然后使用@RequestMapping 和@RequestParam 等一些注解用以定义URL 请求和Controller 方法之间的映射,这样的Controller 就能被外界访问到。此外Controller 不会直接依赖于HttpServletRequest 和HttpServletResponse 等HttpServlet 对象,它们可以通过Controller 的方法参数灵活的获取到。 @Controller 用于标记在一个类上,使用它标记的类就是一个Spring MVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用了 @RequestMapping 注解。@Controller 只是定义了一个控制器类,而使用@RequestMapping 注解的方法才是真正处理请求的处理器。单单使用@Controller 标记在一个类上还不能真正意义上的说它就是Spring MVC 的一个控制器类,因为这个时候Spring还不认识它。那么要如何做Spring 才能认识它呢?这个时候就需要我们把这个控制器类交给Spring 来管理。有两种方式: 在Spring MVC 的配置文件中定义MyController 的bean 对象。在Spring MVC 的配置文件中告诉Spring 该到哪里去找标记为@Controller 的Controller 控制器。 第二题. @RequestMapping注解的作用 RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。 RequestMapping注解有六个属性,下面我们把她分成三类进行说明(下面有相应示例)。 value, method value: 指定请求的实际地址,指定的地址可以是URI Template 模式(后面将会说明); method: 指定请求的method类型, GET、POST、PUT、DELETE等;

centos防火墙firewall-cmd限定特定的ip访问

文章目录 firewall-cmd是什么?启动firewalld服务查看默认区域关闭端口访问添加富规则firewall-cmd的区域概念firewall-cmd的常用选项通用选项:状态选项:永久选项:区域选项: firewall-cmd是什么? firewall-cmd是centos防火墙的命令行管理客户端,提供了接口来管理运行时和持久的防火墙配置。 在firewalld中,运行时配置与永久配置是分开的。这意味着您可以在运行时配置或永久配置中进行更改。 启动firewalld服务 并设置开机自动启动(如果尚未启动) systemctl enable firewalld systemctl start firewalld 查看默认区域 [root@localhost ~]# firewall-cmd --get-default-zone public 如果不是public,改为public 更改防火墙默认区域为public [root@localhost ~]# firewall-cmd --set-default-zone=public success 关闭端口访问 确保端口关闭。如果已开放则关闭端口。此处区域中的端口如果开放,是所有ip都可以进行访问。 #查询打开的端口 firewall-cmd --zone=public --list-ports 关闭区域端口,如果端口未开启则无需关闭。 #关闭端口9001 firewall-cmd --zone=public --remove-port=9001/tcp --permanent #重新载入一下防火墙设置,使设置生效 firewall-cmd --reload #查询打开的端口 firewall-cmd --zone=public --list-ports 添加富规则 只有富规则能进行精细化限制。区域规则会覆盖掉富规则。 #允许192.168.1.118访问8081端口 firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.118" port protocol="tcp" port="8081" accept' #重新载入一下防火墙设置,使设置生效 firewall-cmd --reload #查看已设置规则 firewall-cmd --zone=public --list-rich-rules 这样就可以限定特定的ip才能访问 查看区域 public (active) target: default icmp-block-inversion: no interfaces: eth0 sources: services: dhcpv6-client ssh ports: protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: rule family="

一道题学会如何使用哈希表

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1: 输入:nums = [1,1,1], k = 2 输出:2 示例 2: 输入:nums = [1,2,3], k = 3 输出:2 题目很简单对吧,理解题目意思就可以暴力把他做出来。 暴力做法:两层for循环 class Solution { public: int subarraySum(vector<int>& nums, int k) { int res=0; for(int i=0;i<nums.size();i++) { int temp=0; for(int j=i;j<nums.size();j++) { temp+=nums[j]; if(temp==k){ res++; } } } return res; } }; 哈希表做法:首先计算一个前缀和,维护一个哈希表(unordered_map)来记录前缀和及其出现的次数。通过在迭代过程中不断更新前缀和,然后查找是否存在符合条件的前缀和(pre - k),来累加符合条件的子数组个数。 class Solution { public: int subarraySum(vector<int>& nums, int k) { int res = 0; // 用于存储符合条件的子数组个数 unordered_map<int, int> mp; // 用于存储前缀和及其出现的次数 int pre = 0; // 当前的前缀和 for (int i = 0; i < nums.

Java获取两个月份之间的所有月份

/** * 获取两个日期之间的所有月份 (年月) * * @param startTime * @param endTime * @return:YYYY-MM */ public static List<String> getMonthBetweenDate(String startTime, String endTime){ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM"); // 声明保存日期集合 List<String> list = new ArrayList<String>(); try { // 转化成日期类型 Date startDate = sdf.parse(startTime); Date endDate = sdf.parse(endTime); //用Calendar 进行日期比较判断 Calendar calendar = Calendar.getInstance(); while (startDate.getTime()<=endDate.getTime()){ // 把日期添加到集合 list.add(sdf.format(startDate)); // 设置日期 calendar.setTime(startDate); //把日期增加一天 calendar.add(Calendar.MONTH, 1); // 获取增加后的日期 startDate=calendar.getTime(); } } catch (ParseException e) { e.

ECMAscript6学习

ECMAscript6介绍 ECMA是一个浏览器脚本标准制定的公司,Netscape 创造了 JavaScript 由于商标原因, 后面ECMA公司取名ECMAscript 1 发布,JavaScript 也就是 ECMAscript.到现在最新的版本是6,简称es6. 新增let 与const let 与const 除了都是快作用域 { } const不同的是声明必须赋值且不能更改。 模版字符串`` var a="AAAAAA"; var str=`<div>${a}${a}</div>`; document.querySelector("#div_1").innerHTML=str; 扩展运算符 …keys,接收参数 function fun1(obj,...keys){ alert(keys[0]);//a } fun1({"name":"php"},"a","b","c") //数组扩展运算法 var arrs=[1,5,4,9,5,3]; //找出数组中最大值 alert(Math.max(...arrs)); 箭头函数 var fun1=(a)=>a*10; var fun2=(a,b)=>a*b; var fun3=(a,b)=>{return a*b}; alert(fun3(10,30)) document.querySelector("#div_1").innerHTML=fun1(10); 数组的扩展 Array.from(); 1.将方法的参数转为数组 function aa(...keys){ console.log(Array.from(keys))} aa(1,2,"qqq") //[1,2,"qqq"] 2.对数组进行遍历处理 console.log(Array.from([1, 2, 3], (x) => x + x)); // Expected output: Array [2, 4, 6] 3.

深度学习神经网络训练环境配置以及演示

🎬个人简介:一个全栈工程师的升级之路! 📋个人专栏:高性能(HPC)开发基础教程 🎀CSDN主页 发狂的小花 🌄人生秘诀:学习的本质就是极致重复! 目录 1 NVIDIA Driver and CUDA cuDNN安装配置 2 TensorRT安装配置 2.1 版本对应 2.2 环境配置解压后进入TensorRT根目录: 2.3 安装python包 2.4 测试 3 训练 1 NVIDIA Driver and CUDA cuDNN安装配置 这三者安装安装顺序是GPU Driver->CUDA->cuDNN,可以参考CUDA环境配置在Ubuntu18 注意:版本要对应 2 TensorRT安装配置 2.1 版本对应 笔者CUDA为12.1.1 因此需要找到对应的TensorRT,官网TensorRT官网 2.2 环境配置 解压后进入TensorRT根目录: (1)环境变量 vi ~/.bashrc 在文件末尾添加一行代码: export LD_LIBRARY_PATH=/home/hubery/lib/TensorRT-8.6.1.6/lib:$LD_LIBRARY_PATH 关闭保存 source ~/.bashrc (2)复制文件到系统路径 把TensorRT根目录中的/lib/下面的文件复制到 /usr/lib/下, 把TensorRT根目录中的/include/下面的文件复制到 /usr/include/下 2.3 安装python包 进入TensorRT根目录下的python/目录下 可以看到多个版本的python包。 因为我之前安装的是python3.10版,所以选择安装文件tensorrt_dispatch-8.6.1-cp310-none-linux_x86_64.whl 执行安装命令: pip install --force-reinstall tensorrt_dispatch-8.6.1-cp310-none-linux_x86_64.whl 2.4 测试 执行无报错