737 lines
39 KiB
Plaintext
737 lines
39 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "07a56b94",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import threading\n",
|
|
"import requests\n",
|
|
"from queue import Queue\n",
|
|
"from time import time,sleep\n",
|
|
"import os\n",
|
|
"\n",
|
|
"# 配置信息\n",
|
|
"ip = \"http://localhost:8080\"\n",
|
|
"resource_paths = [\n",
|
|
" \"/static/index.2da1efab.css\",\n",
|
|
" \"/static/js/chunk-vendors.js\",\n",
|
|
" \"/static/js/index.js\",\n",
|
|
" \"/static/js/pages-login-index.js\"\n",
|
|
"]\n",
|
|
"\n",
|
|
"# 创建下载结果队列\n",
|
|
"download_results = Queue()\n",
|
|
"\n",
|
|
"def download_resource(path, thread_name):\n",
|
|
" \"\"\"下载单个资源的线程函数\"\"\"\n",
|
|
" try:\n",
|
|
" url = ip + path\n",
|
|
" start_time = time()\n",
|
|
" response = requests.get(url)\n",
|
|
" \n",
|
|
" # 模拟浏览器行为:检查状态码和内容类型\n",
|
|
" if response.status_code != 200:\n",
|
|
" result = f\"线程 {thread_name}: {path} 下载失败, 状态码 {response.status_code}\"\n",
|
|
" else:\n",
|
|
" # 简略显示内容(实际应用中应保存文件)\n",
|
|
" content_preview = response.text[:50].replace('\\n', ' ') + \"...\" if len(response.text) > 50 else response.text\n",
|
|
" \n",
|
|
" # 模拟浏览器解析CSS/JS的时间延迟\n",
|
|
" process_time = 0.1 if any(ext in path for ext in ['.css', '.js']) else 0.0\n",
|
|
" \n",
|
|
" result = (\n",
|
|
" f\"线程 {thread_name}: 成功下载 {path}\\n\"\n",
|
|
" f\"类型: {'CSS' if '.css' in path else 'JS' if '.js' in path else '其他'}\\n\"\n",
|
|
" f\"大小: {len(response.text)/1024:.1f} KB\\n\"\n",
|
|
" f\"耗时: {time()-start_time:.3f}秒\\n\"\n",
|
|
" f\"内容预览: {content_preview}\"\n",
|
|
" )\n",
|
|
" \n",
|
|
" # 添加处理延迟,模拟浏览器执行\n",
|
|
" sleep(process_time)\n",
|
|
" \n",
|
|
" except Exception as e:\n",
|
|
" result = f\"线程 {thread_name}: {path} 下载异常 - {str(e)}\"\n",
|
|
" \n",
|
|
" download_results.put(result)\n",
|
|
"\n",
|
|
"def simulate_browser_download(max_workers=6):\n",
|
|
" \"\"\"模拟浏览器并发下载行为\"\"\"\n",
|
|
" print(f\"模拟浏览器行为 - 并发下载线程数: {max_workers}\")\n",
|
|
" print(\"=\" * 60)\n",
|
|
" \n",
|
|
" threads = []\n",
|
|
" for i, path in enumerate(resource_paths):\n",
|
|
" # 使用线程名标识资源类型\n",
|
|
" thread_name = f\"资源#{i+1}\"\n",
|
|
" \n",
|
|
" # 创建并启动线程\n",
|
|
" t = threading.Thread(\n",
|
|
" target=download_resource,\n",
|
|
" args=(path, thread_name),\n",
|
|
" name=thread_name\n",
|
|
" )\n",
|
|
" t.start()\n",
|
|
" threads.append(t)\n",
|
|
" \n",
|
|
" # 控制最大并发数,模拟浏览器的连接限制\n",
|
|
" if len(threads) >= max_workers:\n",
|
|
" for t in threads:\n",
|
|
" t.join()\n",
|
|
" threads = []\n",
|
|
" \n",
|
|
" # 等待剩余的线程完成\n",
|
|
" for t in threads:\n",
|
|
" t.join()\n",
|
|
" \n",
|
|
" # 打印结果\n",
|
|
" while not download_results.empty():\n",
|
|
" print(download_results.get())\n",
|
|
" print(\"-\" * 60)\n",
|
|
"\n",
|
|
" print(\"完成\")\n",
|
|
"if __name__ == \"__main__\":\n",
|
|
" print(\"浏览器静态资源请求模拟器\")\n",
|
|
" print(\"=\" * 60)\n",
|
|
" simulate_browser_download()\n",
|
|
" "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "73d41e7d",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from faker import Faker\n",
|
|
"import random\n",
|
|
"import json\n",
|
|
"from datetime import datetime\n",
|
|
"\n",
|
|
"# 初始化Faker生成器(简体中文)\n",
|
|
"fake = Faker('zh_CN')\n",
|
|
"\n",
|
|
"# 定义固定值\n",
|
|
"TEAM_ID = 106\n",
|
|
"PLAN_ID = 131\n",
|
|
"\n",
|
|
"# 常见民族列表\n",
|
|
"ETHNIC_GROUPS = [\"汉\", \"壮\", \"满\", \"回\", \"苗\", \"维吾尔\", \"土家\", \"彝\", \"蒙古\", \"藏\", \"布依\", \n",
|
|
" \"侗\", \"瑶\", \"朝鲜\", \"白\", \"哈尼\", \"哈萨克\", \"黎\", \"傣\", \"畲\", \"傈僳\", \"仡佬\",\n",
|
|
" \"东乡\", \"高山\", \"拉祜\", \"水\", \"佤\", \"纳西\", \"羌\", \"土\", \"仫佬\", \"锡伯\", \"柯尔克孜\",\n",
|
|
" \"达斡尔\", \"景颇\", \"毛南\", \"撒拉\", \"布朗\", \"塔吉克\", \"阿昌\", \"普米\", \"鄂温克\", \"怒\",\n",
|
|
" \"京\", \"基诺\", \"德昂\", \"保安\", \"俄罗斯\", \"裕固\", \"乌兹别克\", \"门巴\", \"鄂伦春\", \"独龙\",\n",
|
|
" \"塔塔尔\", \"赫哲\", \"珞巴\"]\n",
|
|
"\n",
|
|
"# 疾病列表(健康状态)\n",
|
|
"HEALTH_CONDITIONS = [\n",
|
|
" \"无\", \"近视\", \"弱视\", \"鼻炎\", \"哮喘\", \"过敏体质\", \"蛀牙\", \n",
|
|
" \"肥胖\", \"发育迟缓\", \"ADHD\", \"缺铁性贫血\", \"维生素缺乏\",\n",
|
|
" \"易感冒体质\", \"偏瘦\", \"过敏(花粉)\", \"过敏(尘螨)\", \"过敏(牛奶)\", \n",
|
|
" \"消化不良\", \"多动症\", \"抽动症\", \"癫痫\", \"小儿麻痹\", \"乙肝病毒携带\"\n",
|
|
"]\n",
|
|
"\n",
|
|
"# 艺术特长\n",
|
|
"ART_TALENTS = [\"无\", \"钢琴\", \"小提琴\", \"绘画\", \"书法\", \"舞蹈\", \"声乐\", \"戏剧表演\", \n",
|
|
" \"摄影\", \"编程\", \"动画制作\", \"模型制作\", \"手工艺术\"]\n",
|
|
"\n",
|
|
"# 体育特长\n",
|
|
"SPORTS_TALENTS = [\"无\", \"游泳\", \"篮球\", \"足球\", \"乒乓球\", \"羽毛球\", \"田径\", \n",
|
|
" \"武术\", \"跆拳道\", \"空手道\", \"轮滑\", \"滑板\", \"自行车\", \"健美操\"]\n",
|
|
"\n",
|
|
"# 科技特长\n",
|
|
"TECH_TALENTS = [\"无\", \"机器人编程\", \"电子制作\", \"3D打印\", \"人工智能\", \"网页设计\", \n",
|
|
" \"科学实验\", \"天文观测\", \"植物培养\", \"动物观察\", \"航模制作\"]\n",
|
|
"\n",
|
|
"# 职业列表\n",
|
|
"OCCUPATIONS = [\"医生\", \"教师\", \"工程师\", \"程序员\", \"设计师\", \"建筑师\", \"销售经理\",\n",
|
|
" \"会计\", \"律师\", \"公务员\", \"记者\", \"警察\", \"消防员\", \"厨师\", \"商人\",\n",
|
|
" \"自由职业\", \"个体经营者\", \"银行职员\", \"人力资源\", \"市场营销\"]\n",
|
|
"\n",
|
|
"# 公司类型\n",
|
|
"WORKPLACES = [\n",
|
|
" \"国有企业\", \"民营企业\", \"外资企业\", \"合资企业\", \"政府机关\", \n",
|
|
" \"事业单位\", \"学校\", \"医院\", \"设计事务所\", \"律师事务所\",\n",
|
|
" \"科技公司\", \"互联网公司\", \"金融机构\", \"建筑公司\", \"零售企业\"\n",
|
|
"]\n",
|
|
"\n",
|
|
"# 小学名称\n",
|
|
"PRIMARY_SCHOOLS = [\n",
|
|
" \"第一实验小学\", \"第二实验小学\", \"育才小学\", \"阳光小学\", \"希望小学\", \"和平小学\", \n",
|
|
" \"实验小学分校\", \"新世纪小学\", \"东方小学\", \"先锋小学\", \"星光小学\", \"明德小学\"\n",
|
|
"]\n",
|
|
"\n",
|
|
"def generate_id_num(birthday):\n",
|
|
" \"\"\"生成符合规则的身份证号\"\"\"\n",
|
|
" # 生成前6位(地区码,使用真实的地区码)\n",
|
|
" region_codes = [\"110101\", \"110105\", \"110106\", \"110107\", \"310112\", \"330102\", \"440106\", \"440304\"]\n",
|
|
" \n",
|
|
" # 出生日期码(8位)\n",
|
|
" birth_code = birthday.replace(\"-\", \"\")\n",
|
|
" \n",
|
|
" # 顺序码(3位)\n",
|
|
" sequence_code = str(random.randint(101, 998))\n",
|
|
" \n",
|
|
" # 生成校验码(1位)\n",
|
|
" base = region_codes[random.randint(0, len(region_codes)-1)] + birth_code + sequence_code\n",
|
|
" weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]\n",
|
|
" checksum_map = {0: '1', 1: '0', 2: 'X', 3: '9', 4: '8', 5: '7', 6: '6', 7: '5', 8: '4', 9: '3', 10: '2'}\n",
|
|
" \n",
|
|
" total = 0\n",
|
|
" for i in range(17):\n",
|
|
" total += int(base[i]) * weight[i]\n",
|
|
" checksum = checksum_map[total % 11]\n",
|
|
" \n",
|
|
" return base + checksum\n",
|
|
"\n",
|
|
"def generate_student_data():\n",
|
|
" \"\"\"生成单个学生数据\"\"\"\n",
|
|
" # 基础信息\n",
|
|
" sex = random.choice([\"男\", \"女\"])\n",
|
|
" \n",
|
|
" # 生日 (2010-2015年出生)\n",
|
|
" birthday = fake.date_between(start_date=\"-15y\", end_date=\"-8y\").strftime(\"%Y-%m-%d\")\n",
|
|
" \n",
|
|
" # 生成符合规则的身份证号\n",
|
|
" id_num = generate_id_num(birthday)\n",
|
|
" \n",
|
|
" # 计算年龄(仅用于展示)\n",
|
|
" birth_year = int(birthday[:4])\n",
|
|
" current_year = datetime.now().year\n",
|
|
" age = current_year - birth_year\n",
|
|
" \n",
|
|
" # 生成学生信息\n",
|
|
" data = {\n",
|
|
" \"teamId\": TEAM_ID,\n",
|
|
" \"stuName\": fake.name(), # 学生姓名\n",
|
|
" \"idNum\": id_num, # 身份证号\n",
|
|
" \"formerName\": random.choices([\"无\", fake.last_name() + fake.first_name()], weights=[0.8, 0.2])[0], # 曾用名\n",
|
|
" \"sex\": sex, # 性别\n",
|
|
" \"nation\": random.choice(ETHNIC_GROUPS), # 民族\n",
|
|
" \"birthday\": birthday, # 生日\n",
|
|
" \"finishSchool\": random.choice(PRIMARY_SCHOOLS), # 毕业学校\n",
|
|
" \"file\": None, # 文件\n",
|
|
" \"hkadr\": fake.province() + \"/\" + fake.city() + \"/\" + fake.district(), # 户口所在地\n",
|
|
" \"homeAddress\": fake.address(), # 家庭住址\n",
|
|
" \"health\": random.choice(HEALTH_CONDITIONS), # 健康状况\n",
|
|
" \"artisticSpecialty\": random.choice(ART_TALENTS), # 艺术特长\n",
|
|
" \"artisticAchievements\": \"无\", # 艺术成就\n",
|
|
" \"technologicalSpecialty\": random.choice(TECH_TALENTS), # 科技特长\n",
|
|
" \"technologicalAchievements\": \"无\", # 科技成就\n",
|
|
" \"sportsSpecialty\": random.choice(SPORTS_TALENTS), # 体育特长\n",
|
|
" \"sportsAchievements\": \"无\", # 体育成就\n",
|
|
" \"planId\": PLAN_ID, # 计划ID\n",
|
|
" \"imageUrl\": \"\", # 图片URL\n",
|
|
" \"schoolCode\": \"G\" + id_num[:-1], # 学籍号\n",
|
|
" \"age\": age, # 年龄(仅用于展示)\n",
|
|
" \"email\": fake.email() if random.random() > 0.7 else \"\", # 邮箱\n",
|
|
" \"height\": str(random.randint(130, 170)), # 身高\n",
|
|
" \"weight\": str(random.randint(25, 60)), # 体重\n",
|
|
" \"measurements\": f\"{random.randint(60, 90)},{random.randint(60, 90)},{random.randint(60, 90)}\" # 三围\n",
|
|
" }\n",
|
|
" \n",
|
|
" # 生成监护人信息\n",
|
|
" guardian_prefix = fake.last_name()\n",
|
|
" \n",
|
|
" # 监护人1 - 通常为父母之一\n",
|
|
" relationship_choices = [\"父亲\", \"母亲\", \"爷爷\", \"奶奶\", \"外公\", \"外婆\"]\n",
|
|
" relationship = random.choice(relationship_choices[:2]) # 主要选择父母\n",
|
|
" \n",
|
|
" data.update({\n",
|
|
" \"guardian1Name\": guardian_prefix + (\"先生\" if relationship == \"父亲\" else \"女士\"), # 监护人1姓名\n",
|
|
" \"guardian1Relationship\": relationship, # 关系\n",
|
|
" \"guardian1IdCardNumber\": generate_id_num(fake.date_between(start_date=\"-55y\", end_date=\"-25y\").strftime(\"%Y-%m-%d\")), # 身份证号\n",
|
|
" \"guardian1Contact\": fake.phone_number(), # 联系方式\n",
|
|
" \"guardian1Occupation\": random.choice(OCCUPATIONS), # 职业\n",
|
|
" \"guardian1Workplace\": random.choice(WORKPLACES) # 工作单位\n",
|
|
" })\n",
|
|
" \n",
|
|
" # 监护人2 - 可能是另一位家长或其他人\n",
|
|
" if relationship == \"父亲\":\n",
|
|
" guardian2_relationship = \"母亲\"\n",
|
|
" else:\n",
|
|
" guardian2_relationship = random.choices(\n",
|
|
" [\"父亲\", \"爷爷\", \"奶奶\", \"外公\", \"外婆\", \"其他亲属\"], \n",
|
|
" weights=[0.7, 0.1, 0.1, 0.05, 0.05, 0.1]\n",
|
|
" )[0]\n",
|
|
" \n",
|
|
" data.update({\n",
|
|
" \"guardian2Name\": guardian_prefix + (\n",
|
|
" \"先生\" if guardian2_relationship in [\"父亲\", \"爷爷\", \"外公\"] else \"女士\"\n",
|
|
" ), # 监护人2姓名\n",
|
|
" \"guardian2Relationship\": guardian2_relationship, # 关系\n",
|
|
" \"guardian2IdCardNumber\": generate_id_num(fake.date_between(start_date=\"-55y\", end_date=\"-25y\").strftime(\"%Y-%m-%d\")), # 身份证号\n",
|
|
" \"guardian2Contact\": fake.phone_number() if guardian2_relationship != \"无\" else \"\", # 联系方式\n",
|
|
" \"guardian2Occupation\": random.choice(OCCUPATIONS) if guardian2_relationship != \"无\" else \"\", # 职业\n",
|
|
" \"guardian2Workplace\": random.choice(WORKPLACES) if guardian2_relationship != \"无\" else \"\" # 工作单位\n",
|
|
" })\n",
|
|
" \n",
|
|
" return data\n",
|
|
"\n",
|
|
"def generate_students():\n",
|
|
" student = generate_student_data()\n",
|
|
" return student"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "018a3c24",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"🎬 开始模拟 10 个用户并发访问...\n",
|
|
"======================================================================\n",
|
|
"👤 用户 1 开始会话, Session ID: 679e3877-56ac-4791-a1e5-880468dc1d87\n",
|
|
"👤 用户 2 开始会话, Session ID: 96acf953-61d0-4499-900e-482f75112453\n",
|
|
"👤 用户 3 开始会话, Session ID: 588c0b3d-05ec-438e-a327-bc51fbc3927a\n",
|
|
"👤 用户 4 开始会话, Session ID: 52eb7ae8-d1b7-48ae-a0f2-8b1bd384d5b8\n",
|
|
"👤 用户 5 开始会话, Session ID: 42561435-6a9c-4eac-8282-ce4dd7d11547\n",
|
|
"👤 用户 6 开始会话, Session ID: ee1daae1-584b-409c-affe-d14ad170d309\n",
|
|
"👤 用户 7 开始会话, Session ID: 43901a21-0c91-45a5-9c98-b6fddd2dcb50\n",
|
|
"👤 用户 8 开始会话, Session ID: e8ad6873-751f-4f81-8409-cf1c34ee50ee\n",
|
|
"👤 用户 9 开始会话, Session ID: ae1d258d-545e-4c45-8b81-d9a8ba3d94e8\n",
|
|
"👤 用户 10 开始会话, Session ID: fed2a8aa-a697-4e4b-b433-11a9edbe1640\n",
|
|
"✅ 用户 5 资源 /static/index.2da1efab.css 加载完成: 文件: index.2da1efab.css | 大小: 93.7KB | 耗时: 2.032秒\n",
|
|
"✅ 用户 2 资源 /static/js/pages-login-index.js 加载完成: 文件: pages-login-index.js | 大小: 79.8KB | 耗时: 2.040秒\n",
|
|
"✅ 用户 4 资源 /static/index.2da1efab.css 加载完成: 文件: index.2da1efab.css | 大小: 93.7KB | 耗时: 2.040秒\n",
|
|
"✅ 用户 2 资源 /static/js/chunk-vendors.js 加载完成: 文件: chunk-vendors.js | 大小: 2655.9KB | 耗时: 2.057秒\n",
|
|
"✅ 用户 9 资源 /static/index.2da1efab.css 加载完成: 文件: index.2da1efab.css | 大小: 93.7KB | 耗时: 2.038秒\n",
|
|
"✅ 用户 4 资源 /static/js/index.js 加载完成: 文件: index.js | 大小: 100.2KB | 耗时: 2.044秒\n",
|
|
"✅ 用户 6 资源 /static/index.2da1efab.css 加载完成: 文件: index.2da1efab.css | 大小: 93.7KB | 耗时: 2.034秒\n",
|
|
"✅ 用户 1 资源 /static/js/index.js 加载完成: 文件: index.js | 大小: 100.2KB | 耗时: 2.036秒\n",
|
|
"✅ 用户 9 资源 /static/js/pages-login-index.js 加载完成: 文件: pages-login-index.js | 大小: 79.8KB | 耗时: 2.029秒\n",
|
|
"✅ 用户 10 资源 /static/js/index.js 加载完成: 文件: index.js | 大小: 100.2KB | 耗时: 2.037秒\n",
|
|
"✅ 用户 1 资源 /static/js/pages-login-index.js 加载完成: 文件: pages-login-index.js | 大小: 79.8KB | 耗时: 2.033秒\n",
|
|
"✅ 用户 6 资源 /static/js/pages-login-index.js 加载完成: 文件: pages-login-index.js | 大小: 79.8KB | 耗时: 2.040秒\n",
|
|
"✅ 用户 4 资源 /static/js/pages-login-index.js 加载完成: 文件: pages-login-index.js | 大小: 79.8KB | 耗时: 2.040秒\n",
|
|
"✅ 用户 10 资源 /static/index.2da1efab.css 加载完成: 文件: index.2da1efab.css | 大小: 93.7KB | 耗时: 2.040秒\n",
|
|
"✅ 用户 8 资源 /static/js/chunk-vendors.js 加载完成: 文件: chunk-vendors.js | 大小: 2655.9KB | 耗时: 2.051秒\n",
|
|
"✅ 用户 8 资源 /static/index.2da1efab.css 加载完成: 文件: index.2da1efab.css | 大小: 93.7KB | 耗时: 2.032秒\n",
|
|
"✅ 用户 2 资源 /static/index.2da1efab.css 加载完成: 文件: index.2da1efab.css | 大小: 93.7KB | 耗时: 2.038秒\n",
|
|
"✅ 用户 10 资源 /static/js/chunk-vendors.js 加载完成: 文件: chunk-vendors.js | 大小: 2655.9KB | 耗时: 2.077秒\n",
|
|
"✅ 用户 7 资源 /static/js/index.js 加载完成: 文件: index.js | 大小: 100.2KB | 耗时: 2.053秒\n",
|
|
"✅ 用户 10 资源 /static/js/pages-login-index.js 加载完成: 文件: pages-login-index.js | 大小: 79.8KB | 耗时: 2.047秒\n",
|
|
"📊 用户 10 加载所有静态资源耗时: 2.305秒\n",
|
|
"🚀 用户 10 开始看表单\n",
|
|
"✅ 用户 5 资源 /static/js/chunk-vendors.js 加载完成: 文件: chunk-vendors.js | 大小: 2655.9KB | 耗时: 2.066秒\n",
|
|
"✅ 用户 6 资源 /static/js/index.js 加载完成: 文件: index.js | 大小: 100.2KB | 耗时: 2.046秒\n",
|
|
"✅ 用户 4 资源 /static/js/chunk-vendors.js 加载完成: 文件: chunk-vendors.js | 大小: 2655.9KB | 耗时: 2.069秒\n",
|
|
"📊 用户 4 加载所有静态资源耗时: 2.348秒\n",
|
|
"🚀 用户 4 开始看表单\n",
|
|
"✅ 用户 7 资源 /static/index.2da1efab.css 加载完成: 文件: index.2da1efab.css | 大小: 93.7KB | 耗时: 2.055秒\n",
|
|
"✅ 用户 7 资源 /static/js/pages-login-index.js 加载完成: 文件: pages-login-index.js | 大小: 79.8KB | 耗时: 2.055秒\n",
|
|
"✅ 用户 6 资源 /static/js/chunk-vendors.js 加载完成: 文件: chunk-vendors.js | 大小: 2655.9KB | 耗时: 2.069秒\n",
|
|
"📊 用户 6 加载所有静态资源耗时: 2.391秒\n",
|
|
"🚀 用户 6 开始看表单\n",
|
|
"✅ 用户 3 资源 /static/js/index.js 加载完成: 文件: index.js | 大小: 100.2KB | 耗时: 2.043秒\n",
|
|
"✅ 用户 9 资源 /static/js/index.js 加载完成: 文件: index.js | 大小: 100.2KB | 耗时: 2.057秒\n",
|
|
"✅ 用户 1 资源 /static/index.2da1efab.css 加载完成: 文件: index.2da1efab.css | 大小: 93.7KB | 耗时: 2.055秒\n",
|
|
"✅ 用户 8 资源 /static/js/pages-login-index.js 加载完成: 文件: pages-login-index.js | 大小: 79.8KB | 耗时: 2.057秒\n",
|
|
"✅ 用户 3 资源 /static/index.2da1efab.css 加载完成: 文件: index.2da1efab.css | 大小: 93.7KB | 耗时: 2.063秒\n",
|
|
"✅ 用户 7 资源 /static/js/chunk-vendors.js 加载完成: 文件: chunk-vendors.js | 大小: 2655.9KB | 耗时: 2.085秒\n",
|
|
"📊 用户 7 加载所有静态资源耗时: 2.434秒\n",
|
|
"🚀 用户 7 开始看表单\n",
|
|
"✅ 用户 1 资源 /static/js/chunk-vendors.js 加载完成: 文件: chunk-vendors.js | 大小: 2655.9KB | 耗时: 2.073秒\n",
|
|
"📊 用户 1 加载所有静态资源耗时: 2.450秒\n",
|
|
"🚀 用户 1 开始看表单\n",
|
|
"✅ 用户 3 资源 /static/js/pages-login-index.js 加载完成: 文件: pages-login-index.js | 大小: 79.8KB | 耗时: 2.037秒\n",
|
|
"✅ 用户 3 资源 /static/js/chunk-vendors.js 加载完成: 文件: chunk-vendors.js | 大小: 2655.9KB | 耗时: 2.059秒\n",
|
|
"📊 用户 3 加载所有静态资源耗时: 2.487秒\n",
|
|
"🚀 用户 3 开始看表单\n",
|
|
"✅ 用户 2 资源 /static/js/index.js 加载完成: 文件: index.js | 大小: 100.2KB | 耗时: 2.049秒\n",
|
|
"📊 用户 2 加载所有静态资源耗时: 2.507秒\n",
|
|
"🚀 用户 2 开始看表单\n",
|
|
"✅ 用户 9 资源 /static/js/chunk-vendors.js 加载完成: 文件: chunk-vendors.js | 大小: 2655.9KB | 耗时: 2.051秒\n",
|
|
"📊 用户 9 加载所有静态资源耗时: 2.519秒\n",
|
|
"🚀 用户 9 开始看表单\n",
|
|
"✅ 用户 8 资源 /static/js/index.js 加载完成: 文件: index.js | 大小: 100.2KB | 耗时: 2.040秒\n",
|
|
"📊 用户 8 加载所有静态资源耗时: 2.527秒\n",
|
|
"🚀 用户 8 开始看表单\n",
|
|
"✅ 用户 5 资源 /static/js/index.js 加载完成: 文件: index.js | 大小: 100.2KB | 耗时: 2.043秒\n",
|
|
"✅ 用户 5 资源 /static/js/pages-login-index.js 加载完成: 文件: pages-login-index.js | 大小: 79.8KB | 耗时: 2.035秒\n",
|
|
"📊 用户 5 加载所有静态资源耗时: 2.542秒\n",
|
|
"🚀 用户 5 开始看表单\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"from faker import Faker\n",
|
|
"import random\n",
|
|
"import json\n",
|
|
"from datetime import datetime\n",
|
|
"import threading\n",
|
|
"import requests\n",
|
|
"from time import time, sleep\n",
|
|
"import uuid\n",
|
|
"from concurrent.futures import ThreadPoolExecutor, as_completed\n",
|
|
"# 初始化Faker生成器(简体中文)\n",
|
|
"fake = Faker('zh_CN')\n",
|
|
"\n",
|
|
"# 定义固定值\n",
|
|
"TEAM_ID = 106\n",
|
|
"PLAN_ID = 131\n",
|
|
"\n",
|
|
"# 常见民族列表\n",
|
|
"ETHNIC_GROUPS = [\"汉\", \"壮\", \"满\", \"回\", \"苗\", \"维吾尔\", \"土家\", \"彝\", \"蒙古\", \"藏\", \"布依\", \n",
|
|
" \"侗\", \"瑶\", \"朝鲜\", \"白\", \"哈尼\", \"哈萨克\", \"黎\", \"傣\", \"畲\", \"傈僳\", \"仡佬\",\n",
|
|
" \"东乡\", \"高山\", \"拉祜\", \"水\", \"佤\", \"纳西\", \"羌\", \"土\", \"仫佬\", \"锡伯\", \"柯尔克孜\",\n",
|
|
" \"达斡尔\", \"景颇\", \"毛南\", \"撒拉\", \"布朗\", \"塔吉克\", \"阿昌\", \"普米\", \"鄂温克\", \"怒\",\n",
|
|
" \"京\", \"基诺\", \"德昂\", \"保安\", \"俄罗斯\", \"裕固\", \"乌兹别克\", \"门巴\", \"鄂伦春\", \"独龙\",\n",
|
|
" \"塔塔尔\", \"赫哲\", \"珞巴\"]\n",
|
|
"\n",
|
|
"# 疾病列表(健康状态)\n",
|
|
"HEALTH_CONDITIONS = [\n",
|
|
" \"无\", \"近视\", \"弱视\", \"鼻炎\", \"哮喘\", \"过敏体质\", \"蛀牙\", \n",
|
|
" \"肥胖\", \"发育迟缓\", \"ADHD\", \"缺铁性贫血\", \"维生素缺乏\",\n",
|
|
" \"易感冒体质\", \"偏瘦\", \"过敏(花粉)\", \"过敏(尘螨)\", \"过敏(牛奶)\", \n",
|
|
" \"消化不良\", \"多动症\", \"抽动症\", \"癫痫\", \"小儿麻痹\", \"乙肝病毒携带\"\n",
|
|
"]\n",
|
|
"\n",
|
|
"# 艺术特长\n",
|
|
"ART_TALENTS = [\"无\", \"钢琴\", \"小提琴\", \"绘画\", \"书法\", \"舞蹈\", \"声乐\", \"戏剧表演\", \n",
|
|
" \"摄影\", \"编程\", \"动画制作\", \"模型制作\", \"手工艺术\"]\n",
|
|
"\n",
|
|
"# 体育特长\n",
|
|
"SPORTS_TALENTS = [\"无\", \"游泳\", \"篮球\", \"足球\", \"乒乓球\", \"羽毛球\", \"田径\", \n",
|
|
" \"武术\", \"跆拳道\", \"空手道\", \"轮滑\", \"滑板\", \"自行车\", \"健美操\"]\n",
|
|
"\n",
|
|
"# 科技特长\n",
|
|
"TECH_TALENTS = [\"无\", \"机器人编程\", \"电子制作\", \"3D打印\", \"人工智能\", \"网页设计\", \n",
|
|
" \"科学实验\", \"天文观测\", \"植物培养\", \"动物观察\", \"航模制作\"]\n",
|
|
"\n",
|
|
"# 职业列表\n",
|
|
"OCCUPATIONS = [\"医生\", \"教师\", \"工程师\", \"程序员\", \"设计师\", \"建筑师\", \"销售经理\",\n",
|
|
" \"会计\", \"律师\", \"公务员\", \"记者\", \"警察\", \"消防员\", \"厨师\", \"商人\",\n",
|
|
" \"自由职业\", \"个体经营者\", \"银行职员\", \"人力资源\", \"市场营销\"]\n",
|
|
"\n",
|
|
"# 公司类型\n",
|
|
"WORKPLACES = [\n",
|
|
" \"国有企业\", \"民营企业\", \"外资企业\", \"合资企业\", \"政府机关\", \n",
|
|
" \"事业单位\", \"学校\", \"医院\", \"设计事务所\", \"律师事务所\",\n",
|
|
" \"科技公司\", \"互联网公司\", \"金融机构\", \"建筑公司\", \"零售企业\"\n",
|
|
"]\n",
|
|
"\n",
|
|
"# 小学名称\n",
|
|
"PRIMARY_SCHOOLS = [\n",
|
|
" \"第一实验小学\", \"第二实验小学\", \"育才小学\", \"阳光小学\", \"希望小学\", \"和平小学\", \n",
|
|
" \"实验小学分校\", \"新世纪小学\", \"东方小学\", \"先锋小学\", \"星光小学\", \"明德小学\"\n",
|
|
"]\n",
|
|
"\n",
|
|
"def generate_id_num(birthday):\n",
|
|
" \"\"\"生成符合规则的身份证号\"\"\"\n",
|
|
" # 生成前6位(地区码,使用真实的地区码)\n",
|
|
" region_codes = [\"110101\", \"110105\", \"110106\", \"110107\", \"310112\", \"330102\", \"440106\", \"440304\"]\n",
|
|
" \n",
|
|
" # 出生日期码(8位)\n",
|
|
" birth_code = birthday.replace(\"-\", \"\")\n",
|
|
" \n",
|
|
" # 顺序码(3位)\n",
|
|
" sequence_code = str(random.randint(101, 998))\n",
|
|
" \n",
|
|
" # 生成校验码(1位)\n",
|
|
" base = region_codes[random.randint(0, len(region_codes)-1)] + birth_code + sequence_code\n",
|
|
" weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]\n",
|
|
" checksum_map = {0: '1', 1: '0', 2: 'X', 3: '9', 4: '8', 5: '7', 6: '6', 7: '5', 8: '4', 9: '3', 10: '2'}\n",
|
|
" \n",
|
|
" total = 0\n",
|
|
" for i in range(17):\n",
|
|
" total += int(base[i]) * weight[i]\n",
|
|
" checksum = checksum_map[total % 11]\n",
|
|
" \n",
|
|
" return base + checksum\n",
|
|
"\n",
|
|
"def generate_student_data():\n",
|
|
" \"\"\"生成单个学生数据\"\"\"\n",
|
|
" # 基础信息\n",
|
|
" sex = random.choice([\"男\", \"女\"])\n",
|
|
" \n",
|
|
" # 生日 (2010-2015年出生)\n",
|
|
" birthday = fake.date_between(start_date=\"-15y\", end_date=\"-8y\").strftime(\"%Y-%m-%d\")\n",
|
|
" \n",
|
|
" # 生成符合规则的身份证号\n",
|
|
" id_num = generate_id_num(birthday)\n",
|
|
" \n",
|
|
" # 计算年龄(仅用于展示)\n",
|
|
" birth_year = int(birthday[:4])\n",
|
|
" current_year = datetime.now().year\n",
|
|
" age = current_year - birth_year\n",
|
|
" \n",
|
|
" # 生成学生信息\n",
|
|
" data = {\n",
|
|
" \"teamId\": TEAM_ID,\n",
|
|
" \"stuName\": fake.name(), # 学生姓名\n",
|
|
" \"idNum\": id_num, # 身份证号\n",
|
|
" \"formerName\": random.choices([\"无\", fake.last_name() + fake.first_name()], weights=[0.8, 0.2])[0], # 曾用名\n",
|
|
" \"sex\": sex, # 性别\n",
|
|
" \"nation\": random.choice(ETHNIC_GROUPS), # 民族\n",
|
|
" \"birthday\": birthday, # 生日\n",
|
|
" \"finishSchool\": random.choice(PRIMARY_SCHOOLS), # 毕业学校\n",
|
|
" \"file\": None, # 文件\n",
|
|
" \"hkadr\": fake.province() + \"/\" + fake.city() + \"/\" + fake.district(), # 户口所在地\n",
|
|
" \"homeAddress\": fake.address(), # 家庭住址\n",
|
|
" \"health\": random.choice(HEALTH_CONDITIONS), # 健康状况\n",
|
|
" \"artisticSpecialty\": random.choice(ART_TALENTS), # 艺术特长\n",
|
|
" \"artisticAchievements\": \"无\", # 艺术成就\n",
|
|
" \"technologicalSpecialty\": random.choice(TECH_TALENTS), # 科技特长\n",
|
|
" \"technologicalAchievements\": \"无\", # 科技成就\n",
|
|
" \"sportsSpecialty\": random.choice(SPORTS_TALENTS), # 体育特长\n",
|
|
" \"sportsAchievements\": \"无\", # 体育成就\n",
|
|
" \"planId\": PLAN_ID, # 计划ID\n",
|
|
" \"imageUrl\": \"\", # 图片URL\n",
|
|
" \"schoolCode\": \"G\" + id_num[:-1], # 学籍号\n",
|
|
" \"age\": age, # 年龄(仅用于展示)\n",
|
|
" \"email\": fake.email() if random.random() > 0.7 else \"\", # 邮箱\n",
|
|
" \"height\": str(random.randint(130, 170)), # 身高\n",
|
|
" \"weight\": str(random.randint(25, 60)), # 体重\n",
|
|
" \"measurements\": f\"{random.randint(60, 90)},{random.randint(60, 90)},{random.randint(60, 90)}\" # 三围\n",
|
|
" }\n",
|
|
" \n",
|
|
" # 生成监护人信息\n",
|
|
" guardian_prefix = fake.last_name()\n",
|
|
" \n",
|
|
" # 监护人1 - 通常为父母之一\n",
|
|
" relationship_choices = [\"父亲\", \"母亲\", \"爷爷\", \"奶奶\", \"外公\", \"外婆\"]\n",
|
|
" relationship = random.choice(relationship_choices[:2]) # 主要选择父母\n",
|
|
" \n",
|
|
" data.update({\n",
|
|
" \"guardian1Name\": guardian_prefix + (\"先生\" if relationship == \"父亲\" else \"女士\"), # 监护人1姓名\n",
|
|
" \"guardian1Relationship\": relationship, # 关系\n",
|
|
" \"guardian1IdCardNumber\": generate_id_num(fake.date_between(start_date=\"-55y\", end_date=\"-25y\").strftime(\"%Y-%m-%d\")), # 身份证号\n",
|
|
" \"guardian1Contact\": fake.phone_number(), # 联系方式\n",
|
|
" \"guardian1Occupation\": random.choice(OCCUPATIONS), # 职业\n",
|
|
" \"guardian1Workplace\": random.choice(WORKPLACES) # 工作单位\n",
|
|
" })\n",
|
|
" \n",
|
|
" # 监护人2 - 可能是另一位家长或其他人\n",
|
|
" if relationship == \"父亲\":\n",
|
|
" guardian2_relationship = \"母亲\"\n",
|
|
" else:\n",
|
|
" guardian2_relationship = random.choices(\n",
|
|
" [\"父亲\", \"爷爷\", \"奶奶\", \"外公\", \"外婆\", \"其他亲属\"], \n",
|
|
" weights=[0.7, 0.1, 0.1, 0.05, 0.05, 0.1]\n",
|
|
" )[0]\n",
|
|
" \n",
|
|
" data.update({\n",
|
|
" \"guardian2Name\": guardian_prefix + (\n",
|
|
" \"先生\" if guardian2_relationship in [\"父亲\", \"爷爷\", \"外公\"] else \"女士\"\n",
|
|
" ), # 监护人2姓名\n",
|
|
" \"guardian2Relationship\": guardian2_relationship, # 关系\n",
|
|
" \"guardian2IdCardNumber\": generate_id_num(fake.date_between(start_date=\"-55y\", end_date=\"-25y\").strftime(\"%Y-%m-%d\")), # 身份证号\n",
|
|
" \"guardian2Contact\": fake.phone_number() if guardian2_relationship != \"无\" else \"\", # 联系方式\n",
|
|
" \"guardian2Occupation\": random.choice(OCCUPATIONS) if guardian2_relationship != \"无\" else \"\", # 职业\n",
|
|
" \"guardian2Workplace\": random.choice(WORKPLACES) if guardian2_relationship != \"无\" else \"\" # 工作单位\n",
|
|
" })\n",
|
|
" \n",
|
|
" return data\n",
|
|
"\n",
|
|
"def generate_students():\n",
|
|
" student = generate_student_data()\n",
|
|
" return student\n",
|
|
"\n",
|
|
"\n",
|
|
"# 配置信息\n",
|
|
"BASE_URL = \"http://localhost:8080\"\n",
|
|
"STATIC_PATHS = [\n",
|
|
" \"/static/index.2da1efab.css\",\n",
|
|
" \"/static/js/chunk-vendors.js\",\n",
|
|
" \"/static/js/index.js\",\n",
|
|
" \"/static/js/pages-login-index.js\"\n",
|
|
"]\n",
|
|
"\n",
|
|
"# 用户数据生成\n",
|
|
"USER_AGENTS = [\n",
|
|
" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36\",\n",
|
|
" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15\",\n",
|
|
" \"Mozilla/5.0 (iPhone; CPU iPhone OS 15_5 like Mac OS X) AppleWebKit/605.1.15\",\n",
|
|
" \"Mozilla/5.0 (Linux; Android 12; SM-G991B) AppleWebKit/537.36\",\n",
|
|
" \"Mozilla/5.0 (iPad; CPU OS 15_5 like Mac OS X) AppleWebKit/605.1.15\"\n",
|
|
"]\n",
|
|
"\n",
|
|
"def generate_user_data(user_id):\n",
|
|
" \"\"\"生成模拟用户数据\"\"\"\n",
|
|
" return {\n",
|
|
" \"id\": user_id,\n",
|
|
" \"session_id\": str(uuid.uuid4()),\n",
|
|
" \"user_agent\": random.choice(USER_AGENTS),\n",
|
|
" \"request_count\": 0,\n",
|
|
" \"start_time\": time()\n",
|
|
" }\n",
|
|
"\n",
|
|
"def simulate_user_session(user_id):\n",
|
|
" \"\"\"模拟一个用户的完整会话\"\"\"\n",
|
|
" user_data = generate_user_data(user_id)\n",
|
|
" print(f\"👤 用户 {user_id} 开始会话, Session ID: {user_data['session_id']}\")\n",
|
|
" start = time()\n",
|
|
" # 使用线程池请求所有静态资源\n",
|
|
" with ThreadPoolExecutor(max_workers=len(STATIC_PATHS)) as executor:\n",
|
|
" futures = {}\n",
|
|
" \n",
|
|
" # 提交所有静态资源请求任务\n",
|
|
" for path in STATIC_PATHS:\n",
|
|
" url = BASE_URL + path\n",
|
|
" future = executor.submit(\n",
|
|
" fetch_resource, \n",
|
|
" url, \n",
|
|
" user_data\n",
|
|
" )\n",
|
|
" futures[future] = path\n",
|
|
" \n",
|
|
" # 等待所有静态资源加载完成\n",
|
|
" for future in as_completed(futures):\n",
|
|
" path = futures[future]\n",
|
|
" try:\n",
|
|
" result = future.result()\n",
|
|
" print(f\"✅ 用户 {user_id} 资源 {path} 加载完成: {result}\")\n",
|
|
" except Exception as e:\n",
|
|
" print(f\"❌ 用户 {user_id} 资源加载失败: {str(e)}\")\n",
|
|
" end = time()\n",
|
|
" # 所有静态资源加载完成后访问百度提交数据\n",
|
|
" print(f\"📊 用户 {user_id} 加载所有静态资源耗时: {end - start:.3f}秒\")\n",
|
|
" print(f\"🚀 用户 {user_id} 开始看表单\")\n",
|
|
" submit_to_baidu(user_data)\n",
|
|
" \n",
|
|
" return user_data\n",
|
|
"\n",
|
|
"def fetch_resource(url, user_data):\n",
|
|
" \"\"\"模拟用户获取单个资源\"\"\"\n",
|
|
" # 更新用户请求计数\n",
|
|
" user_data[\"request_count\"] += 1\n",
|
|
" \n",
|
|
" # 生成请求头\n",
|
|
" headers = {\n",
|
|
" \"User-Agent\": user_data[\"user_agent\"],\n",
|
|
" \"X-Session-Id\": user_data[\"session_id\"],\n",
|
|
" \"X-Request-Count\": str(user_data[\"request_count\"]),\n",
|
|
" \"Accept-Encoding\": \"gzip, deflate\"\n",
|
|
" }\n",
|
|
" \n",
|
|
" # 添加随机延迟(0.1-0.5秒)模拟网络波动\n",
|
|
" sleep(random.uniform(0.1, 0.5))\n",
|
|
" \n",
|
|
" try:\n",
|
|
" # 执行资源请求\n",
|
|
" start_time = time()\n",
|
|
" response = requests.get(url, headers=headers)\n",
|
|
" elapsed_time = time() - start_time\n",
|
|
" \n",
|
|
" if response.status_code != 200:\n",
|
|
" return f\"错误状态码: {response.status_code} | 耗时: {elapsed_time:.3f}秒\"\n",
|
|
" \n",
|
|
" # 提取文件名\n",
|
|
" file_name = url.split('/')[-1]\n",
|
|
" \n",
|
|
" return f\"文件: {file_name} | 大小: {len(response.text)/1024:.1f}KB | 耗时: {elapsed_time:.3f}秒\"\n",
|
|
" \n",
|
|
" except Exception as e:\n",
|
|
" return f\"请求异常: {str(e)}\"\n",
|
|
"\n",
|
|
"def submit_to_baidu(user_data):\n",
|
|
" \"\"\"提交数据到百度\"\"\"\n",
|
|
" # 构造提交数据\n",
|
|
" payload = generate_students()\n",
|
|
" sleep(random.uniform(5, 20))\n",
|
|
" print(f\"🎉 用户 {user_data['id']} 提交数据 \")\n",
|
|
" try:\n",
|
|
" # 提交到百度\n",
|
|
" start_time = time()\n",
|
|
" response = requests.post(\n",
|
|
" \"http://band.hxzhxy.cn/register/student/add\", # 模拟的百度提交API\n",
|
|
" json=payload,\n",
|
|
" headers={\n",
|
|
" \"User-Agent\": user_data[\"user_agent\"],\n",
|
|
" \"X-Session-Id\": user_data[\"session_id\"],\n",
|
|
" \"Content-Type\": \"application/json\"\n",
|
|
" }\n",
|
|
" )\n",
|
|
" elapsed_time = time() - start_time\n",
|
|
" \n",
|
|
" # 记录用户总用时\n",
|
|
" total_time = time() - user_data[\"start_time\"]\n",
|
|
" \n",
|
|
" if response.status_code == 200:\n",
|
|
" print(f\"🎉 用户 {user_data['id']} 数据提交成功! | 提交耗时: {elapsed_time:.3f}秒 | 总用时: {total_time:.3f}秒\")\n",
|
|
" return True\n",
|
|
" else:\n",
|
|
" print(f\"⚠️ 用户 {user_data['id']} 提交失败: 状态码 {response.status_code} | 总用时: {total_time:.3f}秒\")\n",
|
|
" return False\n",
|
|
" \n",
|
|
" except Exception as e:\n",
|
|
" print(f\"‼️ 用户 {user_data['id']} 提交异常: {str(e)}\")\n",
|
|
" return False\n",
|
|
"\n",
|
|
"def simulate_multiple_users(num_users=10):\n",
|
|
" \"\"\"模拟多个用户并发访问\"\"\"\n",
|
|
" print(f\"🎬 开始模拟 {num_users} 个用户并发访问...\")\n",
|
|
" print(\"=\" * 70)\n",
|
|
" \n",
|
|
" with ThreadPoolExecutor(max_workers=num_users) as executor:\n",
|
|
" # 提交所有用户会话任务\n",
|
|
" futures = [executor.submit(simulate_user_session, i+1) for i in range(5)]\n",
|
|
" \n",
|
|
" # 等待所有用户完成并收集结果\n",
|
|
" results = []\n",
|
|
" for future in as_completed(futures):\n",
|
|
" try:\n",
|
|
" user_data = future.result()\n",
|
|
" results.append(user_data)\n",
|
|
" except Exception as e:\n",
|
|
" print(f\"用户会话异常: {str(e)}\")\n",
|
|
" \n",
|
|
" # 生成性能报告\n",
|
|
" print(\"\\n\" + \"=\" * 70)\n",
|
|
" print(\"🏁 所有用户已完成操作! 性能摘要:\")\n",
|
|
" print(\"-\" * 70)\n",
|
|
" \n",
|
|
" total_time = 0\n",
|
|
" total_requests = 0\n",
|
|
" completed_submissions = 0\n",
|
|
" \n",
|
|
" for user in results:\n",
|
|
" session_time = time() - user[\"start_time\"]\n",
|
|
" total_time += session_time\n",
|
|
" total_requests += user[\"request_count\"]\n",
|
|
" \n",
|
|
" print(f\"用户 {user['id']:2d} | 用时: {session_time:.3f}秒 | 请求数: {user['request_count']}\")\n",
|
|
" \n",
|
|
" print(\"\\n汇总统计:\")\n",
|
|
" print(f\"- 平均用时: {total_time/len(results):.3f}秒/用户\")\n",
|
|
" print(f\"- 总请求数: {total_requests}次\")\n",
|
|
" print(f\"- 用户提交率: {completed_submissions}/{len(results)}\")\n",
|
|
" print(\"=\" * 70)\n",
|
|
"\n",
|
|
"if __name__ == \"__main__\":\n",
|
|
" simulate_multiple_users(num_users=10)"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "base",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.12.4"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|