├── .idea ├── PyScript.iml ├── misc.xml └── modules.xml ├── 111.py ├── Docker └── docker_pull_speed.py ├── K8s监测工具 └── Get_PodStatus.py ├── Linux资源监测 └── Get_Linux_Info.py ├── README.md ├── load.py ├── wechat.py ├── 创建目录.py ├── 天气预报推送.py ├── 密码生成器-1.py ├── 文件字符串统计.py ├── 文件拷贝.py ├── 登入脚本.py ├── 站点测试 ├── web_load_tester.py └── 使用说明.md ├── 简易菜单.py └── 网站资源下载 └── download_images.py /.idea/PyScript.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /111.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # _*_ coding:utf-8 _*_ 3 | __author__ = "dqz" 4 | print("hello") -------------------------------------------------------------------------------- /Docker/docker_pull_speed.py: -------------------------------------------------------------------------------- 1 | import docker 2 | import sys 3 | import re 4 | import time 5 | from collections import defaultdict 6 | import requests 7 | from datetime import datetime 8 | from colorama import init, Fore, Style 9 | from rich.console import Console 10 | from rich.table import Table 11 | 12 | # 需要安装的模块:pip install docker requests colorama rich 13 | 14 | 15 | # 初始化 colorama 16 | init(autoreset=True) 17 | 18 | def format_size(bytes): 19 | """ 20 | 格式化字节数为可读的单位 21 | """ 22 | for unit in ['B', 'KB', 'MB', 'GB', 'TB']: 23 | if bytes < 1024: 24 | formatted = f"{bytes:.2f}{unit}" 25 | return formatted 26 | bytes /= 1024 27 | formatted = f"{bytes:.2f}PB" 28 | return formatted 29 | 30 | def parse_size(size_str): 31 | """ 32 | 解析大小字符串,将其转换为字节数。 33 | 例如:'500kB' -> 500 * 1024 34 | """ 35 | size_str = size_str.strip() 36 | match = re.match(r'([\d\.]+)([KMGTP]?B)', size_str, re.IGNORECASE) 37 | if not match: 38 | return 0 39 | number, unit = match.groups() 40 | number = float(number) 41 | unit_multipliers = { 42 | 'B': 1, 43 | 'KB': 1024, 44 | 'MB': 1024**2, 45 | 'GB': 1024**3, 46 | 'TB': 1024**4, 47 | 'PB': 1024**5, 48 | } 49 | return number * unit_multipliers.get(unit.upper(), 1) 50 | 51 | def get_public_ip_info(): 52 | """获取本机的公网IP地址、地理区域和运营商""" 53 | try: 54 | # 获取公网IP地址 55 | ip_response = requests.get('http://members.3322.org/dyndns/getip', timeout=5) 56 | if ip_response.status_code == 200: 57 | ip = ip_response.text.strip() 58 | # 验证IP格式 59 | if re.match(r'\d+\.\d+\.\d+\.\d+', ip): 60 | # 获取地理位置信息,使用 ip-api.com 61 | geo_response = requests.get(f'http://ip-api.com/json/{ip}?lang=zh-CN', timeout=5) 62 | if geo_response.status_code == 200: 63 | geo_data = geo_response.json() 64 | if geo_data['status'] == 'success': 65 | region = f"{geo_data.get('regionName', '')} {geo_data.get('city', '')}" 66 | isp = geo_data.get('isp', '未知运营商') 67 | return ip, region.strip(), isp 68 | else: 69 | return ip, '无法获取区域信息', '无法获取运营商信息' 70 | else: 71 | return ip, '无法获取区域信息', '无法获取运营商信息' 72 | else: 73 | return '未知', '无法解析公网IP', '无法获取运营商信息' 74 | else: 75 | return '未知', '无法获取公网IP', '无法获取运营商信息' 76 | except Exception as e: 77 | return '未知', f"无法获取公网IP及区域信息: {e}", '无法获取运营商信息' 78 | 79 | def docker_pull_with_speed(image): 80 | try: 81 | client = docker.from_env() 82 | except docker.errors.DockerException as e: 83 | print(f"{Fore.RED}无法连接到Docker守护进程。请确保Docker已安装并正在运行。") 84 | sys.exit(1) 85 | 86 | # 检查镜像是否已存在 87 | try: 88 | existing_image = client.images.get(image) 89 | print(f"{Fore.GREEN}镜像 {Fore.YELLOW}{image} {Fore.GREEN}已存在,无需拉取。") 90 | return 91 | except docker.errors.ImageNotFound: 92 | pass # 镜像不存在,继续拉取 93 | except docker.errors.APIError as e: 94 | print(f"{Fore.RED}无法检查镜像是否存在:{e.explanation}") 95 | sys.exit(1) 96 | 97 | # 如果用户没有指定标签,默认使用 'latest' 98 | if ':' not in image: 99 | image += ':latest' 100 | print(f"{Fore.YELLOW}未指定标签,默认使用 'latest' 标签。") 101 | 102 | # 使用低级 API 以便获取详细的拉取信息 103 | low_level_client = docker.APIClient(base_url='unix://var/run/docker.sock') 104 | 105 | print(f"{Fore.CYAN}开始拉取镜像: {Fore.YELLOW}{image}") 106 | 107 | # 获取并显示公网IP地址、区域和运营商 108 | ip_address, region, isp = get_public_ip_info() 109 | 110 | # 使用 rich 来显示美化的表格 111 | console = Console() 112 | table = Table(show_header=True, header_style="bold cyan") 113 | table.add_column("IP地址", style="yellow", justify="center") 114 | table.add_column("IP区域", style="yellow", justify="center") 115 | table.add_column("运营商", style="yellow", justify="center") 116 | 117 | table.add_row(f"[bold yellow]{ip_address}[/]", f"[bold yellow]{region}[/]", f"[bold yellow]{isp}[/]") 118 | 119 | console.print(table) 120 | 121 | # 打印开始时间 122 | start_time = time.time() 123 | start_datetime = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 124 | print(f"{Fore.GREEN}开始时间: {start_datetime}") 125 | 126 | # 初始化变量 127 | total_downloaded = 0 128 | layer_downloaded = defaultdict(float) # 存储每个层已下载的字节数 129 | layer_totals = defaultdict(float) # 存储每个层的总字节数 130 | 131 | try: 132 | for line in low_level_client.pull(image, stream=True, decode=True): 133 | if 'status' in line: 134 | status = line['status'] 135 | id = line.get('id', '') 136 | progress_detail = line.get('progressDetail', {}) 137 | current = progress_detail.get('current', 0) 138 | total = progress_detail.get('total', 0) 139 | 140 | if 'Downloading' in status or 'Extracting' in status: 141 | if id: 142 | if current > layer_downloaded[id]: # 更新递增的下载量 143 | layer_downloaded[id] = current 144 | layer_totals[id] = total 145 | 146 | # 计算总已下载字节数 147 | total_downloaded = sum(layer_downloaded.values()) 148 | 149 | # 计算下载速度 150 | current_time = time.time() 151 | elapsed_time = current_time - start_time 152 | if elapsed_time > 0: 153 | speed = total_downloaded / elapsed_time 154 | else: 155 | speed = 0 156 | 157 | # 显示进度和速度 158 | total_formatted = format_size(total_downloaded) 159 | speed_formatted = format_size(speed) 160 | 161 | # 构建输出字符串,并添加 '\033[K' 清除行尾 162 | output_str = (f"\r{Fore.MAGENTA}已下载: {Fore.YELLOW}{total_formatted} | " 163 | f"{Fore.CYAN}速度: {Fore.YELLOW}{speed_formatted}/s\033[K") 164 | # 使用 sys.stdout.write 输出并刷新 165 | sys.stdout.write(output_str) 166 | sys.stdout.flush() 167 | 168 | print(f"\n{Fore.GREEN}镜像拉取完成。") 169 | 170 | # 计算并显示结束时间和总耗时 171 | end_time = time.time() 172 | end_datetime = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 173 | total_time = end_time - start_time 174 | print(f"{Fore.GREEN}结束时间: {end_datetime}") 175 | print(f"{Fore.GREEN}总耗时: {Fore.YELLOW}{total_time:.2f} 秒") 176 | 177 | except docker.errors.APIError as e: 178 | print(f"\n{Fore.RED}发生错误: {e.explanation}") 179 | except KeyboardInterrupt: 180 | print(f"\n{Fore.RED}用户中断操作。") 181 | finally: 182 | client.close() 183 | 184 | def main(): 185 | print(f"{Fore.BLUE}欢迎使用 Docker 镜像拉取速度监控脚本!") 186 | image_input = input(f"{Fore.BLUE}请输入要拉取的 Docker 镜像名称和标签(例如:ubuntu:latest):{Style.RESET_ALL}").strip() 187 | if not image_input: 188 | print(f"{Fore.RED}镜像名称不能为空。") 189 | sys.exit(1) 190 | 191 | # 如果用户没有指定标签,默认使用 'latest' 192 | if ':' not in image_input: 193 | image_input += ':latest' 194 | print(f"{Fore.YELLOW}未指定标签,默认使用 'latest' 标签。") 195 | 196 | docker_pull_with_speed(image_input) 197 | 198 | if __name__ == "__main__": 199 | main() 200 | -------------------------------------------------------------------------------- /K8s监测工具/Get_PodStatus.py: -------------------------------------------------------------------------------- 1 | import smtplib 2 | from email.mime.text import MIMEText 3 | from kubernetes import client, config 4 | import time 5 | 6 | # 配置 K8s API 客户端 7 | config.load_kube_config() 8 | v1 = client.CoreV1Api() 9 | 10 | # 邮件通知配置 11 | smtp_server = 'smtp.example.com' 12 | smtp_port = 587 13 | smtp_user = 'user@example.com' 14 | smtp_password = 'password' 15 | mail_from = 'user@example.com' 16 | mail_to = ['user1@example.com', 'user2@example.com'] 17 | mail_subject = 'K8s Pod 监控告警' 18 | 19 | # 监控循环 20 | while True: 21 | # 获取所有运行中的 Pod 22 | pods = v1.list_pod_for_all_namespaces(watch=False) 23 | # 统计运行中和失败的 Pod 数量 24 | running_pods = 0 25 | failed_pods = 0 26 | for pod in pods.items: 27 | if pod.status.phase == 'Running': 28 | running_pods += 1 29 | elif pod.status.phase == 'Failed': 30 | failed_pods += 1 31 | 32 | # 发送邮件通知 33 | if failed_pods > 0: 34 | mail_body = f"当前共有 {running_pods+failed_pods} 个 Pod,其中 {failed_pods} 个 Pod 处于失败状态。" 35 | msg = MIMEText(mail_body) 36 | msg['From'] = mail_from 37 | msg['To'] = ', '.join(mail_to) 38 | msg['Subject'] = mail_subject 39 | smtp = smtplib.SMTP(smtp_server, smtp_port) 40 | smtp.starttls() 41 | smtp.login(smtp_user, smtp_password) 42 | smtp.sendmail(mail_from, mail_to, msg.as_string()) 43 | smtp.quit() 44 | 45 | # 等待 5 分钟后再次检查 46 | time.sleep(300) 47 | -------------------------------------------------------------------------------- /Linux资源监测/Get_Linux_Info.py: -------------------------------------------------------------------------------- 1 | import psutil 2 | import smtplib 3 | from email.mime.text import MIMEText 4 | from email.header import Header 5 | 6 | # 定义邮件发送信息 7 | mail_host = 'smtp.example.com' # 发件人邮箱SMTP服务器地址 8 | mail_user = 'your_email@example.com' # 发件人邮箱账号 9 | mail_pass = 'your_password' # 发件人邮箱密码 10 | receivers = ['recipient1@example.com', 'recipient2@example.com'] # 收件人邮箱账号 11 | 12 | # 获取系统资源使用情况 13 | cpu_percent = psutil.cpu_percent(interval=1) # CPU占用率 14 | memory = psutil.virtual_memory() # 内存使用情况 15 | memory_percent = memory.percent # 内存使用率 16 | memory_used = round(memory.used / 1024 / 1024 / 1024, 2) # 内存使用量(GB) 17 | memory_total = round(memory.total / 1024 / 1024 / 1024, 2) # 内存总量(GB) 18 | disk = psutil.disk_usage('/') # 磁盘使用情况 19 | disk_percent = disk.percent # 磁盘使用率 20 | disk_used = round(disk.used / 1024 / 1024 / 1024, 2) # 磁盘使用量(GB) 21 | disk_total = round(disk.total / 1024 / 1024 / 1024, 2) # 磁盘总量(GB) 22 | 23 | # 构造邮件内容 24 | mail_content = f""" 25 |

