{ "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 }