系统资源使用情况

26 |

CPU占用率:{cpu_percent}%

27 |

内存使用率:{memory_percent}%

28 |

内存使用量:{memory_used}GB

29 |

内存总量:{memory_total}GB

30 |

磁盘使用率:{disk_percent}%

31 |

磁盘使用量:{disk_used}GB

32 |

磁盘总量:{disk_total}GB

33 | """ 34 | 35 | # 构造邮件 36 | message = MIMEText(mail_content, 'html', 'utf-8') 37 | message['From'] = Header(mail_user) 38 | message['To'] = Header(','.join(receivers)) 39 | subject = 'Linux系统资源使用情况' 40 | message['Subject'] = Header(subject) 41 | 42 | try: 43 | # 发送邮件 44 | smtpObj = smtplib.SMTP() 45 | smtpObj.connect(mail_host, 25) 46 | smtpObj.login(mail_user, mail_pass) 47 | smtpObj.sendmail(mail_user, receivers, message.as_string()) 48 | smtpObj.quit() 49 | print("邮件发送成功") 50 | except smtplib.SMTPException as e: 51 | print("邮件发送失败:", e) 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python代码 2 | -------------------------------------------------------------------------------- /load.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding:utf-8 -*- - 3 | import os, time 4 | 5 | last_worktime=0 6 | last_idletime=0 7 | 8 | def get_cpu(): 9 | global last_worktime, last_idletime 10 | f=open("/proc/stat","r") 11 | line="" 12 | while not "cpu " in line: line=f.readline() 13 | f.close() 14 | spl=line.split(" ") 15 | worktime=int(spl[2])+int(spl[3])+int(spl[4]) 16 | idletime=int(spl[5]) 17 | dworktime=(worktime-last_worktime) 18 | didletime=(idletime-last_idletime) 19 | rate=float(dworktime)/(didletime+dworktime) 20 | last_worktime=worktime 21 | last_idletime=idletime 22 | if(last_worktime==0): return 0 23 | return rate 24 | 25 | def get_mem_usage_percent(): 26 | try: 27 | f = open('/proc/meminfo', 'r') 28 | for line in f: 29 | if line.startswith('MemTotal:'): 30 | mem_total = int(line.split()[1]) 31 | elif line.startswith('MemFree:'): 32 | mem_free = int(line.split()[1]) 33 | elif line.startswith('Buffers:'): 34 | mem_buffer = int(line.split()[1]) 35 | elif line.startswith('Cached:'): 36 | mem_cache = int(line.split()[1]) 37 | elif line.startswith('SwapTotal:'): 38 | vmem_total = int(line.split()[1]) 39 | elif line.startswith('SwapFree:'): 40 | vmem_free = int(line.split()[1]) 41 | else: 42 | continue 43 | f.close() 44 | except: 45 | return None 46 | physical_percent = usage_percent(mem_total - (mem_free + mem_buffer + mem_cache), mem_total) 47 | virtual_percent = 0 48 | if vmem_total > 0: 49 | virtual_percent = usage_percent((vmem_total - vmem_free), vmem_total) 50 | return physical_percent, virtual_percent 51 | 52 | def usage_percent(use, total): 53 | try: 54 | ret = (float(use) / total) * 100 55 | except ZeroDivisionError: 56 | raise Exception("ERROR - zero division error") 57 | return ret 58 | 59 | statvfs = os.statvfs('/') 60 | 61 | total_disk_space = statvfs.f_frsize * statvfs.f_blocks 62 | free_disk_space = statvfs.f_frsize * statvfs.f_bfree 63 | disk_usage = (total_disk_space - free_disk_space) * 100.0 / total_disk_space 64 | disk_usage = int(disk_usage) 65 | disk_tip = "硬盘空间使用率(最大100%):"+str(disk_usage)+"%" 66 | print(disk_tip) 67 | 68 | mem_usage = get_mem_usage_percent() 69 | mem_usage = int(mem_usage[0]) 70 | mem_tip = "物理内存使用率(最大100%):"+str(mem_usage)+"%" 71 | print(mem_tip) 72 | 73 | cpu_usage = int(get_cpu()*100) 74 | cpu_tip = "CPU使用率(最大100%):"+str(cpu_usage)+"%" 75 | print(cpu_tip) 76 | 77 | load_average = os.getloadavg() 78 | load_tip = "系统负载(三个数值中有一个超过3就是高):"+str(load_average) 79 | print(load_tip) 80 | -------------------------------------------------------------------------------- /wechat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | import requests 4 | import json 5 | import sys 6 | import os 7 | 8 | headers = {'Content-Type': 'application/json;charset=utf-8'} 9 | api_url = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=c4f1290a-xxx" 10 | 11 | def msg(text): 12 | json_text= { 13 | "msgtype": "text", 14 | "text": { 15 | "content": text 16 | }, 17 | } 18 | print requests.post(api_url,json.dumps(json_text),headers=headers).content 19 | 20 | if __name__ == '__main__': 21 | text = sys.argv[1] 22 | msg(text) 23 | -------------------------------------------------------------------------------- /创建目录.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # _*_ coding:utf-8 _*_ 3 | __author__ = "dqz" 4 | import os 5 | aa = input("输入路径:") 6 | os.makedirs(aa) 7 | -------------------------------------------------------------------------------- /天气预报推送.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import datetime 4 | 5 | # 获取当前日期 6 | today = datetime.date.today().strftime("%Y-%m-%d") 7 | 8 | # 输入城市名称(拼音) 9 | city = input("请输入城市名称(拼音):") 10 | 11 | # 从API获取天气信息 12 | response = requests.get(f"https://tianqiapi.com/free/day?appid=你的API密钥&appsecret=你的API密钥&city={city}&date={today}") 13 | 14 | # 转换JSON格式 15 | weather_info = json.loads(response.text) 16 | 17 | # 提取需要的信息 18 | date = weather_info["date"] 19 | week = weather_info["week"] 20 | wea = weather_info["wea"] 21 | tem = weather_info["tem"] 22 | win = weather_info["win"] 23 | air = weather_info["air"] 24 | humidity = weather_info["humidity"] 25 | 26 | # 构建消息体 27 | message = f"今天是{date} {week},{city}天气为{wea},温度为{tem}℃,风向是{win},空气质量为{air},湿度为{humidity}%。" 28 | 29 | # 发送消息到企业微信机器人 30 | webhook_url = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=你的Webhook Key" 31 | data = { 32 | "msgtype": "text", 33 | "text": { 34 | "content": message 35 | } 36 | } 37 | response = requests.post(url=webhook_url, data=json.dumps(data)) 38 | print(response.text) 39 | -------------------------------------------------------------------------------- /密码生成器-1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # _*_ coding:utf-8 _*_ 3 | __author__ = "dqz" 4 | import string 5 | import random 6 | pwd = '' 7 | all_choise = string.ascii_letters + string.digits 8 | 9 | for i in range(8): 10 | pwd += random.choice(all_choise) 11 | 12 | print(pwd) -------------------------------------------------------------------------------- /文件字符串统计.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # _*_ coding:utf-8 _*_ 3 | __author__ = "dqz" 4 | file = input("请输入要统计的文件路径:") 5 | def filezs(s): 6 | chare = len(s) #统计有多少个字符 7 | words = len(s.split()) #以空格做分隔,统计单词数 8 | lines = s.count('\n') #/n表示回车,统计出多少行 9 | print(lines,words,chare) 10 | if __name__ == '__main__': 11 | s = open(file).read() #open打开文件,read读取文件 12 | 13 | filezs(s) 14 | -------------------------------------------------------------------------------- /文件拷贝.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # _*_ coding:utf-8 _*_ 3 | __author__ = "dqz" 4 | #让用户输入的备份的路径和存放的路径 5 | yuan = input("请输入备份的路径:") 6 | mubiao = input("请输入目标路径:") 7 | 8 | #定义个函数 9 | def bf(x,y): 10 | s = open(yuan,'r') 11 | d = open(mubiao,'w') 12 | for i in s: 13 | d.write(i) 14 | d.flush() 15 | s.close() 16 | d.close() 17 | 18 | #调用函数 19 | bf(x=yuan,y=mubiao) 20 | -------------------------------------------------------------------------------- /登入脚本.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # _*_ coding:utf-8 _*_ 3 | __author__ = "dqz" 4 | #引用函数getpass 实现密码输入的隐藏 5 | import getpass 6 | name = input("输入用户名:") 7 | password = input("输入密码:") 8 | no = 0 9 | while True: 10 | if name == 'tom' and password =='123': 11 | print("登入成功") 12 | break 13 | else: 14 | no += 1 15 | print("登入失败%s次" %no) 16 | name = input("用户输入错误,重新输入:") 17 | password = input("密码输入错误,重新输入:") 18 | 19 | if no == 2: 20 | print("登入失败") 21 | break -------------------------------------------------------------------------------- /站点测试/web_load_tester.py: -------------------------------------------------------------------------------- 1 | """ 2 | Async Web Load Tester (AWLT) 3 | ---------------------------- 4 | 一个异步的网站负载测试工具,用于评估网站性能和承载能力。 5 | 6 | 特性: 7 | - 支持高并发异步请求 8 | - 详细的性能指标统计 9 | - 实时进度显示 10 | - 完整的错误追踪 11 | - 可配置的测试参数 12 | 13 | 作者: [Ding Qinzheng] 14 | 版本: 1.0.0 15 | 日期: [2024-10-30] 16 | 许可: MIT 17 | """ 18 | 19 | import asyncio 20 | import aiohttp 21 | import time 22 | import argparse 23 | from datetime import datetime 24 | from collections import defaultdict 25 | import statistics 26 | 27 | class LoadTester: 28 | def __init__(self, url, total_requests, concurrent_requests, timeout=30): 29 | self.url = url 30 | self.total_requests = total_requests 31 | self.concurrent_requests = concurrent_requests 32 | self.timeout = timeout 33 | self.results = [] 34 | self.errors = defaultdict(int) 35 | self.start_time = None 36 | self.end_time = None 37 | 38 | async def make_request(self, session, request_id): 39 | start_time = time.time() 40 | try: 41 | async with session.get(self.url) as response: 42 | response_time = time.time() - start_time 43 | status = response.status 44 | if status != 200: 45 | self.errors[status] += 1 46 | return { 47 | 'request_id': request_id, 48 | 'status': status, 49 | 'response_time': response_time 50 | } 51 | except Exception as e: 52 | self.errors[str(e)] += 1 53 | return { 54 | 'request_id': request_id, 55 | 'status': 'error', 56 | 'response_time': time.time() - start_time, 57 | 'error': str(e) 58 | } 59 | 60 | async def run_batch(self, start_id): 61 | connector = aiohttp.TCPConnector(limit=None, ssl=False) 62 | timeout = aiohttp.ClientTimeout(total=self.timeout) 63 | async with aiohttp.ClientSession(connector=connector, timeout=timeout) as session: 64 | tasks = [] 65 | for i in range(self.concurrent_requests): 66 | request_id = start_id + i 67 | if request_id < self.total_requests: 68 | tasks.append(self.make_request(session, request_id)) 69 | return await asyncio.gather(*tasks) 70 | 71 | async def run_test(self): 72 | print(f"\n开始测试 URL: {self.url}") 73 | print(f"总请求数: {self.total_requests}") 74 | print(f"并发数: {self.concurrent_requests}") 75 | print("测试进行中...\n") 76 | 77 | self.start_time = datetime.now() 78 | 79 | for i in range(0, self.total_requests, self.concurrent_requests): 80 | batch_results = await self.run_batch(i) 81 | self.results.extend(batch_results) 82 | 83 | # 显示进度 84 | completed = min(i + self.concurrent_requests, self.total_requests) 85 | progress = (completed / self.total_requests) * 100 86 | print(f"\r进度: {progress:.1f}% ({completed}/{self.total_requests})", end="") 87 | 88 | self.end_time = datetime.now() 89 | print("\n\n测试完成!") 90 | self.print_results() 91 | 92 | def print_results(self): 93 | # 计算统计数据 94 | response_times = [r['response_time'] for r in self.results if r['status'] == 200] 95 | if not response_times: 96 | print("没有成功的请求!") 97 | return 98 | 99 | successful_requests = len(response_times) 100 | failed_requests = len(self.results) - successful_requests 101 | total_time = (self.end_time - self.start_time).total_seconds() 102 | 103 | print("\n=== 测试结果摘要 ===") 104 | print(f"测试持续时间: {total_time:.2f} 秒") 105 | print(f"成功请求数: {successful_requests}") 106 | print(f"失败请求数: {failed_requests}") 107 | print(f"实际RPS (Requests Per Second): {len(self.results) / total_time:.2f}") 108 | 109 | if response_times: 110 | print(f"\n响应时间统计 (秒):") 111 | print(f"最小: {min(response_times):.3f}") 112 | print(f"最大: {max(response_times):.3f}") 113 | print(f"平均: {statistics.mean(response_times):.3f}") 114 | print(f"中位数: {statistics.median(response_times):.3f}") 115 | 116 | # 计算百分位数 117 | percentiles = [50, 75, 90, 95, 99] 118 | sorted_times = sorted(response_times) 119 | for p in percentiles: 120 | index = int(len(sorted_times) * (p / 100)) 121 | print(f"P{p}: {sorted_times[index]:.3f}") 122 | 123 | if self.errors: 124 | print("\n错误统计:") 125 | for error, count in self.errors.items(): 126 | print(f"{error}: {count} 次") 127 | 128 | def main(): 129 | parser = argparse.ArgumentParser(description='Website Load Testing Tool') 130 | parser.add_argument('url', help='要测试的网站URL') 131 | parser.add_argument('-n', '--requests', type=int, default=100, help='总请求数 (默认: 100)') 132 | parser.add_argument('-c', '--concurrent', type=int, default=10, help='并发请求数 (默认: 10)') 133 | parser.add_argument('-t', '--timeout', type=int, default=30, help='请求超时时间(秒) (默认: 30)') 134 | 135 | args = parser.parse_args() 136 | 137 | # 安全提示 138 | print("\n=== 安全提示 ===") 139 | print("1. 请确保您有权限对目标网站进行负载测试") 140 | print("2. 建议在测试环境中使用此工具") 141 | print("3. 过度的负载测试可能会影响服务器性能") 142 | print("4. 请负责任地使用此工具\n") 143 | 144 | confirm = input("您确认要继续测试吗? (yes/no): ") 145 | if confirm.lower() != 'yes': 146 | print("测试已取消") 147 | return 148 | 149 | tester = LoadTester(args.url, args.requests, args.concurrent, args.timeout) 150 | asyncio.run(tester.run_test()) 151 | 152 | if __name__ == '__main__': 153 | main() 154 | -------------------------------------------------------------------------------- /站点测试/使用说明.md: -------------------------------------------------------------------------------- 1 | ## 使用示例: 2 | 3 | ### 基本使用: 4 | 5 | ```bash 6 | python web_load_tester.py https://example.com -n 1000 -c 100 7 | ``` 8 | 9 | ### 使用 POST 方法并添加自定义头部: 10 | ```bash 11 | python web_load_tester.py https://example.com/api -m POST -H "Content-Type: application/json" -H "Authorization: Bearer " -n 500 -c 50 12 | ``` 13 | 14 | ### 导出结果为 CSV 文件: 15 | ```bash 16 | python web_load_tester.py https://example.com -n 1000 -c 100 -o results.csv 17 | ``` 18 | 19 | ### 禁用 SSL 证书验证: 20 | 21 | ```bash 22 | python web_load_tester.py https://example.com -n 1000 -c 100 --no-ssl-verify 23 | ``` 24 | 25 | ### 启用逐步增加负载: 26 | ```bash 27 | python web_load_tester.py https://example.com -n 1000 -c 100 --ramp-up 60 28 | ``` 29 | 30 | ### 设置失败请求的最大重试次数: 31 | ```bash 32 | python web_load_tester.py https://example.com -n 1000 -c 100 --retries 3 33 | ``` 34 | 35 | ### 使用配置文件: 36 | ```bash 37 | python web_load_tester.py --config config.yaml 38 | ``` 39 | -------------------------------------------------------------------------------- /简易菜单.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # _*_ coding:utf-8 _*_ 3 | __author__ = "dqz" 4 | x = "" 5 | cd = """1、矿泉水 6 | 2、可口可乐 7 | """ 8 | while not x: 9 | print("请选择以下菜单内容:") 10 | x = input(cd) 11 | if x == "1": 12 | print("矿泉水:3.5元") 13 | elif x == "2": 14 | print("可口可乐:5元") 15 | -------------------------------------------------------------------------------- /网站资源下载/download_images.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import os 3 | import time 4 | import re 5 | from requests.adapters import HTTPAdapter 6 | from requests.packages.urllib3.util.retry import Retry 7 | 8 | def create_session(): 9 | """ 10 | 创建一个带有重试机制的会话 11 | """ 12 | session = requests.Session() 13 | 14 | retry_strategy = Retry( 15 | total=3, 16 | backoff_factor=1, 17 | status_forcelist=[500, 502, 503, 504] 18 | ) 19 | 20 | adapter = HTTPAdapter(max_retries=retry_strategy) 21 | session.mount("http://", adapter) 22 | session.mount("https://", adapter) 23 | 24 | session.headers.update({ 25 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', 26 | 'Accept': 'image/webp,image/apng,image/*,*/*;q=0.8', 27 | 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8' 28 | }) 29 | 30 | return session 31 | 32 | def extract_pattern(url): 33 | """ 34 | 从示例URL中提取模式 35 | """ 36 | # 查找包含数字的部分 37 | pattern = re.search(r'(_\d{3}_)', url) 38 | if not pattern: 39 | raise ValueError("无法从URL中识别出编号模式!请确保URL中包含类似'_001_'的数字编号。") 40 | 41 | # 替换数字部分为占位符 42 | pattern_str = url.replace(pattern.group(), '_{:03d}_') 43 | return pattern_str 44 | 45 | def download_image(session, url_pattern, number): 46 | """ 47 | 下载指定编号的图片 48 | 49 | Args: 50 | session: 请求会话 51 | url_pattern: URL模式字符串 52 | number (int): 图片编号 53 | """ 54 | # 使用提供的模式生成URL 55 | url = url_pattern.format(number) 56 | 57 | try: 58 | print(f"正在下载: {url}") 59 | response = session.get(url, timeout=15) 60 | 61 | if response.status_code == 200: 62 | if 'image' in response.headers.get('Content-Type', ''): 63 | if not os.path.exists('downloaded_images'): 64 | os.makedirs('downloaded_images') 65 | 66 | # 从URL中提取文件名 67 | filename = url.split('/')[-1] 68 | save_path = os.path.join('downloaded_images', filename) 69 | 70 | with open(save_path, 'wb') as f: 71 | f.write(response.content) 72 | 73 | print(f"✓ 成功下载图片: {filename}") 74 | return True 75 | else: 76 | print(f"✗ 错误: URL返回的不是图片内容") 77 | else: 78 | print(f"✗ 错误: 状态码 {response.status_code}") 79 | 80 | except requests.exceptions.RequestException as e: 81 | print(f"✗ 下载失败: {e}") 82 | 83 | return False 84 | 85 | def get_number_range(): 86 | """ 87 | 获取用户输入的数字范围 88 | """ 89 | while True: 90 | try: 91 | range_input = input("请输入下载范围(格式:起始编号-结束编号,例如1-6): ") 92 | start, end = map(int, range_input.split('-')) 93 | if start > end: 94 | print("起始编号不能大于结束编号!") 95 | continue 96 | if start < 1: 97 | print("起始编号不能小于1!") 98 | continue 99 | if end > 999: 100 | print("结束编号不能大于999!") 101 | continue 102 | return start, end 103 | except ValueError: 104 | print("格式错误!请使用正确的格式,例如:1-6") 105 | 106 | def main(): 107 | """ 108 | 主函数:处理用户输入并下载图片 109 | """ 110 | try: 111 | # 获取示例URL 112 | example_url = input("请输入示例URL(包含编号,例如: https://example.com/image_001.png): ") 113 | 114 | # 获取下载范围 115 | start_num, end_num = get_number_range() 116 | 117 | # 提取URL模式 118 | url_pattern = extract_pattern(example_url) 119 | print(f"\n识别到的URL模式: {url_pattern}") 120 | print(f"将下载范围: {start_num} 到 {end_num}\n") 121 | 122 | # 确认 123 | confirm = input("是否确认开始下载?(y/n): ") 124 | if confirm.lower() != 'y': 125 | print("已取消下载") 126 | return 127 | 128 | print("\n=== 开始下载图片 ===") 129 | session = create_session() 130 | success_count = 0 131 | total_count = end_num - start_num + 1 132 | 133 | for i in range(start_num, end_num + 1): 134 | retry_count = 3 135 | while retry_count > 0: 136 | if download_image(session, url_pattern, i): 137 | success_count += 1 138 | break 139 | retry_count -= 1 140 | if retry_count > 0: 141 | print(f"将在2秒后重试... (剩余重试次数: {retry_count})") 142 | time.sleep(2) 143 | 144 | # 每张图片下载之间暂停1秒 145 | if i < end_num: 146 | time.sleep(1) 147 | 148 | print("\n=== 下载任务完成 ===") 149 | print(f"成功下载: {success_count}/{total_count} 张图片") 150 | print(f"图片保存在 'downloaded_images' 文件夹中") 151 | 152 | except KeyboardInterrupt: 153 | print("\n\n下载已被用户中断") 154 | except Exception as e: 155 | print(f"\n发生错误: {e}") 156 | 157 | if __name__ == "__main__": 158 | main() 159 | --------------------------------------------------------------------------------