chore: 批量新增各类工具脚本与配置文件
1. 新增音频录制、下载、上传相关脚本 2. 新增数据库操作、API调用工具 3. 新增Excel数据处理脚本 4. 新增弱密码检测脚本
This commit is contained in:
@@ -11,6 +11,10 @@ dist/
|
||||
*.egg-info
|
||||
*.pyc
|
||||
*.jar
|
||||
*.csv
|
||||
*.wav
|
||||
*.json
|
||||
*/output/
|
||||
build/
|
||||
out/
|
||||
__pycache__/
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
import subprocess
|
||||
import time
|
||||
from datetime import datetime
|
||||
import os
|
||||
|
||||
# RTSP 流地址
|
||||
rtsp_url = "rtsp://10.68.66.174/audio"
|
||||
|
||||
# 录制时长(分钟)
|
||||
duration_minutes = 60
|
||||
output_filename = f"rtsp_recording_{datetime.now().strftime('%Y%m%d_%H%M%S')}.wav"
|
||||
|
||||
print(f"开始录制 RTSP 音频流...")
|
||||
print(f"RTSP 地址: {rtsp_url}")
|
||||
print(f"录制时长: {duration_minutes} 分钟")
|
||||
print(f"保存路径: {output_filename}")
|
||||
print(f"按 Ctrl+C 停止录制")
|
||||
print("-" * 50)
|
||||
|
||||
# 转换为秒
|
||||
duration_seconds = duration_minutes * 60
|
||||
|
||||
try:
|
||||
# 使用 ffmpeg 录制 RTSP 流
|
||||
# -rtsp_transport tcp 使用 TCP 协议,更稳定
|
||||
# -t 指定录制时长
|
||||
# -acodec pcm_s16le 输出 PCM WAV 格式
|
||||
cmd = [
|
||||
'ffmpeg',
|
||||
'-rtsp_transport', 'tcp',
|
||||
'-i', rtsp_url,
|
||||
'-t', str(duration_seconds),
|
||||
'-acodec', 'pcm_s16le',
|
||||
'-ar', '16000', # 采样率
|
||||
'-ac', '1', # 单声道
|
||||
'-y', # 覆盖已存在的文件
|
||||
output_filename
|
||||
]
|
||||
|
||||
print(f"执行命令: {' '.join(cmd)}")
|
||||
print("开始录制...")
|
||||
|
||||
# 执行 ffmpeg 命令
|
||||
process = subprocess.Popen(
|
||||
cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
universal_newlines=True
|
||||
)
|
||||
|
||||
# 用于跟踪进度的变量
|
||||
start_time = time.time()
|
||||
last_size = 0
|
||||
|
||||
# 实时输出 ffmpeg 的日志
|
||||
for line in iter(process.stdout.readline, ''):
|
||||
if line:
|
||||
# 检查文件大小变化
|
||||
if os.path.exists(output_filename):
|
||||
current_size = os.path.getsize(output_filename)
|
||||
if current_size != last_size:
|
||||
elapsed = time.time() - start_time
|
||||
size_mb = current_size / (1024 * 1024)
|
||||
progress = (elapsed / duration_seconds) * 100 if duration_seconds > 0 else 0
|
||||
print(f"进度: {int(elapsed)}秒 / {duration_seconds}秒 ({progress:.1f}%), 大小: {size_mb:.2f}MB", end='\r')
|
||||
last_size = current_size
|
||||
|
||||
process.wait()
|
||||
|
||||
# 录制完成
|
||||
elapsed = time.time() - start_time
|
||||
if os.path.exists(output_filename):
|
||||
size_mb = os.path.getsize(output_filename) / (1024 * 1024)
|
||||
print(f"\n\n录制完成!")
|
||||
print(f"总时长: {int(elapsed)}秒 ({elapsed/60:.1f}分钟)")
|
||||
print(f"文件大小: {size_mb:.2f}MB")
|
||||
print(f"保存路径: {os.path.abspath(output_filename)}")
|
||||
else:
|
||||
print("\n录制失败,文件未生成")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print(f"\n\n录制已手动停止")
|
||||
if os.path.exists(output_filename):
|
||||
size_mb = os.path.getsize(output_filename) / (1024 * 1024)
|
||||
elapsed = time.time() - start_time
|
||||
print(f"已录制: {int(elapsed)}秒")
|
||||
print(f"文件大小: {size_mb:.2f}MB")
|
||||
print(f"保存路径: {os.path.abspath(output_filename)}")
|
||||
except Exception as e:
|
||||
print(f"\n错误: {e}")
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langchain_mcp_adapters.client import MultiServerMCPClient
|
||||
from langchain_core.tools import StructuredTool, Tool
|
||||
from langchain.agents import create_agent
|
||||
import asyncio
|
||||
|
||||
def normalize_base_url(url):
|
||||
"""标准化base_url,移除反引号和首尾空格,去除末尾斜杠"""
|
||||
if url:
|
||||
url = url.strip().strip('`').rstrip('/')
|
||||
return url
|
||||
|
||||
# OpenAI配置
|
||||
api_key = "sk-8d657b8b7efe0cb6c141a30d9cee97f726efb9b18ea72bb1e8cfb080b42c140d"
|
||||
base_url = normalize_base_url("https://console.pivotbak.cfd/v1")
|
||||
model_name = "MiniMax-M2.7-highspeed"
|
||||
|
||||
# MCP配置
|
||||
mcp_server_url = normalize_base_url("http://192.168.0.10:9999/admin/mcp/sse")
|
||||
|
||||
# 全局参数 - 每次对话都要传递
|
||||
team_id = 19
|
||||
token = "f1d23a59-479c-44a8-94b5-2344e4672ffd"
|
||||
|
||||
# 初始化LLM,每次请求都会携带teamId和token
|
||||
llm = ChatOpenAI(
|
||||
model=model_name,
|
||||
openai_api_key=api_key,
|
||||
openai_api_base=base_url,
|
||||
temperature=0.7,
|
||||
max_tokens=4096,
|
||||
extra_body={
|
||||
"teamId": team_id,
|
||||
"token": token
|
||||
}
|
||||
)
|
||||
|
||||
# 示例工具函数
|
||||
def get_current_time():
|
||||
"""获取当前时间"""
|
||||
from datetime import datetime
|
||||
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
def calculate(a: float, b: float, operation: str = "add") -> float:
|
||||
"""
|
||||
简单计算器
|
||||
:param a: 第一个数
|
||||
:param b: 第二个数
|
||||
:param operation: 操作类型,可选 add, sub, mul, div
|
||||
"""
|
||||
if operation == "add":
|
||||
return a + b
|
||||
elif operation == "sub":
|
||||
return a - b
|
||||
elif operation == "mul":
|
||||
return a * b
|
||||
elif operation == "div":
|
||||
if b == 0:
|
||||
return "错误:除数不能为零"
|
||||
return a / b
|
||||
else:
|
||||
return f"未知操作: {operation}"
|
||||
|
||||
# 定义工具
|
||||
tools = [
|
||||
Tool(
|
||||
name="get_current_time",
|
||||
func=get_current_time,
|
||||
description="获取当前时间"
|
||||
),
|
||||
StructuredTool.from_function(calculate)
|
||||
]
|
||||
|
||||
# 从MCP加载工具
|
||||
async def load_mcp_tools():
|
||||
mcp_client = MultiServerMCPClient(
|
||||
{"server": {"url": mcp_server_url, "transport": "sse"}}
|
||||
)
|
||||
try:
|
||||
mcp_tools = await mcp_client.get_tools()
|
||||
print(f"从MCP服务器加载到 {len(mcp_tools)} 个工具:")
|
||||
for tool in mcp_tools:
|
||||
print(f" - {tool.name}: {tool.description}")
|
||||
return mcp_tools
|
||||
except Exception as e:
|
||||
print(f"连接MCP服务器失败: {e}")
|
||||
print("将继续使用本地工具")
|
||||
return []
|
||||
|
||||
# 创建Agent
|
||||
def create_my_agent(all_tools):
|
||||
agent = create_agent(
|
||||
model=llm,
|
||||
tools=all_tools,
|
||||
system_prompt="你是一个有用的助手,使用提供的工具来回答问题。"
|
||||
)
|
||||
return agent
|
||||
|
||||
# 测试示例
|
||||
async def main():
|
||||
print("=" * 60)
|
||||
print("LangChain + MCP 测试")
|
||||
print(f"模型: {model_name}")
|
||||
print(f"API地址: {base_url}")
|
||||
print(f"MCP地址: {mcp_server_url}")
|
||||
print(f"Team ID: {team_id}")
|
||||
print(f"Token: {token[:10]}..." if len(token) > 10 else token)
|
||||
print("=" * 60)
|
||||
|
||||
# 加载MCP工具
|
||||
mcp_tools = await load_mcp_tools()
|
||||
all_tools = tools + mcp_tools
|
||||
|
||||
# 创建Agent
|
||||
agent = create_my_agent(all_tools)
|
||||
|
||||
# 测试1: 直接对话
|
||||
print("\n--- 测试1: 直接对话 ---")
|
||||
response = llm.invoke("你好,介绍一下自己")
|
||||
print(response.content)
|
||||
|
||||
# 测试2: 使用工具
|
||||
print("\n--- 测试2: 使用工具 - 获取当前时间 ---")
|
||||
result = await agent.ainvoke({
|
||||
"messages": [("user", "现在几点了?")]
|
||||
})
|
||||
print(result["messages"][-1].content)
|
||||
|
||||
# 测试3: 使用计算器
|
||||
print("\n--- 测试3: 使用工具 - 计算 ---")
|
||||
result = await agent.ainvoke({
|
||||
"messages": [("user", "计算 100 乘以 50 等于多少?")]
|
||||
})
|
||||
print(result["messages"][-1].content)
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,221 @@
|
||||
from flask import Flask, jsonify, request
|
||||
import subprocess
|
||||
import threading
|
||||
import time
|
||||
import os
|
||||
from datetime import datetime
|
||||
import schedule
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
# 配置参数
|
||||
RTSP_URL = "rtsp://10.68.66.174/audio"
|
||||
RECORD_DURATION_MINUTES = 60 # 录制时长(分钟)
|
||||
REST_DURATION_MINUTES = 20 # 休息时长(分钟)
|
||||
START_HOUR = 8 # 开始时间(小时)
|
||||
END_HOUR = 20 # 结束时间(小时)
|
||||
OUTPUT_DIR = "./" # 输出目录
|
||||
|
||||
# 录制状态
|
||||
recording_state = {
|
||||
"is_recording": False,
|
||||
"current_file": None,
|
||||
"start_time": None,
|
||||
"total_recorded": 0,
|
||||
"schedule_next": None
|
||||
}
|
||||
|
||||
def get_output_path():
|
||||
"""生成带时间戳的文件名"""
|
||||
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
||||
return os.path.join(OUTPUT_DIR, f"rtsp_{timestamp}.wav")
|
||||
|
||||
def is_within_schedule():
|
||||
"""检查当前是否在有效时间段内"""
|
||||
current_hour = datetime.now().hour
|
||||
return START_HOUR <= current_hour < END_HOUR
|
||||
|
||||
def record_audio():
|
||||
"""执行音频录制"""
|
||||
if recording_state["is_recording"]:
|
||||
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 正在录制中,跳过本次录制")
|
||||
return
|
||||
|
||||
if not is_within_schedule():
|
||||
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 不在有效时间段内(8:00-20:00),跳过本次录制")
|
||||
return
|
||||
|
||||
output_file = get_output_path()
|
||||
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 开始录制: {output_file}")
|
||||
|
||||
recording_state["is_recording"] = True
|
||||
recording_state["current_file"] = output_file
|
||||
recording_state["start_time"] = datetime.now()
|
||||
|
||||
try:
|
||||
# 使用 ffmpeg 录制
|
||||
cmd = [
|
||||
'ffmpeg',
|
||||
'-rtsp_transport', 'tcp',
|
||||
'-i', RTSP_URL,
|
||||
'-t', str(RECORD_DURATION_MINUTES * 60),
|
||||
'-acodec', 'pcm_s16le',
|
||||
'-ar', '16000',
|
||||
'-ac', '1',
|
||||
'-y',
|
||||
output_file
|
||||
]
|
||||
|
||||
process = subprocess.Popen(
|
||||
cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
universal_newlines=True
|
||||
)
|
||||
|
||||
# 监控录制进度
|
||||
start_time = time.time()
|
||||
while process.poll() is None:
|
||||
if os.path.exists(output_file):
|
||||
size_mb = os.path.getsize(output_file) / (1024 * 1024)
|
||||
elapsed = time.time() - start_time
|
||||
print(f"\r进度: {int(elapsed)}秒 / {RECORD_DURATION_MINUTES * 60}秒, 大小: {size_mb:.2f}MB", end='')
|
||||
time.sleep(1)
|
||||
|
||||
print() # 换行
|
||||
|
||||
# 录制完成
|
||||
if os.path.exists(output_file):
|
||||
size_mb = os.path.getsize(output_file) / (1024 * 1024)
|
||||
recording_state["total_recorded"] += 1
|
||||
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 录制完成: {output_file} ({size_mb:.2f}MB)")
|
||||
else:
|
||||
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 录制失败")
|
||||
|
||||
except Exception as e:
|
||||
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 录制错误: {e}")
|
||||
finally:
|
||||
recording_state["is_recording"] = False
|
||||
recording_state["current_file"] = None
|
||||
recording_state["start_time"] = None
|
||||
|
||||
# 录制完成后,在有效时间段内等待 REST_DURATION_MINUTES 分钟
|
||||
if is_within_schedule():
|
||||
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 进入休息模式,等待 {REST_DURATION_MINUTES} 分钟...")
|
||||
time.sleep(REST_DURATION_MINUTES * 60)
|
||||
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 休息结束")
|
||||
else:
|
||||
# 不在有效时间段,等待到下一个有效时间段
|
||||
now = datetime.now()
|
||||
if now.hour >= END_HOUR:
|
||||
# 等待到明天早上 8 点
|
||||
from datetime import timedelta
|
||||
next_day = now + timedelta(days=1)
|
||||
target = next_day.replace(hour=START_HOUR, minute=0, second=0, microsecond=0)
|
||||
else:
|
||||
# 等待到今天早上 8 点
|
||||
target = now.replace(hour=START_HOUR, minute=0, second=0, microsecond=0)
|
||||
|
||||
wait_seconds = (target - now).total_seconds()
|
||||
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 不在有效时间段,等待 {wait_seconds/3600:.1f} 小时...")
|
||||
time.sleep(wait_seconds)
|
||||
|
||||
def schedule_recording():
|
||||
"""定时录制任务"""
|
||||
thread = threading.Thread(target=record_audio, daemon=True)
|
||||
thread.start()
|
||||
|
||||
def run_scheduler():
|
||||
"""运行定时器"""
|
||||
# 设置定时任务:每小时整点录制
|
||||
schedule.every().hour.at(":00").do(schedule_recording)
|
||||
|
||||
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 定时录制服务已启动")
|
||||
print(f" - 录制时长: {RECORD_DURATION_MINUTES} 分钟")
|
||||
print(f" - 休息时长: {REST_DURATION_MINUTES} 分钟")
|
||||
print(f" - 有效时段: {START_HOUR}:00 - {END_HOUR}:00")
|
||||
print("-" * 50)
|
||||
|
||||
while True:
|
||||
schedule.run_pending()
|
||||
time.sleep(1)
|
||||
|
||||
# Flask 路由
|
||||
@app.route('/')
|
||||
def index():
|
||||
"""主页"""
|
||||
return jsonify({
|
||||
"service": "RTSP Audio Recorder",
|
||||
"status": "running" if recording_state["is_recording"] else "idle",
|
||||
"config": {
|
||||
"rtsp_url": RTSP_URL,
|
||||
"record_duration": f"{RECORD_DURATION_MINUTES} minutes",
|
||||
"rest_duration": f"{REST_DURATION_MINUTES} minutes",
|
||||
"schedule": f"{START_HOUR}:00 - {END_HOUR}:00"
|
||||
}
|
||||
})
|
||||
|
||||
@app.route('/status')
|
||||
def status():
|
||||
"""获取录制状态"""
|
||||
return jsonify({
|
||||
"is_recording": recording_state["is_recording"],
|
||||
"current_file": recording_state["current_file"],
|
||||
"start_time": recording_state["start_time"].isoformat() if recording_state["start_time"] else None,
|
||||
"total_recorded": recording_state["total_recorded"],
|
||||
"current_time": datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
|
||||
"is_in_schedule": is_within_schedule()
|
||||
})
|
||||
|
||||
@app.route('/start')
|
||||
def start_recording():
|
||||
"""手动开始录制"""
|
||||
if recording_state["is_recording"]:
|
||||
return jsonify({"status": "error", "message": "正在录制中"})
|
||||
|
||||
thread = threading.Thread(target=record_audio, daemon=True)
|
||||
thread.start()
|
||||
|
||||
return jsonify({"status": "success", "message": "开始录制"})
|
||||
|
||||
@app.route('/stop')
|
||||
def stop_recording():
|
||||
"""手动停止录制(终止 ffmpeg 进程)"""
|
||||
if not recording_state["is_recording"]:
|
||||
return jsonify({"status": "error", "message": "当前没有在录制"})
|
||||
|
||||
# 查找并终止 ffmpeg 进程
|
||||
try:
|
||||
subprocess.run(['taskkill', '/f', '/im', 'ffmpeg.exe'], capture_output=True)
|
||||
recording_state["is_recording"] = False
|
||||
return jsonify({"status": "success", "message": "已停止录制"})
|
||||
except Exception as e:
|
||||
return jsonify({"status": "error", "message": str(e)})
|
||||
|
||||
@app.route('/files')
|
||||
def list_files():
|
||||
"""列出已录制的文件"""
|
||||
files = []
|
||||
for f in os.listdir(OUTPUT_DIR):
|
||||
if f.endswith('.wav') and f.startswith('rtsp_'):
|
||||
path = os.path.join(OUTPUT_DIR, f)
|
||||
files.append({
|
||||
"name": f,
|
||||
"size": os.path.getsize(path),
|
||||
"modified": datetime.fromtimestamp(os.path.getmtime(path)).isoformat()
|
||||
})
|
||||
return jsonify({"files": files})
|
||||
|
||||
if __name__ == '__main__':
|
||||
# 确保输出目录存在
|
||||
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
||||
|
||||
# 启动定时器线程
|
||||
scheduler_thread = threading.Thread(target=run_scheduler, daemon=True)
|
||||
scheduler_thread.start()
|
||||
|
||||
# 启动 Flask 服务
|
||||
print(f"\n{'='*50}")
|
||||
print(f"RTSP 音频录制服务")
|
||||
print(f"{'='*50}")
|
||||
app.run(host='0.0.0.0', port=5000, debug=False, use_reloader=False)
|
||||
@@ -0,0 +1,232 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import subprocess
|
||||
import threading
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
# 配置参数
|
||||
RTSP_URL = "rtsp://10.68.66.174/audio"
|
||||
RECORD_DURATION_MINUTES = 60 # 录制时长(分钟)
|
||||
REST_DURATION_MINUTES = 20 # 休息时长(分钟)
|
||||
START_HOUR = 8 # 开始时间(小时)
|
||||
END_HOUR = 20 # 结束时间(小时)
|
||||
OUTPUT_DIR = "./" # 输出目录
|
||||
|
||||
# 录制状态
|
||||
recording_state = {
|
||||
"is_recording": False,
|
||||
"current_file": None,
|
||||
"start_time": None,
|
||||
"total_recorded": 0
|
||||
}
|
||||
|
||||
def log(msg):
|
||||
"""带时间戳的日志输出"""
|
||||
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] {msg}")
|
||||
sys.stdout.flush()
|
||||
|
||||
def check_dependencies():
|
||||
"""检查依赖是否满足"""
|
||||
errors = []
|
||||
|
||||
# 检查 Python 版本
|
||||
if sys.version_info[0] < 3:
|
||||
errors.append("需要 Python 3.x")
|
||||
|
||||
# 检查 ffmpeg
|
||||
try:
|
||||
result = subprocess.run(['ffmpeg', '-version'], capture_output=True, text=True, timeout=5)
|
||||
if result.returncode != 0:
|
||||
errors.append("ffmpeg 未正确安装")
|
||||
else:
|
||||
log("ffmpeg 已安装: " + result.stdout.split('\n')[0])
|
||||
except FileNotFoundError:
|
||||
errors.append("未找到 ffmpeg,请安装: yum install ffmpeg 或 apt install ffmpeg")
|
||||
except Exception as e:
|
||||
errors.append(f"检查 ffmpeg 时出错: {e}")
|
||||
|
||||
return errors
|
||||
|
||||
def get_output_path():
|
||||
"""生成带时间戳的文件名"""
|
||||
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
||||
return os.path.join(OUTPUT_DIR, f"rtsp_{timestamp}.wav")
|
||||
|
||||
def is_within_schedule():
|
||||
"""检查当前是否在有效时间段内"""
|
||||
current_hour = datetime.now().hour
|
||||
return START_HOUR <= current_hour < END_HOUR
|
||||
|
||||
def do_record(output_file):
|
||||
"""执行 ffmpeg 录制"""
|
||||
cmd = [
|
||||
'ffmpeg',
|
||||
'-rtsp_transport', 'tcp',
|
||||
'-i', RTSP_URL,
|
||||
'-t', str(RECORD_DURATION_MINUTES * 60),
|
||||
'-acodec', 'pcm_s16le',
|
||||
'-ar', '16000',
|
||||
'-ac', '1',
|
||||
'-y',
|
||||
output_file
|
||||
]
|
||||
|
||||
log(f"执行命令: {' '.join(cmd)}")
|
||||
|
||||
process = subprocess.Popen(
|
||||
cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
universal_newlines=True
|
||||
)
|
||||
|
||||
# 监控录制进度
|
||||
start_time = time.time()
|
||||
last_size = 0
|
||||
|
||||
while process.poll() is None:
|
||||
if os.path.exists(output_file):
|
||||
current_size = os.path.getsize(output_file)
|
||||
if current_size != last_size:
|
||||
size_mb = current_size / (1024 * 1024)
|
||||
elapsed = time.time() - start_time
|
||||
progress = (elapsed / (RECORD_DURATION_MINUTES * 60)) * 100
|
||||
print(f"\r进度: {int(elapsed)}秒 / {RECORD_DURATION_MINUTES * 60}秒 ({progress:.1f}%), 大小: {size_mb:.2f}MB", end='')
|
||||
sys.stdout.flush()
|
||||
last_size = current_size
|
||||
time.sleep(1)
|
||||
|
||||
print() # 换行
|
||||
|
||||
# 检查进程返回码
|
||||
if process.returncode != 0:
|
||||
log(f"ffmpeg 返回错误码: {process.returncode}")
|
||||
remaining = process.stdout.read()
|
||||
if remaining:
|
||||
log(f"ffmpeg 输出: {remaining[:500]}")
|
||||
|
||||
return process.returncode, output_file
|
||||
|
||||
def record_audio(check_schedule=True):
|
||||
"""执行音频录制
|
||||
check_schedule: 是否检查时间段限制
|
||||
"""
|
||||
if recording_state["is_recording"]:
|
||||
log("正在录制中,跳过本次录制")
|
||||
return
|
||||
|
||||
if check_schedule and not is_within_schedule():
|
||||
log(f"不在有效时间段内({START_HOUR}:00-{END_HOUR}:00),跳过本次录制")
|
||||
return
|
||||
|
||||
output_file = get_output_path()
|
||||
log(f"开始录制: {output_file}")
|
||||
|
||||
recording_state["is_recording"] = True
|
||||
recording_state["current_file"] = output_file
|
||||
recording_state["start_time"] = datetime.now()
|
||||
|
||||
try:
|
||||
returncode, file_path = do_record(output_file)
|
||||
|
||||
# 录制完成
|
||||
if os.path.exists(file_path):
|
||||
size_mb = os.path.getsize(file_path) / (1024 * 1024)
|
||||
recording_state["total_recorded"] += 1
|
||||
log(f"录制完成: {file_path} ({size_mb:.2f}MB)")
|
||||
else:
|
||||
log("录制失败,文件未生成")
|
||||
|
||||
except FileNotFoundError as e:
|
||||
log(f"命令未找到: {e}")
|
||||
log("请确保 ffmpeg 已安装并可在 PATH 中访问")
|
||||
except Exception as e:
|
||||
log(f"录制错误: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
recording_state["is_recording"] = False
|
||||
recording_state["current_file"] = None
|
||||
recording_state["start_time"] = None
|
||||
|
||||
def handle_rest():
|
||||
"""处理休息时间"""
|
||||
if is_within_schedule():
|
||||
log(f"进入休息模式,等待 {REST_DURATION_MINUTES} 分钟...")
|
||||
time.sleep(REST_DURATION_MINUTES * 60)
|
||||
log("休息结束")
|
||||
else:
|
||||
# 计算到下一个有效时间段
|
||||
now = datetime.now()
|
||||
if now.hour >= END_HOUR:
|
||||
next_day = now + timedelta(days=1)
|
||||
target = next_day.replace(hour=START_HOUR, minute=0, second=0, microsecond=0)
|
||||
else:
|
||||
target = now.replace(hour=START_HOUR, minute=0, second=0, microsecond=0)
|
||||
|
||||
wait_seconds = (target - now).total_seconds()
|
||||
log(f"不在有效时间段,等待 {wait_seconds/3600:.1f} 小时到 {START_HOUR}:00...")
|
||||
time.sleep(wait_seconds)
|
||||
|
||||
def run_scheduler():
|
||||
"""运行定时器"""
|
||||
log("定时录制服务已启动")
|
||||
log(f" - 录制时长: {RECORD_DURATION_MINUTES} 分钟")
|
||||
log(f" - 休息时长: {REST_DURATION_MINUTES} 分钟")
|
||||
log(f" - 有效时段: {START_HOUR}:00 - {END_HOUR}:00")
|
||||
log("-" * 50)
|
||||
|
||||
# 启动时立即开始录制(无视时间段)
|
||||
log("启动脚本,立即开始录制(本次无视时间段)")
|
||||
record_audio(check_schedule=False)
|
||||
|
||||
# 录制完成后处理休息
|
||||
if recording_state["total_recorded"] > 0:
|
||||
handle_rest()
|
||||
|
||||
while True:
|
||||
now = datetime.now()
|
||||
|
||||
# 检查是否在有效时间段内
|
||||
if is_within_schedule():
|
||||
# 每小时整点开始录制
|
||||
if now.minute == 0 and now.second == 0:
|
||||
log("整点时间到,开始录制")
|
||||
record_audio(check_schedule=True)
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
print("=" * 50)
|
||||
print("RTSP 音频录制服务")
|
||||
print("=" * 50)
|
||||
|
||||
# 检查依赖
|
||||
log("检查系统依赖...")
|
||||
errors = check_dependencies()
|
||||
|
||||
if errors:
|
||||
log("发现以下问题:")
|
||||
for error in errors:
|
||||
log(f" - {error}")
|
||||
log("请修复上述问题后重试")
|
||||
sys.exit(1)
|
||||
|
||||
# 确保输出目录存在
|
||||
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
||||
log(f"输出目录: {os.path.abspath(OUTPUT_DIR)}")
|
||||
|
||||
# 启动定时器
|
||||
try:
|
||||
run_scheduler()
|
||||
except KeyboardInterrupt:
|
||||
log("收到停止信号,正在退出...")
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,10 @@
|
||||
from requests import get
|
||||
|
||||
url = "http://10.68.66.174/mix.wav"
|
||||
output_path = "mix.wav"
|
||||
|
||||
response = get(url)
|
||||
with open(output_path, "wb") as f:
|
||||
f.write(response.content)
|
||||
|
||||
print(f"文件已下载到: {output_path}")
|
||||
@@ -0,0 +1,58 @@
|
||||
import oss2
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class AliyunOSSUploader:
|
||||
def __init__(self):
|
||||
self.access_key_id = "LTAI5tGTySgnmBWAzQMtKDSS"
|
||||
self.secret_access_key = "V3c7TI4KfK9ks8ReZGhSbADjX6avT0"
|
||||
self.endpoint = "oss-cn-beijing.aliyuncs.com"
|
||||
self.bucket_name = "remote-xtl"
|
||||
|
||||
auth = oss2.Auth(self.access_key_id, self.secret_access_key)
|
||||
self.bucket = oss2.Bucket(auth, self.endpoint, self.bucket_name)
|
||||
|
||||
def _progress_callback(self, consumed_bytes, total_bytes):
|
||||
if total_bytes:
|
||||
rate = int(consumed_bytes * 100 / total_bytes)
|
||||
print(f"\r上传进度: {rate}% ({consumed_bytes}/{total_bytes} bytes)", end="")
|
||||
|
||||
def upload(self, file_path, oss_object_name=None):
|
||||
file_path = Path(file_path)
|
||||
|
||||
if not file_path.exists():
|
||||
raise FileNotFoundError(f"文件不存在: {file_path}")
|
||||
|
||||
if oss_object_name is None:
|
||||
oss_object_name = file_path.name
|
||||
|
||||
print(f"正在上传: {file_path}")
|
||||
print(f"目标: oss://{self.bucket_name}/{oss_object_name}")
|
||||
|
||||
self.bucket.put_object_from_file(
|
||||
oss_object_name,
|
||||
str(file_path),
|
||||
progress_callback=self._progress_callback
|
||||
)
|
||||
|
||||
print(f"\n上传成功!")
|
||||
url = f"https://{self.bucket_name}.{self.endpoint}/{oss_object_name}"
|
||||
print(f"访问地址: {url}")
|
||||
return url
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
uploader = AliyunOSSUploader()
|
||||
|
||||
print("=" * 50)
|
||||
print("阿里云 OSS 文件上传工具")
|
||||
print("=" * 50)
|
||||
|
||||
file_path = input("\n请输入文件绝对路径: ").strip().strip('"').strip("'")
|
||||
|
||||
try:
|
||||
uploader.upload(file_path)
|
||||
except FileNotFoundError as e:
|
||||
print(f"\n错误: {e}")
|
||||
except Exception as e:
|
||||
print(f"\n上传失败: {e}")
|
||||
@@ -1,76 +0,0 @@
|
||||
import socket
|
||||
import threading
|
||||
from queue import Queue
|
||||
import time
|
||||
|
||||
# 定义要检查的IP范围和端口
|
||||
IP_BASE = "192.168.10."
|
||||
START_IP = 1
|
||||
END_IP = 255
|
||||
TARGET_PORT = 5555
|
||||
|
||||
# 线程数量,可根据需要调整
|
||||
THREAD_COUNT = 30
|
||||
|
||||
|
||||
def check_port(ip, port, result_queue):
|
||||
"""检查指定IP的端口是否开放"""
|
||||
try:
|
||||
# 创建socket对象
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
# 设置超时时间为1秒
|
||||
sock.settimeout(1)
|
||||
# 尝试连接
|
||||
result = sock.connect_ex((ip, port))
|
||||
if result == 0:
|
||||
result_queue.put(ip)
|
||||
sock.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def worker(ip_queue, result_queue):
|
||||
"""工作线程,从队列中获取IP并检查端口"""
|
||||
while not ip_queue.empty():
|
||||
ip = ip_queue.get()
|
||||
check_port(ip, TARGET_PORT, result_queue)
|
||||
ip_queue.task_done()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
start_time = time.time()
|
||||
print(f"开始扫描 {IP_BASE}{START_IP} 到 {IP_BASE}{END_IP} 的 {TARGET_PORT} 端口...")
|
||||
|
||||
# 创建IP队列
|
||||
ip_queue = Queue()
|
||||
for i in range(START_IP, END_IP + 1):
|
||||
ip = f"{IP_BASE}{i}"
|
||||
ip_queue.put(ip)
|
||||
|
||||
# 创建存储开放端口IP的队列
|
||||
result_queue = Queue()
|
||||
|
||||
# 创建并启动线程
|
||||
threads = []
|
||||
for _ in range(THREAD_COUNT):
|
||||
thread = threading.Thread(target=worker, args=(ip_queue, result_queue))
|
||||
thread.start()
|
||||
threads.append(thread)
|
||||
|
||||
# 等待所有IP都被处理
|
||||
ip_queue.join()
|
||||
|
||||
# 收集结果
|
||||
open_ips = []
|
||||
while not result_queue.empty():
|
||||
open_ips.append(result_queue.get())
|
||||
|
||||
# 排序结果
|
||||
open_ips.sort(key=lambda x: int(x.split(".")[-1]))
|
||||
|
||||
# 输出结果
|
||||
print("\n扫描完成!")
|
||||
print(f"耗时: {time.time() - start_time:.2f} 秒")
|
||||
print(f"发现 {len(open_ips)} 个设备的 {TARGET_PORT} 端口开放:")
|
||||
for ip in open_ips:
|
||||
print(f" {ip}:{TARGET_PORT}")
|
||||
@@ -1,50 +0,0 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
|
||||
block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(
|
||||
['port.py'],
|
||||
pathex=[],
|
||||
binaries=[],
|
||||
datas=[],
|
||||
hiddenimports=[],
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False,
|
||||
)
|
||||
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
|
||||
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
[],
|
||||
exclude_binaries=True,
|
||||
name='port',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
console=True,
|
||||
disable_windowed_traceback=False,
|
||||
argv_emulation=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None,
|
||||
)
|
||||
coll = COLLECT(
|
||||
exe,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
name='port',
|
||||
)
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"id": "fee9c5bf",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"401\n",
|
||||
"{'code': 'INVALID_API_KEY', 'message': 'Invalid API key'}\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import requests\n",
|
||||
"\n",
|
||||
"base_url = \"https://console.pivotbak.cfd/v1\"\n",
|
||||
"api_key = \"sk-e5246cf15eed1c8c1b94f172c95115de3ae5413eaa5b0366810fa7842de6ada1\"\n",
|
||||
"\n",
|
||||
"resp = requests.get(\n",
|
||||
" f\"{base_url}/models\",\n",
|
||||
" headers={\n",
|
||||
" \"Authorization\": f\"Bearer {api_key}\",\n",
|
||||
" \"Content-Type\": \"application/json\",\n",
|
||||
" },\n",
|
||||
" timeout=30,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"print(resp.status_code)\n",
|
||||
"print(resp.json())"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"id": "c479e82c",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"ename": "ModuleNotFoundError",
|
||||
"evalue": "No module named 'curl_cffi'",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
|
||||
"\u001b[1;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)",
|
||||
"Cell \u001b[1;32mIn[11], line 2\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mos\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcurl_cffi\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m requests\n\u001b[0;32m 4\u001b[0m BASE_URL \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhttps://console.pivotbak.cfd/v1\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 5\u001b[0m API_KEY \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msk-e5246cf15eed1c8c1b94f172c95115de3ae5413eaa5b0366810fa7842de6ada1\u001b[39m\u001b[38;5;124m\"\u001b[39m\n",
|
||||
"\u001b[1;31mModuleNotFoundError\u001b[0m: No module named 'curl_cffi'"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"from curl_cffi import requests\n",
|
||||
"\n",
|
||||
"BASE_URL = \"https://console.pivotbak.cfd/v1\"\n",
|
||||
"API_KEY = \"sk-e5246cf15eed1c8c1b94f172c95115de3ae5413eaa5b0366810fa7842de6ada1\"\n",
|
||||
"\n",
|
||||
"headers = {\n",
|
||||
" \"Authorization\": f\"Bearer {API_KEY}\",\n",
|
||||
" \"x-api-key\": API_KEY,\n",
|
||||
" \"Accept\": \"*/*\",\n",
|
||||
" \"Content-Type\": \"application/json\",\n",
|
||||
" \"sec-ch-ua-platform\": '\"Windows\"',\n",
|
||||
" \"sec-ch-ua\": '\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"',\n",
|
||||
" \"sec-ch-ua-mobile\": \"?0\",\n",
|
||||
" \"x-title\": \"Cherry Studio\",\n",
|
||||
" \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) CherryStudio/1.9.9 Chrome/146.0.7680.188 Electron/41.2.1 Safari/537.36\",\n",
|
||||
" \"HTTP-Referer\": \"https://cherry-ai.com\",\n",
|
||||
" \"Sec-Fetch-Site\": \"cross-site\",\n",
|
||||
" \"Sec-Fetch-Mode\": \"cors\",\n",
|
||||
" \"Sec-Fetch-Dest\": \"empty\",\n",
|
||||
" \"Accept-Encoding\": \"gzip, deflate, br, zstd\",\n",
|
||||
" \"Accept-Language\": \"zh-CN\",\n",
|
||||
" \"Priority\": \"u=1, i\",\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"resp = requests.get(\n",
|
||||
" f\"{BASE_URL}/models\",\n",
|
||||
" headers=headers,\n",
|
||||
" impersonate=\"chrome136\",\n",
|
||||
" timeout=30,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"print(\"status:\", resp.status_code)\n",
|
||||
"print(resp.text)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"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
|
||||
}
|
||||
+208
File diff suppressed because one or more lines are too long
@@ -0,0 +1,30 @@
|
||||
"input": "最近一次考试是什么?",
|
||||
"input": "最近一次数学考试的成绩情况",
|
||||
"input": "最近一次英语考试各班考得怎么样",
|
||||
"input": "最近一次语文考试全年级的平均分",
|
||||
"input": "最近一次考试是谁发布的?",
|
||||
"input": "帮我查一下期中相关的成绩批次",
|
||||
"input": "帮我看看最近一次数学考试的数据结构",
|
||||
"input": "帮我分析最近一次数学考试各班成绩情况",
|
||||
"input": "帮我看看最近一次数学考试整个年级的成绩概况",
|
||||
"input": "帮我分析最近一次数学考试的分数分布情况",
|
||||
"input": "帮我对比分析最近一次考试语文数学英语三个科目的成绩情况",
|
||||
"input": "帮我查一下白若耶是哪位学生",
|
||||
"input": "帮我看看白若耶最近整体成绩怎么样",
|
||||
"input": "把白若耶最近几次数学成绩列出来",
|
||||
"input": "白若耶最近10次数学考试的成绩趋势怎么样",
|
||||
"input": "只分析语文数学英语这三科,帮我看白若耶哪科强哪科弱",
|
||||
"input": "只看语文数学英语三科,白若耶偏科吗?",
|
||||
"input": "白若耶最近有没有退步预警?",
|
||||
"input": "帮我看看白若耶最近一次考试的成绩详情",
|
||||
"input": "先给我看看趋势分析有哪些可用参数和批次",
|
||||
"input": "帮我看一班最近几次数学考试的均分走势",
|
||||
"input": "帮我看最近几次数学考试整体均分变化",
|
||||
"input": "白若耶这次考试比上次是进步还是退步?",
|
||||
"input": "白若耶最近一次考试排第几名?",
|
||||
"input": "最近一次数学考试分段分析有哪些可用配置?",
|
||||
"input": "帮我看最近一次数学考试各分段人数分布",
|
||||
"input": "帮我看最近一次数学考试高分段有哪些学生",
|
||||
"input": "帮我比较最近两次数学考试各分数段人数变化",
|
||||
"input": "帮我对比分析语文数学英语三个科目在不同批次的成绩情况,按班级分组",
|
||||
"input": "帮我对比分析白若耶在语文数学英语三个科目的跨批次成绩"
|
||||
+184
@@ -0,0 +1,184 @@
|
||||
const BASE_URL = process.env.LANGGRAPH_URL || "http://192.168.0.100:2026";
|
||||
const ASSISTANT_ID = process.env.ASSISTANT_ID || "student_score";
|
||||
const QUESTION = process.env.QUESTION || "白若耶最近10次数学考试的成绩趋势怎么样";
|
||||
|
||||
const CONTEXT = {
|
||||
team_id: process.env.TEAM_ID || "19",
|
||||
env: process.env.AGENT_ENV || "dev",
|
||||
};
|
||||
|
||||
function parseJson(text) {
|
||||
try {
|
||||
return JSON.parse(text);
|
||||
} catch {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
async function createThread() {
|
||||
const response = await fetch(`${BASE_URL}/threads`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`create thread failed: ${response.status} ${await response.text()}`);
|
||||
}
|
||||
|
||||
const thread = await response.json();
|
||||
return thread.thread_id;
|
||||
}
|
||||
|
||||
function pickFinalAnswer(data) {
|
||||
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const renderAnswer = data.render_answer;
|
||||
if (renderAnswer && typeof renderAnswer.answer === "string") {
|
||||
return renderAnswer.answer;
|
||||
}
|
||||
|
||||
if (typeof data.answer === "string") {
|
||||
return data.answer;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
function pickReasoning(data) {
|
||||
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const renderAnswer = data.render_answer;
|
||||
if (renderAnswer && typeof renderAnswer.reasoning === "string") {
|
||||
return renderAnswer.reasoning;
|
||||
}
|
||||
|
||||
if (typeof data.reasoning === "string") {
|
||||
return data.reasoning;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
function handleEvent(eventName, dataText, answerParts, finalAnswers) {
|
||||
const data = parseJson(dataText);
|
||||
|
||||
if (eventName === "updates") {
|
||||
const finalAnswer = pickFinalAnswer(data);
|
||||
const reasoning = pickReasoning(data);
|
||||
if (data && typeof data === "object" && !Array.isArray(data)) {
|
||||
console.log(`\n[updates] ${Object.keys(data).join(", ")}`);
|
||||
} else {
|
||||
console.log("\n[updates]", data);
|
||||
}
|
||||
if (reasoning) {
|
||||
console.log("\n[reasoning]");
|
||||
console.log(reasoning);
|
||||
}
|
||||
if (finalAnswer) {
|
||||
finalAnswers.push(finalAnswer);
|
||||
console.log("\n[final.answer]");
|
||||
console.log(finalAnswer);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (eventName === "messages") {
|
||||
const messageChunk = Array.isArray(data) ? data[0] : undefined;
|
||||
const content = messageChunk && typeof messageChunk.content === "string" ? messageChunk.content : "";
|
||||
if (content) {
|
||||
answerParts.push(content);
|
||||
process.stdout.write(content);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (eventName) {
|
||||
console.log(`\n[${eventName}]`, data);
|
||||
}
|
||||
}
|
||||
|
||||
async function readSse(response) {
|
||||
if (!response.body) {
|
||||
throw new Error("response body is empty");
|
||||
}
|
||||
|
||||
const reader = response.body.getReader();
|
||||
const decoder = new TextDecoder("utf-8");
|
||||
const answerParts = [];
|
||||
const finalAnswers = [];
|
||||
let buffer = "";
|
||||
|
||||
while (true) {
|
||||
const { value, done } = await reader.read();
|
||||
if (done) break;
|
||||
|
||||
buffer += decoder.decode(value, { stream: true });
|
||||
const events = buffer.split(/\r?\n\r?\n/);
|
||||
buffer = events.pop() || "";
|
||||
|
||||
for (const rawEvent of events) {
|
||||
let eventName = "";
|
||||
const dataLines = [];
|
||||
|
||||
for (const line of rawEvent.split(/\r?\n/)) {
|
||||
if (line.startsWith("event:")) {
|
||||
eventName = line.slice("event:".length).trim();
|
||||
} else if (line.startsWith("data:")) {
|
||||
dataLines.push(line.slice("data:".length).trimStart());
|
||||
}
|
||||
}
|
||||
|
||||
handleEvent(eventName, dataLines.join("\n"), answerParts, finalAnswers);
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer.trim()) {
|
||||
handleEvent("", buffer.trim(), answerParts, finalAnswers);
|
||||
}
|
||||
|
||||
return finalAnswers.at(-1) || answerParts.join("");
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const threadId = await createThread();
|
||||
const endpoint = `${BASE_URL}/threads/${threadId}/runs/stream`;
|
||||
const started = Date.now();
|
||||
|
||||
console.log("=== LangGraph fetch stream test ===");
|
||||
console.log(`base_url: ${BASE_URL}`);
|
||||
console.log(`assistant_id: ${ASSISTANT_ID}`);
|
||||
console.log(`thread_id: ${threadId}`);
|
||||
console.log("");
|
||||
|
||||
const response = await fetch(endpoint, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "text/event-stream",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
assistant_id: ASSISTANT_ID,
|
||||
input: { question: QUESTION },
|
||||
context: CONTEXT,
|
||||
stream_mode: ["updates", "messages-tuple"],
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`stream request failed: ${response.status} ${await response.text()}`);
|
||||
}
|
||||
|
||||
const answer = await readSse(response);
|
||||
const elapsed = ((Date.now() - started) / 1000).toFixed(2);
|
||||
console.log(`\n\n=== done: ${elapsed}s, answer length: ${answer.length} ===`);
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
from typing import Any
|
||||
|
||||
from langgraph_sdk import get_client
|
||||
|
||||
|
||||
BASE_URL = os.getenv("LANGGRAPH_URL", "http://192.168.0.100:2026")
|
||||
ASSISTANT_ID = "student_score"
|
||||
QUESTION = "帮我看看白若耶同学的信息"
|
||||
CONTEXT = {
|
||||
"team_id": "19",
|
||||
"env": "dev",
|
||||
}
|
||||
|
||||
|
||||
if hasattr(sys.stdout, "reconfigure"):
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
|
||||
def event_data(event: Any) -> Any:
|
||||
if isinstance(event, dict):
|
||||
return event.get("data")
|
||||
return getattr(event, "data", None)
|
||||
|
||||
|
||||
def event_name(event: Any) -> str:
|
||||
if isinstance(event, dict):
|
||||
return str(event.get("event") or "")
|
||||
return str(getattr(event, "event", ""))
|
||||
|
||||
|
||||
def pick_final_answer(data: Any) -> str:
|
||||
if not isinstance(data, dict):
|
||||
return ""
|
||||
render_answer = data.get("render_answer")
|
||||
if isinstance(render_answer, dict) and isinstance(render_answer.get("answer"), str):
|
||||
return render_answer["answer"]
|
||||
answer = data.get("answer")
|
||||
return answer if isinstance(answer, str) else ""
|
||||
|
||||
|
||||
def pick_answer_source(data: Any) -> str:
|
||||
if not isinstance(data, dict):
|
||||
return ""
|
||||
render_answer = data.get("render_answer")
|
||||
if isinstance(render_answer, dict) and isinstance(render_answer.get("answer_source"), str):
|
||||
return render_answer["answer_source"]
|
||||
answer_source = data.get("answer_source")
|
||||
return answer_source if isinstance(answer_source, str) else ""
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
client = get_client(url=BASE_URL)
|
||||
thread = await client.threads.create()
|
||||
answer_parts: list[str] = []
|
||||
final_answers: list[str] = []
|
||||
|
||||
print("=== LangGraph updates + messages-tuple 流式调用 ===", flush=True)
|
||||
print("[updates] 节点进度;[messages] 最终 Markdown token。", flush=True)
|
||||
print("", flush=True)
|
||||
|
||||
async for event in client.runs.stream(
|
||||
thread_id=thread["thread_id"],
|
||||
assistant_id=ASSISTANT_ID,
|
||||
input={"question": QUESTION},
|
||||
context=CONTEXT,
|
||||
stream_mode=["updates", "messages-tuple"],
|
||||
):
|
||||
name = event_name(event)
|
||||
data = event_data(event)
|
||||
|
||||
if name == "updates":
|
||||
final_answer = pick_final_answer(data)
|
||||
answer_source = pick_answer_source(data)
|
||||
if isinstance(data, dict):
|
||||
print(f"\n[updates] {', '.join(data.keys())}", flush=True)
|
||||
render_answer = data.get("render_answer")
|
||||
if isinstance(render_answer, dict):
|
||||
print(f"[render_answer.keys] {', '.join(render_answer.keys())}", flush=True)
|
||||
else:
|
||||
print(f"\n[updates] {data}", flush=True)
|
||||
if answer_source:
|
||||
print(f"[answer_source] {answer_source}", flush=True)
|
||||
if final_answer:
|
||||
final_answers.append(final_answer)
|
||||
print("\n[final.answer]", flush=True)
|
||||
print(final_answer, flush=True)
|
||||
continue
|
||||
|
||||
if name == "messages":
|
||||
if isinstance(data, list) and data:
|
||||
message_chunk = data[0]
|
||||
content = message_chunk.get("content") if isinstance(message_chunk, dict) else ""
|
||||
if isinstance(content, str) and content:
|
||||
answer_parts.append(content)
|
||||
print(content, end="", flush=True)
|
||||
continue
|
||||
|
||||
print("\n\n=== 最终 Markdown 长度 ===", flush=True)
|
||||
print(len(final_answers[-1] if final_answers else "".join(answer_parts)), flush=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,58 @@
|
||||
import requests
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
url = "http://10.68.66.174/mix.wav"
|
||||
duration_minutes = 60 # 录制时长(分钟)
|
||||
output_file = f"recording_{datetime.now().strftime('%Y%m%d_%H%M%S')}.wav"
|
||||
|
||||
duration_seconds = duration_minutes * 60
|
||||
print(f"开始录制音频流...")
|
||||
print(f"录制时长: {duration_minutes} 分钟")
|
||||
print(f"保存路径: {output_file}")
|
||||
|
||||
start_time = time.time()
|
||||
chunk_size = 8192
|
||||
total_bytes = 0
|
||||
last_print_time = 0
|
||||
|
||||
try:
|
||||
response = requests.get(url, stream=True, timeout=60)
|
||||
response.raise_for_status()
|
||||
|
||||
with open(output_file, 'wb') as f:
|
||||
for chunk in response.iter_content(chunk_size=chunk_size):
|
||||
if chunk:
|
||||
f.write(chunk)
|
||||
total_bytes += len(chunk)
|
||||
|
||||
elapsed = time.time() - start_time
|
||||
|
||||
# 每10秒打印一次进度
|
||||
if int(elapsed) - last_print_time >= 10:
|
||||
last_print_time = int(elapsed)
|
||||
size_mb = total_bytes / (1024 * 1024)
|
||||
remaining = int(duration_seconds - elapsed)
|
||||
print(f"已录制: {int(elapsed)}秒 / {duration_seconds}秒 ({elapsed/duration_seconds*100:.1f}%), 大小: {size_mb:.2f}MB, 剩余: {remaining}秒")
|
||||
|
||||
# 达到指定时长后自动停止
|
||||
if elapsed >= duration_seconds:
|
||||
print(f"\n已达到指定录制时长 {duration_minutes} 分钟")
|
||||
break
|
||||
|
||||
elapsed = time.time() - start_time
|
||||
size_mb = total_bytes / (1024 * 1024)
|
||||
print(f"\n录制完成!")
|
||||
print(f"总时长: {int(elapsed)}秒 ({elapsed/60:.1f}分钟)")
|
||||
print(f"文件大小: {size_mb:.2f}MB")
|
||||
print(f"保存路径: {output_file}")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
elapsed = time.time() - start_time
|
||||
size_mb = total_bytes / (1024 * 1024)
|
||||
print(f"\n录制已手动停止")
|
||||
print(f"总时长: {int(elapsed)}秒 ({elapsed/60:.1f}分钟)")
|
||||
print(f"文件大小: {size_mb:.2f}MB")
|
||||
print(f"保存路径: {output_file}")
|
||||
except Exception as e:
|
||||
print(f"错误: {e}")
|
||||
+84
-27
@@ -20,7 +20,7 @@
|
||||
"port=3306,\n",
|
||||
"user='root',\n",
|
||||
"password='Abcd@123456',\n",
|
||||
"database='hongxx_video',\n",
|
||||
"database='hongxx',\n",
|
||||
"charset='utf8'\n",
|
||||
")\n",
|
||||
"# 创建游标对象\n",
|
||||
@@ -50,17 +50,17 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"execution_count": 26,
|
||||
"id": "b717043a",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"sql = 'select * from video_info'"
|
||||
"sql = 'select * from sys_user where dept_id=100'\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"execution_count": 27,
|
||||
"id": "b4b373b8",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -72,46 +72,103 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"id": "84652b4b",
|
||||
"execution_count": 28,
|
||||
"id": "394495d3",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[2,\n",
|
||||
" 3,\n",
|
||||
" 4,\n",
|
||||
" 6,\n",
|
||||
" 24,\n",
|
||||
" 31,\n",
|
||||
" 308,\n",
|
||||
" 909,\n",
|
||||
" 917,\n",
|
||||
" 918,\n",
|
||||
" 1145,\n",
|
||||
" 3690,\n",
|
||||
" 3698,\n",
|
||||
" 3828,\n",
|
||||
" 3842,\n",
|
||||
" 3843,\n",
|
||||
" 3844,\n",
|
||||
" 3895,\n",
|
||||
" 3899,\n",
|
||||
" 3912,\n",
|
||||
" 3913,\n",
|
||||
" 3935,\n",
|
||||
" 3936,\n",
|
||||
" 3988,\n",
|
||||
" 5440,\n",
|
||||
" 5492,\n",
|
||||
" 7696,\n",
|
||||
" 7713,\n",
|
||||
" 7714,\n",
|
||||
" 7723,\n",
|
||||
" 7728,\n",
|
||||
" 2059454179031199746]"
|
||||
]
|
||||
},
|
||||
"execution_count": 28,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"[i[\"user_id\"] for i in result]\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 25,
|
||||
"id": "325e4664",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"result\n",
|
||||
"# http://192.168.0.244:88/record/original-files/video/522e4c55fc804decafdd0a62e5a1bf74.mp4\n",
|
||||
"for item in result:\n",
|
||||
" if item[\"video_url\"].startswith(\"http://192.168.0.244:88\"):\n",
|
||||
" video_url = item[\"video_url\"].replace(\"http://192.168.0.244:88\",\"/mp4\")\n",
|
||||
" sql = f\"update video_info set video_url='{video_url}' where id={item['id']}\"\n",
|
||||
" cursor.execute(sql)"
|
||||
" userid = item[\"user_id\"]\n",
|
||||
" \n",
|
||||
" sql2 = f\"update sys_user set dept_id=100, team_user_type ='BACKEND' where user_id={userid}\"\n",
|
||||
" cursor.execute(sql2)\n",
|
||||
"connection.commit()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 24,
|
||||
"id": "f62b4e7d",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"for item in result:\n",
|
||||
" userid = item[\"user_id\"]\n",
|
||||
" sql2 = f\"update sys_user_dept set dept_id=100, person_type='hx_sys' where user_id={userid}\"\n",
|
||||
" cursor.execute(sql2)\n",
|
||||
"connection.commit()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "0b4381f4",
|
||||
"id": "7dcf47b8",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"ename": "",
|
||||
"evalue": "",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"\u001b[1;31m在当前单元格或上一个单元格中执行代码时 Kernel 崩溃。\n",
|
||||
"\u001b[1;31m请查看单元格中的代码,以确定故障的可能原因。\n",
|
||||
"\u001b[1;31m单击<a href='https://aka.ms/vscodeJupyterKernelCrash'>此处</a>了解详细信息。\n",
|
||||
"\u001b[1;31m有关更多详细信息,请查看 Jupyter <a href='command:jupyter.viewOutput'>log</a>。"
|
||||
]
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"for item in result:\n",
|
||||
" userid = item[\"user_id\"]\n",
|
||||
" sql2 = f\"update sys_user_role set dept_id=100 where user_id={userid}\"\n",
|
||||
" cursor.execute(sql2)\n",
|
||||
"connection.commit()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "base",
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"id": "42e17205",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# %%\n",
|
||||
"import pymysql\n",
|
||||
"\n",
|
||||
"# %%\n",
|
||||
"\n",
|
||||
"# 创建数据库连接\n",
|
||||
"connection = pymysql.connect(\n",
|
||||
"host='192.168.0.244',\n",
|
||||
"port=3300,\n",
|
||||
"user='root',\n",
|
||||
"password='hxyd1109',\n",
|
||||
"database='school_server',\n",
|
||||
"charset='utf8'\n",
|
||||
")\n",
|
||||
"cursor = connection.cursor()\n",
|
||||
"# %%\n",
|
||||
"def create_table(cursor,result):\n",
|
||||
" \n",
|
||||
" data = []\n",
|
||||
" for i in result:\n",
|
||||
" list_list = list(i)\n",
|
||||
" des=cursor.description # 获取表详情,字段名,长度,属性等\n",
|
||||
" t = \",\".join([item[0] for item in des])\n",
|
||||
" table_head = t.split(',') # # 查询表列名 用,分割\n",
|
||||
" \n",
|
||||
" dict_result = dict(zip(table_head, list_list)) # 打包为元组的列表 再转换为字典\n",
|
||||
" data.append(dict_result) # 将字典添加到list_result中\n",
|
||||
" return data\n",
|
||||
"\n",
|
||||
"# %%\n",
|
||||
"\n",
|
||||
"# %%\n",
|
||||
"\n",
|
||||
"# %%\n",
|
||||
"sql1 = \"select * from teacher where id=828\"\n",
|
||||
"cursor.execute(sql1)\n",
|
||||
"result=cursor.fetchall()\n",
|
||||
"table_app = create_table(cursor,result)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"id": "54db4116",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[{'id': 828,\n",
|
||||
" 'tea_name': '彭兰英',\n",
|
||||
" 'sex': 2,\n",
|
||||
" 'phone': '15198039323',\n",
|
||||
" 'type': 6,\n",
|
||||
" 'grade_id': None,\n",
|
||||
" 'class_id': None,\n",
|
||||
" 'user_name': 'ptszxbr9023',\n",
|
||||
" 'team_id': '110',\n",
|
||||
" 'pid': None,\n",
|
||||
" 'serial_no': '1336827486',\n",
|
||||
" 'openid': None,\n",
|
||||
" 'tea_no': 'ptszxbr9023',\n",
|
||||
" 'wx_phone': '15198039323',\n",
|
||||
" 'user_id': None,\n",
|
||||
" 'department_id': None,\n",
|
||||
" 'zt_teacher_uuid': None,\n",
|
||||
" 'hire': '职工',\n",
|
||||
" 'power': '门卫安保',\n",
|
||||
" 'class_type_name': None,\n",
|
||||
" 'hire_id': 98,\n",
|
||||
" 'flag': None,\n",
|
||||
" 'state': 1,\n",
|
||||
" 'sync_source': 'local'}]"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"table_app"
|
||||
]
|
||||
}
|
||||
],
|
||||
"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
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import pymysql
|
||||
import random
|
||||
import datetime
|
||||
import random
|
||||
# 创建数据库连接
|
||||
connection = pymysql.connect(
|
||||
host='192.168.0.244',
|
||||
port=3300,
|
||||
user='root',
|
||||
password='hxyd1109',
|
||||
database='school_server',
|
||||
charset='utf8'
|
||||
)
|
||||
# 创建游标对象
|
||||
cursor = connection.cursor()
|
||||
orgianl = {'id': 828,
|
||||
'tea_name': '彭兰英',
|
||||
'sex': 2,
|
||||
'phone': '15198039323',
|
||||
'type': 6,
|
||||
'grade_id': None,
|
||||
'class_id': None,
|
||||
'user_name': 'ptszxbr9023',
|
||||
'team_id': '110',
|
||||
'pid': None,
|
||||
'serial_no': '1336827486',
|
||||
'openid': None,
|
||||
'tea_no': 'ptszxbr9023',
|
||||
'wx_phone': '15198039323',
|
||||
'user_id': None,
|
||||
'department_id': None,
|
||||
'zt_teacher_uuid': None,
|
||||
'hire': '职工',
|
||||
'power': '门卫安保',
|
||||
'class_type_name': None,
|
||||
'hire_id': 98,
|
||||
'flag': None,
|
||||
'state': 1,
|
||||
'sync_source': 'local'}
|
||||
sql = f"""
|
||||
UPDATE `school_server`.`teacher` SET `tea_name` = '彭兰英' WHERE `id` = 828;
|
||||
"""
|
||||
cursor.execute(sql)
|
||||
connection.commit()
|
||||
cursor.close()
|
||||
connection.close()
|
||||
@@ -2,7 +2,7 @@
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"execution_count": 1,
|
||||
"id": "b82fd271",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -27,7 +27,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"execution_count": 2,
|
||||
"id": "759c550a",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
# %%
|
||||
import pymysql
|
||||
import pandas as pd
|
||||
import snowflake
|
||||
import random
|
||||
|
||||
# %%
|
||||
|
||||
# 创建数据库连接
|
||||
connection = pymysql.connect(
|
||||
host='100.64.0.36',
|
||||
user='root',
|
||||
password='@HXYD1109mysql',
|
||||
database='school_server',
|
||||
charset='utf8'
|
||||
)
|
||||
# 创建游标对象
|
||||
cursor = connection.cursor()
|
||||
sql="select id,stu_name from student where team_id=19"
|
||||
cursor.execute(sql)
|
||||
result=cursor.fetchall()
|
||||
|
||||
# %%
|
||||
def create_table(cursor,result):
|
||||
|
||||
data = []
|
||||
for i in result:
|
||||
list_list = list(i)
|
||||
des=cursor.description # 获取表详情,字段名,长度,属性等
|
||||
t = ",".join([item[0] for item in des])
|
||||
table_head = t.split(',') # # 查询表列名 用,分割
|
||||
|
||||
dict_result = dict(zip(table_head, list_list)) # 打包为元组的列表 再转换为字典
|
||||
data.append(dict_result) # 将字典添加到list_result中
|
||||
return data
|
||||
|
||||
# %%
|
||||
table = create_table(cursor,result)
|
||||
|
||||
# %%
|
||||
|
||||
# %%
|
||||
sql1 = "select user_name from account"
|
||||
cursor.execute(sql1)
|
||||
result=cursor.fetchall()
|
||||
table_app = create_table(cursor,result)
|
||||
|
||||
# %%
|
||||
|
||||
|
||||
# %%
|
||||
from requests import get,post
|
||||
import pandas as pd
|
||||
import time
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
import threading
|
||||
|
||||
# %%
|
||||
|
||||
# 常用弱密码列表
|
||||
WEAK_PASSWORDS = [
|
||||
"123456a",
|
||||
"123456",
|
||||
"admin123",
|
||||
"password",
|
||||
"admin@123",
|
||||
"root123",
|
||||
"12345678",
|
||||
"123456789",
|
||||
"888888",
|
||||
"666666",
|
||||
"123123",
|
||||
"111111",
|
||||
"qwerty",
|
||||
"abc123",
|
||||
"1q2w3e",
|
||||
"1qaz2wsx",
|
||||
"a123456",
|
||||
"Aa123456",
|
||||
"@123456",
|
||||
"Abcd1234",
|
||||
"Abcd@123",
|
||||
"admin",
|
||||
"123321",
|
||||
"000000",
|
||||
"1234",
|
||||
"12345",
|
||||
"test123",
|
||||
"pass123",
|
||||
"1234567",
|
||||
"1234567890",
|
||||
]
|
||||
|
||||
BASE_URL = "http://band.hxzhxy.cn"
|
||||
|
||||
# 先用一个已知弱密码账号验证接口是否通畅
|
||||
print("=" * 50)
|
||||
print("验证接口是否通畅...")
|
||||
test_param = {
|
||||
"username": "zhongwei",
|
||||
"password": "123456a",
|
||||
"client_id": "client",
|
||||
"grant_type": "password",
|
||||
"client_secret": "123456",
|
||||
}
|
||||
try:
|
||||
test_resp = get(url=f"{BASE_URL}/oauth/token", params=test_param, timeout=10).json()
|
||||
if "access_token" in test_resp:
|
||||
print("接口通畅,已获取测试 token")
|
||||
else:
|
||||
print(f"接口返回: {test_resp}")
|
||||
except Exception as e:
|
||||
print(f"接口请求异常: {e}")
|
||||
|
||||
# %%
|
||||
|
||||
# 线程安全的检测结果
|
||||
weak_accounts = []
|
||||
total_attempts = [0]
|
||||
lock = threading.Lock()
|
||||
|
||||
def try_account_password(account_idx, username):
|
||||
"""尝试单个账号的所有弱密码,返回找到的弱密码或 None"""
|
||||
for pwd in WEAK_PASSWORDS:
|
||||
param = {
|
||||
"username": username,
|
||||
"password": pwd,
|
||||
"client_id": "client",
|
||||
"grant_type": "password",
|
||||
"client_secret": "123456",
|
||||
}
|
||||
with lock:
|
||||
total_attempts[0] += 1
|
||||
attempt = total_attempts[0]
|
||||
|
||||
try:
|
||||
resp = get(url=f"{BASE_URL}/oauth/token", params=param, timeout=10)
|
||||
data = resp.json()
|
||||
|
||||
if "access_token" in data:
|
||||
print(f"[弱密码] 账号#{account_idx}: {username} | 密码: {pwd} | token: {data['access_token'][:20]}...")
|
||||
return {
|
||||
"username": username,
|
||||
"password": pwd,
|
||||
"token": data["access_token"],
|
||||
}
|
||||
except Exception as e:
|
||||
print(f" [异常] #{account_idx} {username} / {pwd} -> {e}")
|
||||
|
||||
return None
|
||||
|
||||
print("=" * 50)
|
||||
print(f"开始检测 {len(table_app)} 个账号的弱密码...")
|
||||
print(f"弱密码列表 ({len(WEAK_PASSWORDS)} 个): {WEAK_PASSWORDS}")
|
||||
print(f"线程数: 3")
|
||||
print("-" * 50)
|
||||
|
||||
start_time = time.time()
|
||||
completed = [0]
|
||||
|
||||
with ThreadPoolExecutor(max_workers=3) as executor:
|
||||
futures = {}
|
||||
for i, account in enumerate(table_app, 1):
|
||||
username = account['user_name']
|
||||
future = executor.submit(try_account_password, i, username)
|
||||
futures[future] = i
|
||||
|
||||
for future in as_completed(futures):
|
||||
result = future.result()
|
||||
with lock:
|
||||
completed[0] += 1
|
||||
if completed[0] % 10 == 0:
|
||||
elapsed = time.time() - start_time
|
||||
print(f"[进度] 已检测 {completed[0]}/{len(table_app)} | 用时 {elapsed:.1f}s | 发现弱密码: {len(weak_accounts)} 个")
|
||||
|
||||
if result:
|
||||
with lock:
|
||||
weak_accounts.append(result)
|
||||
|
||||
elapsed_total = time.time() - start_time
|
||||
|
||||
# %%
|
||||
|
||||
# 输出检测结果
|
||||
print("=" * 50)
|
||||
print("检测完成!")
|
||||
print(f"累计尝试 {total_attempts[0]} 次请求")
|
||||
print(f"耗时: {elapsed_total:.1f} 秒")
|
||||
print(f"发现 {len(weak_accounts)} 个弱密码账号:")
|
||||
print("=" * 50)
|
||||
|
||||
if weak_accounts:
|
||||
df_weak = pd.DataFrame(weak_accounts)
|
||||
# token 太长,截断显示
|
||||
df_weak["token_preview"] = df_weak["token"].str[:30] + "..."
|
||||
df_display = df_weak[["username", "password", "token_preview"]]
|
||||
print(df_display.to_string(index=False))
|
||||
|
||||
# 可选:导出到 Excel
|
||||
# df_weak.to_excel("weak_password_accounts.xlsx", index=False)
|
||||
# print("\n结果已导出到 weak_password_accounts.xlsx")
|
||||
else:
|
||||
print("未发现弱密码账号")
|
||||
|
||||
|
||||
|
||||
+2108
File diff suppressed because it is too large
Load Diff
+1059
-394
File diff suppressed because it is too large
Load Diff
+2156
-131
File diff suppressed because one or more lines are too long
@@ -0,0 +1,15 @@
|
||||
# %%
|
||||
import os
|
||||
os.add_dll_directory(os.getcwd())
|
||||
from pctoken import get_token
|
||||
from requests import get,post
|
||||
|
||||
# %%
|
||||
BASE_URL = 'http://net2.hxzhxy.cn:5092'
|
||||
USERNAME = 'xiatianle'
|
||||
PASSWORD = 'Xia123456'
|
||||
TOKEN = get_token(BASE_URL, USERNAME, PASSWORD)["access_token"]
|
||||
|
||||
|
||||
# %%
|
||||
print(TOKEN)
|
||||
+1
-1
@@ -27,7 +27,7 @@ def get_token(base_url: str, username: str, password: str) -> dict:
|
||||
oauth_client = 'hongxapp:hongxplapp'
|
||||
|
||||
enc_password = encrypt_password(password, enc_key)
|
||||
|
||||
print(enc_password)
|
||||
url = f"{base_url.rstrip('/')}/auth/oauth2/token"
|
||||
params = {
|
||||
'username': username,
|
||||
|
||||
+238
-32
@@ -2,7 +2,7 @@
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"execution_count": 2,
|
||||
"id": "70c9ccec",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -15,7 +15,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 24,
|
||||
"execution_count": null,
|
||||
"id": "379f4db2",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
@@ -23,81 +23,287 @@
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"342e75d2-dd64-4d6b-9316-da51fdce642d\n"
|
||||
"bN7Xn9xVdkyg\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ename": "",
|
||||
"evalue": "",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"\u001b[1;31m在当前单元格或上一个单元格中执行代码时 Kernel 崩溃。\n",
|
||||
"\u001b[1;31m请查看单元格中的代码,以确定故障的可能原因。\n",
|
||||
"\u001b[1;31m单击<a href='https://aka.ms/vscodeJupyterKernelCrash'>此处</a>了解详细信息。\n",
|
||||
"\u001b[1;31m有关更多详细信息,请查看 Jupyter <a href='command:jupyter.viewOutput'>log</a>。"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"BASE_URL = \"http://192.168.0.244:9999\"\n",
|
||||
"data = get_token(BASE_URL, \"admin\", \"123456\")\n",
|
||||
"TOKEN = data.get(\"access_token\", \"\")\n",
|
||||
"print(TOKEN)\n",
|
||||
"headers = {\n",
|
||||
" \"Authorization\": f\"Bearer {TOKEN}\",\n",
|
||||
" \"hx-client\": \"hongxapp\",\n",
|
||||
"}"
|
||||
"BASE_URL = 'http://192.168.0.10:9999'\n",
|
||||
"USERNAME = '00000001CDSPTSZX'\n",
|
||||
"PASSWORD = 'xia123456'\n",
|
||||
"TOKEN = get_token(BASE_URL, USERNAME, PASSWORD)[\"access_token\"]\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 31,
|
||||
"id": "820f6d23",
|
||||
"execution_count": 5,
|
||||
"id": "dcf475eb",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"'{\"timestamp\":\"2026-02-27 15:36:51\",\"status\":500,\"error\":\"Internal Server Error\",\"path\":\"/videoInfoStream/page\"}'"
|
||||
"'ee5552cb-7dd8-46b4-b54a-e8cf57e90ddc'"
|
||||
]
|
||||
},
|
||||
"execution_count": 31,
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"TOKEN"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 26,
|
||||
"id": "820f6d23",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"headers = {\n",
|
||||
" \"Authorization\": f\"Bearer {TOKEN}\",\n",
|
||||
" \"HX-CLIENT\": \"hongxapp\",\n",
|
||||
" 'H-SV-CODE':'video',\n",
|
||||
" 'Host': '192.168.0.111:5173',\n",
|
||||
" 'Referer': 'http://192.168.0.111:5173/'\n",
|
||||
"}\n",
|
||||
"get( \" http://192.168.0.244:9999/video/videoInfoStream/page?current=1&size=10&descs=&ascs=\",headers=headers).text"
|
||||
" 'hx-p-type':'WEB',\n",
|
||||
" 'hx-t-type':'PLATFORM',\n",
|
||||
"}\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "2c7227e6",
|
||||
"execution_count": 27,
|
||||
"id": "dd5eb589",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"'{\"timestamp\":\"2026-02-27 15:34:24\",\"status\":500,\"error\":\"Internal Server Error\",\"path\":\"/podPhoto/pageInfoBySections\"}'"
|
||||
"{'Authorization': 'Bearer 295b20e2-1ce0-44ab-8d74-384cdefc16bb',\n",
|
||||
" 'HX-CLIENT': 'hongxapp',\n",
|
||||
" 'hx-p-type': 'WEB',\n",
|
||||
" 'hx-t-type': 'PLATFORM'}"
|
||||
]
|
||||
},
|
||||
"execution_count": 21,
|
||||
"execution_count": 27,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": []
|
||||
"source": [
|
||||
"headers"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "1822efb2",
|
||||
"id": "869391ea",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
" # \"Accept\": 'application/json, text/plain, */*',\n",
|
||||
"# 'Connection': 'keep-alive',\n",
|
||||
"# 'H-SV-CODE':'video',\n",
|
||||
"# 'HX-CLIENT':'hongxapp',\n",
|
||||
"# 'Host': '192.168.0.111:5173',\n",
|
||||
"# 'Referer': 'http://192.168.0.111:5173/'"
|
||||
"post('http://192.168.0.10:8888/api/admin/user/v1/exist/add', headers=headers, json={\"userId\":\"2\",\"deptId\":\"19\",\"roleId\":\"2053724615032193025\"})\n",
|
||||
"{\"userId\":\"2\",\"deptId\":\"110\",\"roleId\":\"2055118564695838722\"}\n",
|
||||
"{\"userId\":\"2\",\"deptId\":\"119\",\"roleId\":\"2059515940711231489\"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"id": "7006382d",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"user_ids = [\n",
|
||||
" 3,\n",
|
||||
" 4,\n",
|
||||
" 6,\n",
|
||||
" 24,\n",
|
||||
" 31,\n",
|
||||
" 308,\n",
|
||||
" 909,\n",
|
||||
" 917,\n",
|
||||
" 918,\n",
|
||||
" 1145,\n",
|
||||
" 3690,\n",
|
||||
" 3698,\n",
|
||||
" 3828,\n",
|
||||
" 3842,\n",
|
||||
" 3843,\n",
|
||||
" 3844,\n",
|
||||
" 3895,\n",
|
||||
" 3899,\n",
|
||||
" 3912,\n",
|
||||
" 3913,\n",
|
||||
" 3935,\n",
|
||||
" 3936,\n",
|
||||
" 3988,\n",
|
||||
" 5440,\n",
|
||||
" 5492,\n",
|
||||
" 7696,\n",
|
||||
" 7713,\n",
|
||||
" 7714,\n",
|
||||
" 7723,\n",
|
||||
" 7728,\n",
|
||||
" 2059454179031199746]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 29,
|
||||
"id": "0e7366e2",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"{\"code\":1,\"msg\":\"用户不存在\",\"data\":null,\"ok\":false}\n",
|
||||
"{\"code\":1,\"msg\":\"用户不存在\",\"data\":null,\"ok\":false}\n",
|
||||
"{\"code\":1,\"msg\":\"用户不存在\",\"data\":null,\"ok\":false}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":1,\"msg\":\"用户不存在\",\"data\":null,\"ok\":false}\n",
|
||||
"{\"code\":1,\"msg\":\"用户不存在\",\"data\":null,\"ok\":false}\n",
|
||||
"{\"code\":1,\"msg\":\"用户不存在\",\"data\":null,\"ok\":false}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":1,\"msg\":\"用户不存在\",\"data\":null,\"ok\":false}\n",
|
||||
"{\"code\":1,\"msg\":\"用户不存在\",\"data\":null,\"ok\":false}\n",
|
||||
"{\"code\":1,\"msg\":\"用户不存在\",\"data\":null,\"ok\":false}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":1,\"msg\":\"用户不存在\",\"data\":null,\"ok\":false}\n",
|
||||
"{\"code\":1,\"msg\":\"用户不存在\",\"data\":null,\"ok\":false}\n",
|
||||
"{\"code\":1,\"msg\":\"用户不存在\",\"data\":null,\"ok\":false}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":1,\"msg\":\"用户不存在\",\"data\":null,\"ok\":false}\n",
|
||||
"{\"code\":1,\"msg\":\"用户不存在\",\"data\":null,\"ok\":false}\n",
|
||||
"{\"code\":1,\"msg\":\"用户不存在\",\"data\":null,\"ok\":false}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"{\"code\":0,\"msg\":null,\"data\":true,\"ok\":true}\n",
|
||||
"==================================================\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"for user_id in user_ids:\n",
|
||||
" resp = post('http://192.168.0.10:9999/admin/user/v1/exist/add', headers=headers, json={\"userId\":str(user_id),\"deptId\":\"110\",\"roleId\":\"2055118564695838722\"}).text\n",
|
||||
" resp1 = post('http://192.168.0.10:9999/admin/user/v1/exist/add', headers=headers, json={\"userId\":str(user_id),\"deptId\":\"119\",\"roleId\":\"2059515940711231489\"}).text\n",
|
||||
" resp2 = post('http://192.168.0.10:9999/admin/user/v1/exist/add', headers=headers, json={\"userId\":str(user_id),\"deptId\":\"19\",\"roleId\":\"2053724615032193025\"}).text\n",
|
||||
" print(resp)\n",
|
||||
" print(resp1)\n",
|
||||
" print(resp2)\n",
|
||||
" print(\"=\"*50)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
+1640
File diff suppressed because one or more lines are too long
+30
-16
@@ -2,7 +2,7 @@
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 18,
|
||||
"execution_count": 1,
|
||||
"id": "d9c14718",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -29,7 +29,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 19,
|
||||
"execution_count": 2,
|
||||
"id": "1673af54",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -43,7 +43,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 20,
|
||||
"execution_count": 3,
|
||||
"id": "4cf83c82",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -56,7 +56,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 21,
|
||||
"execution_count": 4,
|
||||
"id": "1790800e",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -66,7 +66,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"execution_count": 5,
|
||||
"id": "34f18ca5",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -77,7 +77,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 23,
|
||||
"execution_count": 6,
|
||||
"id": "7cf83679",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
@@ -87,7 +87,7 @@
|
||||
"0"
|
||||
]
|
||||
},
|
||||
"execution_count": 23,
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
@@ -120,17 +120,17 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 24,
|
||||
"execution_count": 8,
|
||||
"id": "e706bbb0",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<paho.mqtt.client.MQTTMessageInfo at 0x1b6a5f5e0c0>"
|
||||
"<paho.mqtt.client.MQTTMessageInfo at 0x1f295d5cef0>"
|
||||
]
|
||||
},
|
||||
"execution_count": 24,
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
@@ -146,10 +146,10 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"for item in data[0:1]:\n",
|
||||
"for item in data:\n",
|
||||
" print(item)\n",
|
||||
" mac=item[\"mac\"]\n",
|
||||
" topic=f\"cmd/publicizeBanpai/08E60E75E09E/control\"\n",
|
||||
" topic=f\"cmd/publicizeBanpai/{mac}/cmd\"\n",
|
||||
" message={\n",
|
||||
" \"type\":\"info\"\n",
|
||||
" }\n",
|
||||
@@ -158,17 +158,31 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 31,
|
||||
"execution_count": 11,
|
||||
"id": "3da280f9",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"for item in data:\n",
|
||||
" mac=item[\"mac\"]\n",
|
||||
" topic=f\"cmd/publicizeBanpai/{mac}/cmd\"\n",
|
||||
" message=\"reboot -p\"\n",
|
||||
" client.publish(topic, message)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"id": "82403f63",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<paho.mqtt.client.MQTTMessageInfo at 0x1b6a5c2bec0>"
|
||||
"<paho.mqtt.client.MQTTMessageInfo at 0x1f295d5c360>"
|
||||
]
|
||||
},
|
||||
"execution_count": 31,
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
@@ -204,7 +218,7 @@
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "undefined.undefined.undefined"
|
||||
"version": "3.12.4"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
||||
+29
-36
@@ -1,42 +1,35 @@
|
||||
from requests import get, post, put, delete
|
||||
import random
|
||||
from requests import get, post
|
||||
import time
|
||||
|
||||
ip = "http://192.168.0.209:8100"
|
||||
param = {
|
||||
"username": "zhongwei",
|
||||
"password": "123456a",
|
||||
"client_id": "client",
|
||||
"grant_type": "password",
|
||||
"client_secret": "123456",
|
||||
}
|
||||
data = get(url=f"{ip}/oauth/token", params=param).json()
|
||||
token = data["access_token"]
|
||||
header = {
|
||||
"content-type": "application/json",
|
||||
"authorization": f"Bearer {token}",
|
||||
}
|
||||
teamId = 110
|
||||
year = 2026
|
||||
month = 3
|
||||
|
||||
# v1.jinrishici.com/all.json
|
||||
def apiSentence():
|
||||
data = get("https://v1.hitokoto.cn").json()
|
||||
return data
|
||||
data1 = get(f"{ip}/classAttend/screen/summary", headers=header, params={"teamId": teamId, "year": year, "month": month}).text
|
||||
print("summary:", data1, end="\n\n")
|
||||
|
||||
data2 = get(f"{ip}/classAttend/screen/dailyTrend", headers=header, params={"teamId": teamId, "year": year, "month": month}).text
|
||||
print("dailyTrend:", data2, end="\n\n")
|
||||
|
||||
def cat():
|
||||
data = get("https://api.thecatapi.com/v1/images/search?size=full").json()
|
||||
result = data[0]["url"]
|
||||
return result
|
||||
data3 = get(f"{ip}/classAttend/screen/statusPie", headers=header, params={"teamId": teamId, "year": year, "month": month}).text
|
||||
print("statusPie:", data3, end="\n\n")
|
||||
|
||||
data4 = get(f"{ip}/classAttend/screen/gradeRanking", headers=header, params={"teamId": teamId, "year": year, "month": month}).text
|
||||
print("gradeRanking:", data4, end="\n\n")
|
||||
|
||||
def dog():
|
||||
data = get("https://api.thedogapi.com/v1/images/search?size=full").json()
|
||||
result = data[0]["url"]
|
||||
return result
|
||||
|
||||
|
||||
def pic():
|
||||
data = get("https://api.vvhan.com/api/bing?type=json&rand=sj").json()
|
||||
result = data["data"]["url"]
|
||||
return result
|
||||
|
||||
|
||||
def randomPic():
|
||||
func = random.choice([cat])
|
||||
data = func()
|
||||
return data
|
||||
|
||||
|
||||
def getEmoji():
|
||||
data = get("https://api.vvhan.com/api/emoji?type=json").json()
|
||||
return data
|
||||
|
||||
|
||||
def getShi():
|
||||
data = post("http://v1.jinrishici.com/all.json").json()
|
||||
return data
|
||||
data5 = get(f"{ip}/classAttend/screen/studentRanking", headers=header, params={"teamId": teamId, "year": year, "month": month}).text
|
||||
print("studentRanking:", data5, end="\n\n")
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
from requests import get,post
|
||||
import time
|
||||
ip = "http://192.168.0.209:8100"
|
||||
param = {
|
||||
"username": "zhongwei",
|
||||
"password": "123456a",
|
||||
"client_id": "client",
|
||||
"grant_type": "password",
|
||||
"client_secret": "123456",
|
||||
}
|
||||
data = get(url=f"{ip}/oauth/token",params=param).json()
|
||||
token = data["access_token"]
|
||||
header = {
|
||||
"content-type": "application/json",
|
||||
"authorization": f"Bearer {token}",
|
||||
}
|
||||
teamId=110
|
||||
month=5
|
||||
data1= get(f"{ip}/counseling/screen/stats",headers=header,params={"teamId":teamId,"year":2026,"month":month}).text
|
||||
print(data1,end="\n\n")
|
||||
|
||||
data2=get(f"{ip}/counseling/screen/trend",headers=header,params={"teamId":teamId,"year":2026,"month":month}).text
|
||||
print(data2,end="\n\n")
|
||||
|
||||
data3=get(f"{ip}/counseling/screen/statusDistribution",headers=header,params={"teamId":teamId,"year":2026,"month":month}).text
|
||||
print(data3,end="\n\n")
|
||||
|
||||
data4=get(f"{ip}/counseling/screen/gradeStats",headers=header,params={"teamId":teamId,"year":2026,"month":month}).text
|
||||
print(data4,end="\n\n")
|
||||
|
||||
data5=get(f"{ip}/counseling/screen/projectStats",headers=header,params={"teamId":teamId,"year":2026,"month":month}).text
|
||||
print(data5,end="\n\n")
|
||||
|
||||
data6=get(f"{ip}/counseling/screen/completionStats",headers=header,params={"teamId":teamId,"year":2026,"month":month}).text
|
||||
print(data6,end="\n\n")
|
||||
+45
-53
File diff suppressed because one or more lines are too long
@@ -0,0 +1,17 @@
|
||||
from requests import post
|
||||
tem = post("http://11.1.1.106:8082/api",json={
|
||||
"service_name": "operate_plate",
|
||||
"data": [
|
||||
{
|
||||
"departName": "百仁",
|
||||
"authType": 30000,
|
||||
"plateNumber": "鄂A1234569",
|
||||
"personName": "夏天乐测试",
|
||||
"plateIdStr": "test-plate-id-001",
|
||||
"opType": 1,
|
||||
"beginTime": "2026-05-18 17:53:44",
|
||||
"endTime": "2027-05-18 17:53:44"
|
||||
}
|
||||
]
|
||||
}).text
|
||||
print(tem)
|
||||
@@ -0,0 +1,288 @@
|
||||
from requests import get, post
|
||||
from faker import Faker
|
||||
import random
|
||||
import time
|
||||
import uuid
|
||||
import json
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
fake = Faker('zh_CN')
|
||||
|
||||
ip = "http://band.hxzhxy.cn"
|
||||
param = {
|
||||
"username": "xtl",
|
||||
"password": "xia123456",
|
||||
"client_id": "client",
|
||||
"grant_type": "password",
|
||||
"client_secret": "123456",
|
||||
}
|
||||
|
||||
def get_token():
|
||||
data = get(url=f"{ip}/oauth/token", params=param).json()
|
||||
return data["access_token"]
|
||||
|
||||
token = get_token()
|
||||
header = {
|
||||
"content-type": "application/json",
|
||||
"authorization": f"Bearer {token}",
|
||||
}
|
||||
teamId = 106
|
||||
|
||||
def generate_leave_data(stu_id, stu_name, stu_no, grade_name, class_name, grade_id, class_id, phone=None):
|
||||
leave_types = ["事假", "病假"]
|
||||
|
||||
leave_type = random.choice(leave_types)
|
||||
is_cycle = random.choice([1, 2, 3])
|
||||
|
||||
begin_date = datetime.now() - timedelta(days=random.randint(0,15))
|
||||
end_date = begin_date + timedelta(days=random.randint(0, 120))
|
||||
|
||||
begin_section = random.randint(1, 6)
|
||||
end_section = random.randint(begin_section, 12)
|
||||
|
||||
leave_reasons = [
|
||||
"身体不适,需要休息",
|
||||
"家中有事需要处理",
|
||||
"去医院检查身体",
|
||||
"发烧感冒,需要就医",
|
||||
"参加重要家庭活动",
|
||||
"个人事务需要处理",
|
||||
"肠胃不适,需要就医",
|
||||
"头痛发热,请假休息",
|
||||
"参加校外培训活动",
|
||||
"家庭紧急事务",
|
||||
]
|
||||
|
||||
disease_date = begin_date.strftime("%Y-%m-%d")
|
||||
|
||||
if is_cycle == 3:
|
||||
week_days = ["周一", "周二", "周三", "周四", "周五"]
|
||||
selected_day = random.choice(week_days)
|
||||
sections = random.sample(range(1, 13), random.randint(2, 4))
|
||||
sections.sort()
|
||||
week_info = json.dumps({selected_day: ",".join(str(s) for s in sections)})
|
||||
end_date = begin_date
|
||||
else:
|
||||
week_info = None
|
||||
|
||||
data = {
|
||||
"stuId": str(stu_id),
|
||||
"leaveType": leave_type,
|
||||
"isCycle": is_cycle,
|
||||
"leaveReason": random.choice(leave_reasons),
|
||||
"beginDate": begin_date.strftime("%Y-%m-%d"),
|
||||
"endDate": end_date.strftime("%Y-%m-%d"),
|
||||
"beginSection": str(begin_section),
|
||||
"endSection": str(end_section),
|
||||
"diseaseDate": disease_date,
|
||||
"symptom": "",
|
||||
"fever": "",
|
||||
"hospital": "",
|
||||
"treatmentDate": "",
|
||||
"imgUrl": "[]",
|
||||
"weekInfo": week_info,
|
||||
}
|
||||
|
||||
return data
|
||||
|
||||
def get_grade_list():
|
||||
url = f"{ip}/uc/grade/listSelect/{teamId}?access_token={token}"
|
||||
response = get(url, headers=header)
|
||||
result = response.json()
|
||||
if result.get('code') == 0:
|
||||
return result.get('data', [])
|
||||
return []
|
||||
|
||||
def get_class_list(grade_id):
|
||||
url = f"{ip}/uc/class/listClass"
|
||||
params = {
|
||||
"access_token": token,
|
||||
"teamId": teamId,
|
||||
"gradeId": grade_id
|
||||
}
|
||||
response = get(url, params=params, headers=header)
|
||||
result = response.json()
|
||||
if result.get('code') == 0:
|
||||
return result.get('data', [])
|
||||
return []
|
||||
|
||||
def get_students_from_db(grade_id=None, class_id=None):
|
||||
import pymysql
|
||||
conn = pymysql.connect(
|
||||
host='192.168.0.244',
|
||||
port=3306,
|
||||
user='root',
|
||||
password='Abcd@123456',
|
||||
database='school_server',
|
||||
charset='utf8'
|
||||
)
|
||||
cursor = conn.cursor()
|
||||
|
||||
sql = """
|
||||
SELECT s.id, s.stu_no, s.stu_name, s.phone,
|
||||
g.grade_name, c.class_name
|
||||
FROM student s
|
||||
LEFT JOIN grade g ON s.grade_id = g.id
|
||||
LEFT JOIN tclass c ON s.class_id = c.id
|
||||
WHERE s.team_id = %s
|
||||
"""
|
||||
params = [str(teamId)]
|
||||
|
||||
if grade_id:
|
||||
sql += " AND s.grade_id = %s"
|
||||
params.append(grade_id)
|
||||
if class_id:
|
||||
sql += " AND s.class_id = %s"
|
||||
params.append(class_id)
|
||||
|
||||
sql += " ORDER BY RAND() LIMIT 100"
|
||||
|
||||
cursor.execute(sql, params)
|
||||
students = cursor.fetchall()
|
||||
conn.close()
|
||||
return students
|
||||
|
||||
def add_leave_record(leave_data):
|
||||
url = f"{ip}/studentLeave/add"
|
||||
leave_data["access_token"] = token
|
||||
response = post(url, json=leave_data, headers=header)
|
||||
return response.json()
|
||||
|
||||
def batch_add_leaves(count=10):
|
||||
print(f"正在获取年级列表...")
|
||||
grades = get_grade_list()
|
||||
if not grades:
|
||||
print("未获取到年级数据,请检查 teamId 或 token")
|
||||
return
|
||||
|
||||
grade = random.choice(grades)
|
||||
grade_id = grade.get('id', grade.get('gradeId'))
|
||||
grade_name = grade.get('gradeName', grade.get('name', ''))
|
||||
print(f"随机选择年级: {grade_name}")
|
||||
|
||||
print(f"正在获取 [{grade_name}] 的班级列表...")
|
||||
classes = get_class_list(grade_id)
|
||||
if not classes:
|
||||
print("未获取到班级数据")
|
||||
return
|
||||
|
||||
cls = random.choice(classes)
|
||||
class_id = cls.get('id', cls.get('classId'))
|
||||
class_name = cls.get('className', cls.get('name', ''))
|
||||
print(f"随机选择班级: {class_name}")
|
||||
|
||||
print(f"\n正在从数据库获取 [{grade_name} {class_name}] 的学生数据...")
|
||||
students = get_students_from_db(grade_id, class_id)
|
||||
print(f"获取到 {len(students)} 名学生")
|
||||
|
||||
if not students:
|
||||
print("未获取到学生数据,请检查数据库连接")
|
||||
return
|
||||
|
||||
success_count = 0
|
||||
fail_count = 0
|
||||
|
||||
for i in range(min(count, len(students))):
|
||||
stu = students[i]
|
||||
stu_id, stu_no, stu_name, phone, db_grade_name, db_class_name = stu
|
||||
|
||||
leave_data = generate_leave_data(
|
||||
stu_id, stu_name, stu_no,
|
||||
grade_name, class_name, grade_id, class_id, phone
|
||||
)
|
||||
|
||||
print(f"\n[{i+1}/{min(count, len(students))}] 为学生 {stu_name}({stu_no}) 添加请假记录...")
|
||||
print(f" 请假类型: {leave_data['leaveType']}")
|
||||
print(f" 请假时间: {leave_data['beginDate']} ~ {leave_data['endDate']}")
|
||||
print(f" 请假节次: 第{leave_data['beginSection']}节 ~ 第{leave_data['endSection']}节")
|
||||
print(f" 请假事由: {leave_data['leaveReason']}")
|
||||
|
||||
try:
|
||||
result = add_leave_record(leave_data)
|
||||
if result.get('code') == 0:
|
||||
print(f" ✓ 添加成功")
|
||||
success_count += 1
|
||||
else:
|
||||
print(f" ✗ 添加失败: {result.get('msg', '未知错误')}")
|
||||
fail_count += 1
|
||||
except Exception as e:
|
||||
print(f" ✗ 请求异常: {e}")
|
||||
fail_count += 1
|
||||
|
||||
time.sleep(0.5)
|
||||
|
||||
print(f"\n{'='*50}")
|
||||
print(f"批量添加完成!")
|
||||
print(f"成功: {success_count} 条")
|
||||
print(f"失败: {fail_count} 条")
|
||||
|
||||
def generate_fake_students(count=20):
|
||||
students = []
|
||||
for i in range(count):
|
||||
stu = {
|
||||
"id": i + 1,
|
||||
"stu_no": f"2024{str(i+1).zfill(4)}",
|
||||
"stu_name": fake.name(),
|
||||
"phone": fake.phone_number(),
|
||||
"grade_name": random.choice(["初一", "初二", "初三", "高一", "高二", "高三"]),
|
||||
"class_name": f"{random.randint(1, 10)}班",
|
||||
}
|
||||
students.append(stu)
|
||||
return students
|
||||
|
||||
def batch_add_leaves_with_fake_students(count=10):
|
||||
print(f"使用 Faker 生成 {count} 条请假记录...")
|
||||
|
||||
students = generate_fake_students(count)
|
||||
success_count = 0
|
||||
fail_count = 0
|
||||
|
||||
for i, stu in enumerate(students):
|
||||
leave_data = generate_leave_data(
|
||||
stu['id'], stu['stu_name'], stu['stu_no'],
|
||||
stu['grade_name'], stu['class_name'],
|
||||
None, None, stu['phone']
|
||||
)
|
||||
|
||||
print(f"\n[{i+1}/{count}] 为学生 {stu['stu_name']}({stu['stu_no']}) 添加请假记录...")
|
||||
print(f" 请假类型: {leave_data['leaveType']}")
|
||||
print(f" 请假时间: {leave_data['beginDate']} ~ {leave_data['endDate']}")
|
||||
print(f" 请假节次: 第{leave_data['beginSection']}节 ~ 第{leave_data['endSection']}节")
|
||||
print(f" 请假事由: {leave_data['leaveReason']}")
|
||||
|
||||
try:
|
||||
result = add_leave_record(leave_data)
|
||||
if result.get('code') == 0:
|
||||
print(f" ✓ 添加成功")
|
||||
success_count += 1
|
||||
else:
|
||||
print(f" ✗ 添加失败: {result.get('msg', '未知错误')}")
|
||||
fail_count += 1
|
||||
except Exception as e:
|
||||
print(f" ✗ 请求异常: {e}")
|
||||
fail_count += 1
|
||||
|
||||
time.sleep(0.5)
|
||||
|
||||
print(f"\n{'='*50}")
|
||||
print(f"批量添加完成!")
|
||||
print(f"成功: {success_count} 条")
|
||||
print(f"失败: {fail_count} 条")
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("="*50)
|
||||
print("批量添加学生请假信息")
|
||||
print("="*50)
|
||||
print("1. 从数据库获取学生并添加请假记录")
|
||||
print("2. 使用 Faker 生成虚拟学生并添加请假记录")
|
||||
print("="*50)
|
||||
|
||||
choice = input("请选择模式 (1/2): ").strip()
|
||||
count = int(input("请输入要生成的请假记录数量: ").strip() or "10")
|
||||
|
||||
if choice == "1":
|
||||
batch_add_leaves(count)
|
||||
elif choice == "2":
|
||||
batch_add_leaves_with_fake_students(count)
|
||||
else:
|
||||
print("无效选择")
|
||||
@@ -0,0 +1,288 @@
|
||||
from requests import get, post
|
||||
from faker import Faker
|
||||
import random
|
||||
import time
|
||||
import uuid
|
||||
import json
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
fake = Faker('zh_CN')
|
||||
|
||||
ip = "http://band.hxzhxy.cn"
|
||||
param = {
|
||||
"username": "xtl",
|
||||
"password": "xia123456",
|
||||
"client_id": "client",
|
||||
"grant_type": "password",
|
||||
"client_secret": "123456",
|
||||
}
|
||||
|
||||
def get_token():
|
||||
data = get(url=f"{ip}/oauth/token", params=param).json()
|
||||
return data["access_token"]
|
||||
|
||||
token = get_token()
|
||||
header = {
|
||||
"content-type": "application/json",
|
||||
"authorization": f"Bearer {token}",
|
||||
}
|
||||
teamId = 106
|
||||
|
||||
def generate_leave_data(stu_id, stu_name, stu_no, grade_name, class_name, grade_id, class_id, phone=None):
|
||||
leave_types = ["事假", "病假"]
|
||||
|
||||
leave_type = random.choice(leave_types)
|
||||
is_cycle = random.choice([1, 2, 3])
|
||||
|
||||
begin_date = datetime.now() - timedelta(days=random.randint(0,15))
|
||||
end_date = begin_date + timedelta(days=random.randint(0, 120))
|
||||
|
||||
begin_section = random.randint(1, 6)
|
||||
end_section = random.randint(begin_section, 12)
|
||||
|
||||
leave_reasons = [
|
||||
"身体不适,需要休息",
|
||||
"家中有事需要处理",
|
||||
"去医院检查身体",
|
||||
"发烧感冒,需要就医",
|
||||
"参加重要家庭活动",
|
||||
"个人事务需要处理",
|
||||
"肠胃不适,需要就医",
|
||||
"头痛发热,请假休息",
|
||||
"参加校外培训活动",
|
||||
"家庭紧急事务",
|
||||
]
|
||||
|
||||
disease_date = begin_date.strftime("%Y-%m-%d")
|
||||
|
||||
if is_cycle == 3:
|
||||
week_days = ["周一", "周二", "周三", "周四", "周五"]
|
||||
selected_day = random.choice(week_days)
|
||||
sections = random.sample(range(1, 13), random.randint(2, 4))
|
||||
sections.sort()
|
||||
week_info = json.dumps({selected_day: ",".join(str(s) for s in sections)})
|
||||
end_date = begin_date
|
||||
else:
|
||||
week_info = None
|
||||
|
||||
data = {
|
||||
"stuId": str(stu_id),
|
||||
"leaveType": leave_type,
|
||||
"isCycle": is_cycle,
|
||||
"leaveReason": random.choice(leave_reasons),
|
||||
"beginDate": begin_date.strftime("%Y-%m-%d"),
|
||||
"endDate": end_date.strftime("%Y-%m-%d"),
|
||||
"beginSection": str(begin_section),
|
||||
"endSection": str(end_section),
|
||||
"diseaseDate": disease_date,
|
||||
"symptom": "",
|
||||
"fever": "",
|
||||
"hospital": "",
|
||||
"treatmentDate": "",
|
||||
"imgUrl": "[]",
|
||||
"weekInfo": week_info,
|
||||
}
|
||||
|
||||
return data
|
||||
|
||||
def get_grade_list():
|
||||
url = f"{ip}/uc/grade/listSelect/{teamId}?access_token={token}"
|
||||
response = get(url, headers=header)
|
||||
result = response.json()
|
||||
if result.get('code') == 0:
|
||||
return result.get('data', [])
|
||||
return []
|
||||
|
||||
def get_class_list(grade_id):
|
||||
url = f"{ip}/uc/class/listClass"
|
||||
params = {
|
||||
"access_token": token,
|
||||
"teamId": teamId,
|
||||
"gradeId": grade_id
|
||||
}
|
||||
response = get(url, params=params, headers=header)
|
||||
result = response.json()
|
||||
if result.get('code') == 0:
|
||||
return result.get('data', [])
|
||||
return []
|
||||
|
||||
def get_students_from_db(grade_id=None, class_id=None):
|
||||
import pymysql
|
||||
conn = pymysql.connect(
|
||||
host='100.64.0.36',
|
||||
port=3306,
|
||||
user='root',
|
||||
password='@HXYD1109mysql',
|
||||
database='school_server',
|
||||
charset='utf8'
|
||||
)
|
||||
cursor = conn.cursor()
|
||||
|
||||
sql = """
|
||||
SELECT s.id, s.stu_no, s.stu_name, s.phone,
|
||||
g.grade_name, c.class_name
|
||||
FROM student s
|
||||
LEFT JOIN grade g ON s.grade_id = g.id
|
||||
LEFT JOIN tclass c ON s.class_id = c.id
|
||||
WHERE s.team_id = %s
|
||||
"""
|
||||
params = [str(teamId)]
|
||||
|
||||
if grade_id:
|
||||
sql += " AND s.grade_id = %s"
|
||||
params.append(grade_id)
|
||||
if class_id:
|
||||
sql += " AND s.class_id = %s"
|
||||
params.append(class_id)
|
||||
|
||||
sql += " ORDER BY RAND() LIMIT 100"
|
||||
|
||||
cursor.execute(sql, params)
|
||||
students = cursor.fetchall()
|
||||
conn.close()
|
||||
return students
|
||||
|
||||
def add_leave_record(leave_data):
|
||||
url = f"{ip}/studentLeave/add"
|
||||
leave_data["access_token"] = token
|
||||
response = post(url, json=leave_data, headers=header)
|
||||
return response.json()
|
||||
|
||||
def batch_add_leaves(count=10):
|
||||
print(f"正在获取年级列表...")
|
||||
grades = get_grade_list()
|
||||
if not grades:
|
||||
print("未获取到年级数据,请检查 teamId 或 token")
|
||||
return
|
||||
|
||||
grade = random.choice(grades)
|
||||
grade_id = grade.get('id', grade.get('gradeId'))
|
||||
grade_name = grade.get('gradeName', grade.get('name', ''))
|
||||
print(f"随机选择年级: {grade_name}")
|
||||
|
||||
print(f"正在获取 [{grade_name}] 的班级列表...")
|
||||
classes = get_class_list(grade_id)
|
||||
if not classes:
|
||||
print("未获取到班级数据")
|
||||
return
|
||||
|
||||
cls = random.choice(classes)
|
||||
class_id = cls.get('id', cls.get('classId'))
|
||||
class_name = cls.get('className', cls.get('name', ''))
|
||||
print(f"随机选择班级: {class_name}")
|
||||
|
||||
print(f"\n正在从数据库获取 [{grade_name} {class_name}] 的学生数据...")
|
||||
students = get_students_from_db(grade_id, class_id)
|
||||
print(f"获取到 {len(students)} 名学生")
|
||||
|
||||
if not students:
|
||||
print("未获取到学生数据,请检查数据库连接")
|
||||
return
|
||||
|
||||
success_count = 0
|
||||
fail_count = 0
|
||||
|
||||
for i in range(min(count, len(students))):
|
||||
stu = students[i]
|
||||
stu_id, stu_no, stu_name, phone, db_grade_name, db_class_name = stu
|
||||
|
||||
leave_data = generate_leave_data(
|
||||
stu_id, stu_name, stu_no,
|
||||
grade_name, class_name, grade_id, class_id, phone
|
||||
)
|
||||
|
||||
print(f"\n[{i+1}/{min(count, len(students))}] 为学生 {stu_name}({stu_no}) 添加请假记录...")
|
||||
print(f" 请假类型: {leave_data['leaveType']}")
|
||||
print(f" 请假时间: {leave_data['beginDate']} ~ {leave_data['endDate']}")
|
||||
print(f" 请假节次: 第{leave_data['beginSection']}节 ~ 第{leave_data['endSection']}节")
|
||||
print(f" 请假事由: {leave_data['leaveReason']}")
|
||||
|
||||
try:
|
||||
result = add_leave_record(leave_data)
|
||||
if result.get('code') == 0:
|
||||
print(f" ✓ 添加成功")
|
||||
success_count += 1
|
||||
else:
|
||||
print(f" ✗ 添加失败: {result.get('msg', '未知错误')}")
|
||||
fail_count += 1
|
||||
except Exception as e:
|
||||
print(f" ✗ 请求异常: {e}")
|
||||
fail_count += 1
|
||||
|
||||
time.sleep(0.5)
|
||||
|
||||
print(f"\n{'='*50}")
|
||||
print(f"批量添加完成!")
|
||||
print(f"成功: {success_count} 条")
|
||||
print(f"失败: {fail_count} 条")
|
||||
|
||||
def generate_fake_students(count=20):
|
||||
students = []
|
||||
for i in range(count):
|
||||
stu = {
|
||||
"id": i + 1,
|
||||
"stu_no": f"2024{str(i+1).zfill(4)}",
|
||||
"stu_name": fake.name(),
|
||||
"phone": fake.phone_number(),
|
||||
"grade_name": random.choice(["初一", "初二", "初三", "高一", "高二", "高三"]),
|
||||
"class_name": f"{random.randint(1, 10)}班",
|
||||
}
|
||||
students.append(stu)
|
||||
return students
|
||||
|
||||
def batch_add_leaves_with_fake_students(count=10):
|
||||
print(f"使用 Faker 生成 {count} 条请假记录...")
|
||||
|
||||
students = generate_fake_students(count)
|
||||
success_count = 0
|
||||
fail_count = 0
|
||||
|
||||
for i, stu in enumerate(students):
|
||||
leave_data = generate_leave_data(
|
||||
stu['id'], stu['stu_name'], stu['stu_no'],
|
||||
stu['grade_name'], stu['class_name'],
|
||||
None, None, stu['phone']
|
||||
)
|
||||
|
||||
print(f"\n[{i+1}/{count}] 为学生 {stu['stu_name']}({stu['stu_no']}) 添加请假记录...")
|
||||
print(f" 请假类型: {leave_data['leaveType']}")
|
||||
print(f" 请假时间: {leave_data['beginDate']} ~ {leave_data['endDate']}")
|
||||
print(f" 请假节次: 第{leave_data['beginSection']}节 ~ 第{leave_data['endSection']}节")
|
||||
print(f" 请假事由: {leave_data['leaveReason']}")
|
||||
|
||||
try:
|
||||
result = add_leave_record(leave_data)
|
||||
if result.get('code') == 0:
|
||||
print(f" ✓ 添加成功")
|
||||
success_count += 1
|
||||
else:
|
||||
print(f" ✗ 添加失败: {result.get('msg', '未知错误')}")
|
||||
fail_count += 1
|
||||
except Exception as e:
|
||||
print(f" ✗ 请求异常: {e}")
|
||||
fail_count += 1
|
||||
|
||||
time.sleep(0.5)
|
||||
|
||||
print(f"\n{'='*50}")
|
||||
print(f"批量添加完成!")
|
||||
print(f"成功: {success_count} 条")
|
||||
print(f"失败: {fail_count} 条")
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("="*50)
|
||||
print("批量添加学生请假信息")
|
||||
print("="*50)
|
||||
print("1. 从数据库获取学生并添加请假记录")
|
||||
print("2. 使用 Faker 生成虚拟学生并添加请假记录")
|
||||
print("="*50)
|
||||
|
||||
choice = input("请选择模式 (1/2): ").strip()
|
||||
count = int(input("请输入要生成的请假记录数量: ").strip() or "10")
|
||||
|
||||
if choice == "1":
|
||||
batch_add_leaves(count)
|
||||
elif choice == "2":
|
||||
batch_add_leaves_with_fake_students(count)
|
||||
else:
|
||||
print("无效选择")
|
||||
@@ -0,0 +1,128 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "318e7588",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"ename": "",
|
||||
"evalue": "",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"\u001b[1;31m在当前单元格或上一个单元格中执行代码时 Kernel 崩溃。\n",
|
||||
"\u001b[1;31m请查看单元格中的代码,以确定故障的可能原因。\n",
|
||||
"\u001b[1;31m单击<a href='https://aka.ms/vscodeJupyterKernelCrash'>此处</a>了解详细信息。\n",
|
||||
"\u001b[1;31m有关更多详细信息,请查看 Jupyter <a href='command:jupyter.viewOutput'>log</a>。"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from requests import get,post\n",
|
||||
"import time\n",
|
||||
"ip = \"http://192.168.0.244:8100\"\n",
|
||||
"param = {\n",
|
||||
" \"username\": \"jz97621\",\n",
|
||||
" \"password\": \"123456a\",\n",
|
||||
" \"client_id\": \"client\",\n",
|
||||
" \"grant_type\": \"password\",\n",
|
||||
" \"client_secret\": \"123456\",\n",
|
||||
"}\n",
|
||||
"data = get(url=f\"{ip}/oauth/token\",params=param).json()\n",
|
||||
"token = data[\"access_token\"]\n",
|
||||
"header = {\n",
|
||||
" \"content-type\": \"application/json\",\n",
|
||||
" \"authorization\": f\"Bearer {token}\",\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "3c046d8d",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"ename": "ReadTimeout",
|
||||
"evalue": "HTTPConnectionPool(host='192.168.0.209', port=8100): Read timed out. (read timeout=600)",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
|
||||
"\u001b[1;31mTimeoutError\u001b[0m Traceback (most recent call last)",
|
||||
"File \u001b[1;32md:\\Anaconda3\\Lib\\site-packages\\urllib3\\connectionpool.py:534\u001b[0m, in \u001b[0;36mHTTPConnectionPool._make_request\u001b[1;34m(self, conn, method, url, body, headers, retries, timeout, chunked, response_conn, preload_content, decode_content, enforce_content_length)\u001b[0m\n\u001b[0;32m 533\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m--> 534\u001b[0m response \u001b[38;5;241m=\u001b[39m conn\u001b[38;5;241m.\u001b[39mgetresponse()\n\u001b[0;32m 535\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (BaseSSLError, \u001b[38;5;167;01mOSError\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m e:\n",
|
||||
"File \u001b[1;32md:\\Anaconda3\\Lib\\site-packages\\urllib3\\connection.py:565\u001b[0m, in \u001b[0;36mHTTPConnection.getresponse\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 564\u001b[0m \u001b[38;5;66;03m# Get the response from http.client.HTTPConnection\u001b[39;00m\n\u001b[1;32m--> 565\u001b[0m httplib_response \u001b[38;5;241m=\u001b[39m \u001b[38;5;28msuper\u001b[39m()\u001b[38;5;241m.\u001b[39mgetresponse()\n\u001b[0;32m 567\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n",
|
||||
"File \u001b[1;32md:\\Anaconda3\\Lib\\http\\client.py:1428\u001b[0m, in \u001b[0;36mHTTPConnection.getresponse\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 1427\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m-> 1428\u001b[0m response\u001b[38;5;241m.\u001b[39mbegin()\n\u001b[0;32m 1429\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mConnectionError\u001b[39;00m:\n",
|
||||
"File \u001b[1;32md:\\Anaconda3\\Lib\\http\\client.py:331\u001b[0m, in \u001b[0;36mHTTPResponse.begin\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 330\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[1;32m--> 331\u001b[0m version, status, reason \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_read_status()\n\u001b[0;32m 332\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m status \u001b[38;5;241m!=\u001b[39m CONTINUE:\n",
|
||||
"File \u001b[1;32md:\\Anaconda3\\Lib\\http\\client.py:292\u001b[0m, in \u001b[0;36mHTTPResponse._read_status\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 291\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_read_status\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[1;32m--> 292\u001b[0m line \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mstr\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfp\u001b[38;5;241m.\u001b[39mreadline(_MAXLINE \u001b[38;5;241m+\u001b[39m \u001b[38;5;241m1\u001b[39m), \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124miso-8859-1\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m 293\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(line) \u001b[38;5;241m>\u001b[39m _MAXLINE:\n",
|
||||
"File \u001b[1;32md:\\Anaconda3\\Lib\\socket.py:708\u001b[0m, in \u001b[0;36mSocketIO.readinto\u001b[1;34m(self, b)\u001b[0m\n\u001b[0;32m 707\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m--> 708\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_sock\u001b[38;5;241m.\u001b[39mrecv_into(b)\n\u001b[0;32m 709\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m timeout:\n",
|
||||
"\u001b[1;31mTimeoutError\u001b[0m: timed out",
|
||||
"\nThe above exception was the direct cause of the following exception:\n",
|
||||
"\u001b[1;31mReadTimeoutError\u001b[0m Traceback (most recent call last)",
|
||||
"File \u001b[1;32md:\\Anaconda3\\Lib\\site-packages\\requests\\adapters.py:589\u001b[0m, in \u001b[0;36mHTTPAdapter.send\u001b[1;34m(self, request, stream, timeout, verify, cert, proxies)\u001b[0m\n\u001b[0;32m 588\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m--> 589\u001b[0m resp \u001b[38;5;241m=\u001b[39m conn\u001b[38;5;241m.\u001b[39murlopen(\n\u001b[0;32m 590\u001b[0m method\u001b[38;5;241m=\u001b[39mrequest\u001b[38;5;241m.\u001b[39mmethod,\n\u001b[0;32m 591\u001b[0m url\u001b[38;5;241m=\u001b[39murl,\n\u001b[0;32m 592\u001b[0m body\u001b[38;5;241m=\u001b[39mrequest\u001b[38;5;241m.\u001b[39mbody,\n\u001b[0;32m 593\u001b[0m headers\u001b[38;5;241m=\u001b[39mrequest\u001b[38;5;241m.\u001b[39mheaders,\n\u001b[0;32m 594\u001b[0m redirect\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m,\n\u001b[0;32m 595\u001b[0m assert_same_host\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m,\n\u001b[0;32m 596\u001b[0m preload_content\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m,\n\u001b[0;32m 597\u001b[0m decode_content\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m,\n\u001b[0;32m 598\u001b[0m retries\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mmax_retries,\n\u001b[0;32m 599\u001b[0m timeout\u001b[38;5;241m=\u001b[39mtimeout,\n\u001b[0;32m 600\u001b[0m chunked\u001b[38;5;241m=\u001b[39mchunked,\n\u001b[0;32m 601\u001b[0m )\n\u001b[0;32m 603\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (ProtocolError, \u001b[38;5;167;01mOSError\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m err:\n",
|
||||
"File \u001b[1;32md:\\Anaconda3\\Lib\\site-packages\\urllib3\\connectionpool.py:841\u001b[0m, in \u001b[0;36mHTTPConnectionPool.urlopen\u001b[1;34m(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, preload_content, decode_content, **response_kw)\u001b[0m\n\u001b[0;32m 839\u001b[0m new_e \u001b[38;5;241m=\u001b[39m ProtocolError(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mConnection aborted.\u001b[39m\u001b[38;5;124m\"\u001b[39m, new_e)\n\u001b[1;32m--> 841\u001b[0m retries \u001b[38;5;241m=\u001b[39m retries\u001b[38;5;241m.\u001b[39mincrement(\n\u001b[0;32m 842\u001b[0m method, url, error\u001b[38;5;241m=\u001b[39mnew_e, _pool\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m, _stacktrace\u001b[38;5;241m=\u001b[39msys\u001b[38;5;241m.\u001b[39mexc_info()[\u001b[38;5;241m2\u001b[39m]\n\u001b[0;32m 843\u001b[0m )\n\u001b[0;32m 844\u001b[0m retries\u001b[38;5;241m.\u001b[39msleep()\n",
|
||||
"File \u001b[1;32md:\\Anaconda3\\Lib\\site-packages\\urllib3\\util\\retry.py:474\u001b[0m, in \u001b[0;36mRetry.increment\u001b[1;34m(self, method, url, response, error, _pool, _stacktrace)\u001b[0m\n\u001b[0;32m 473\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m read \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mFalse\u001b[39;00m \u001b[38;5;129;01mor\u001b[39;00m method \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_is_method_retryable(method):\n\u001b[1;32m--> 474\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m reraise(\u001b[38;5;28mtype\u001b[39m(error), error, _stacktrace)\n\u001b[0;32m 475\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m read \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n",
|
||||
"File \u001b[1;32md:\\Anaconda3\\Lib\\site-packages\\urllib3\\util\\util.py:39\u001b[0m, in \u001b[0;36mreraise\u001b[1;34m(tp, value, tb)\u001b[0m\n\u001b[0;32m 38\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m value\u001b[38;5;241m.\u001b[39mwith_traceback(tb)\n\u001b[1;32m---> 39\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m value\n\u001b[0;32m 40\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n",
|
||||
"File \u001b[1;32md:\\Anaconda3\\Lib\\site-packages\\urllib3\\connectionpool.py:787\u001b[0m, in \u001b[0;36mHTTPConnectionPool.urlopen\u001b[1;34m(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, preload_content, decode_content, **response_kw)\u001b[0m\n\u001b[0;32m 786\u001b[0m \u001b[38;5;66;03m# Make the request on the HTTPConnection object\u001b[39;00m\n\u001b[1;32m--> 787\u001b[0m response \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_make_request(\n\u001b[0;32m 788\u001b[0m conn,\n\u001b[0;32m 789\u001b[0m method,\n\u001b[0;32m 790\u001b[0m url,\n\u001b[0;32m 791\u001b[0m timeout\u001b[38;5;241m=\u001b[39mtimeout_obj,\n\u001b[0;32m 792\u001b[0m body\u001b[38;5;241m=\u001b[39mbody,\n\u001b[0;32m 793\u001b[0m headers\u001b[38;5;241m=\u001b[39mheaders,\n\u001b[0;32m 794\u001b[0m chunked\u001b[38;5;241m=\u001b[39mchunked,\n\u001b[0;32m 795\u001b[0m retries\u001b[38;5;241m=\u001b[39mretries,\n\u001b[0;32m 796\u001b[0m response_conn\u001b[38;5;241m=\u001b[39mresponse_conn,\n\u001b[0;32m 797\u001b[0m preload_content\u001b[38;5;241m=\u001b[39mpreload_content,\n\u001b[0;32m 798\u001b[0m decode_content\u001b[38;5;241m=\u001b[39mdecode_content,\n\u001b[0;32m 799\u001b[0m \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mresponse_kw,\n\u001b[0;32m 800\u001b[0m )\n\u001b[0;32m 802\u001b[0m \u001b[38;5;66;03m# Everything went great!\u001b[39;00m\n",
|
||||
"File \u001b[1;32md:\\Anaconda3\\Lib\\site-packages\\urllib3\\connectionpool.py:536\u001b[0m, in \u001b[0;36mHTTPConnectionPool._make_request\u001b[1;34m(self, conn, method, url, body, headers, retries, timeout, chunked, response_conn, preload_content, decode_content, enforce_content_length)\u001b[0m\n\u001b[0;32m 535\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (BaseSSLError, \u001b[38;5;167;01mOSError\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m--> 536\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_raise_timeout(err\u001b[38;5;241m=\u001b[39me, url\u001b[38;5;241m=\u001b[39murl, timeout_value\u001b[38;5;241m=\u001b[39mread_timeout)\n\u001b[0;32m 537\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m\n",
|
||||
"File \u001b[1;32md:\\Anaconda3\\Lib\\site-packages\\urllib3\\connectionpool.py:367\u001b[0m, in \u001b[0;36mHTTPConnectionPool._raise_timeout\u001b[1;34m(self, err, url, timeout_value)\u001b[0m\n\u001b[0;32m 366\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(err, SocketTimeout):\n\u001b[1;32m--> 367\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m ReadTimeoutError(\n\u001b[0;32m 368\u001b[0m \u001b[38;5;28mself\u001b[39m, url, \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mRead timed out. (read timeout=\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mtimeout_value\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m)\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 369\u001b[0m ) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01merr\u001b[39;00m\n\u001b[0;32m 371\u001b[0m \u001b[38;5;66;03m# See the above comment about EAGAIN in Python 3.\u001b[39;00m\n",
|
||||
"\u001b[1;31mReadTimeoutError\u001b[0m: HTTPConnectionPool(host='192.168.0.209', port=8100): Read timed out. (read timeout=600)",
|
||||
"\nDuring handling of the above exception, another exception occurred:\n",
|
||||
"\u001b[1;31mReadTimeout\u001b[0m Traceback (most recent call last)",
|
||||
"Cell \u001b[1;32mIn[2], line 2\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(\u001b[38;5;241m35\u001b[39m,\u001b[38;5;241m36\u001b[39m):\n\u001b[1;32m----> 2\u001b[0m post(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mip\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m/classAttendStu/createThisWeek\u001b[39m\u001b[38;5;124m\"\u001b[39m,headers\u001b[38;5;241m=\u001b[39mheader,params\u001b[38;5;241m=\u001b[39m{\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mplanId\u001b[39m\u001b[38;5;124m\"\u001b[39m:i},timeout\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m600\u001b[39m)\u001b[38;5;241m.\u001b[39mtext\n",
|
||||
"File \u001b[1;32md:\\Anaconda3\\Lib\\site-packages\\requests\\api.py:115\u001b[0m, in \u001b[0;36mpost\u001b[1;34m(url, data, json, **kwargs)\u001b[0m\n\u001b[0;32m 103\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mpost\u001b[39m(url, data\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, json\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[0;32m 104\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124mr\u001b[39m\u001b[38;5;124;03m\"\"\"Sends a POST request.\u001b[39;00m\n\u001b[0;32m 105\u001b[0m \n\u001b[0;32m 106\u001b[0m \u001b[38;5;124;03m :param url: URL for the new :class:`Request` object.\u001b[39;00m\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 112\u001b[0m \u001b[38;5;124;03m :rtype: requests.Response\u001b[39;00m\n\u001b[0;32m 113\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[1;32m--> 115\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m request(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mpost\u001b[39m\u001b[38;5;124m\"\u001b[39m, url, data\u001b[38;5;241m=\u001b[39mdata, json\u001b[38;5;241m=\u001b[39mjson, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
|
||||
"File \u001b[1;32md:\\Anaconda3\\Lib\\site-packages\\requests\\api.py:59\u001b[0m, in \u001b[0;36mrequest\u001b[1;34m(method, url, **kwargs)\u001b[0m\n\u001b[0;32m 55\u001b[0m \u001b[38;5;66;03m# By using the 'with' statement we are sure the session is closed, thus we\u001b[39;00m\n\u001b[0;32m 56\u001b[0m \u001b[38;5;66;03m# avoid leaving sockets open which can trigger a ResourceWarning in some\u001b[39;00m\n\u001b[0;32m 57\u001b[0m \u001b[38;5;66;03m# cases, and look like a memory leak in others.\u001b[39;00m\n\u001b[0;32m 58\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m sessions\u001b[38;5;241m.\u001b[39mSession() \u001b[38;5;28;01mas\u001b[39;00m session:\n\u001b[1;32m---> 59\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m session\u001b[38;5;241m.\u001b[39mrequest(method\u001b[38;5;241m=\u001b[39mmethod, url\u001b[38;5;241m=\u001b[39murl, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
|
||||
"File \u001b[1;32md:\\Anaconda3\\Lib\\site-packages\\requests\\sessions.py:589\u001b[0m, in \u001b[0;36mSession.request\u001b[1;34m(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)\u001b[0m\n\u001b[0;32m 584\u001b[0m send_kwargs \u001b[38;5;241m=\u001b[39m {\n\u001b[0;32m 585\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtimeout\u001b[39m\u001b[38;5;124m\"\u001b[39m: timeout,\n\u001b[0;32m 586\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mallow_redirects\u001b[39m\u001b[38;5;124m\"\u001b[39m: allow_redirects,\n\u001b[0;32m 587\u001b[0m }\n\u001b[0;32m 588\u001b[0m send_kwargs\u001b[38;5;241m.\u001b[39mupdate(settings)\n\u001b[1;32m--> 589\u001b[0m resp \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msend(prep, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39msend_kwargs)\n\u001b[0;32m 591\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m resp\n",
|
||||
"File \u001b[1;32md:\\Anaconda3\\Lib\\site-packages\\requests\\sessions.py:703\u001b[0m, in \u001b[0;36mSession.send\u001b[1;34m(self, request, **kwargs)\u001b[0m\n\u001b[0;32m 700\u001b[0m start \u001b[38;5;241m=\u001b[39m preferred_clock()\n\u001b[0;32m 702\u001b[0m \u001b[38;5;66;03m# Send the request\u001b[39;00m\n\u001b[1;32m--> 703\u001b[0m r \u001b[38;5;241m=\u001b[39m adapter\u001b[38;5;241m.\u001b[39msend(request, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m 705\u001b[0m \u001b[38;5;66;03m# Total elapsed time of the request (approximately)\u001b[39;00m\n\u001b[0;32m 706\u001b[0m elapsed \u001b[38;5;241m=\u001b[39m preferred_clock() \u001b[38;5;241m-\u001b[39m start\n",
|
||||
"File \u001b[1;32md:\\Anaconda3\\Lib\\site-packages\\requests\\adapters.py:635\u001b[0m, in \u001b[0;36mHTTPAdapter.send\u001b[1;34m(self, request, stream, timeout, verify, cert, proxies)\u001b[0m\n\u001b[0;32m 633\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m SSLError(e, request\u001b[38;5;241m=\u001b[39mrequest)\n\u001b[0;32m 634\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(e, ReadTimeoutError):\n\u001b[1;32m--> 635\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m ReadTimeout(e, request\u001b[38;5;241m=\u001b[39mrequest)\n\u001b[0;32m 636\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(e, _InvalidHeader):\n\u001b[0;32m 637\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m InvalidHeader(e, request\u001b[38;5;241m=\u001b[39mrequest)\n",
|
||||
"\u001b[1;31mReadTimeout\u001b[0m: HTTPConnectionPool(host='192.168.0.209', port=8100): Read timed out. (read timeout=600)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ename": "",
|
||||
"evalue": "",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"\u001b[1;31m在当前单元格或上一个单元格中执行代码时 Kernel 崩溃。\n",
|
||||
"\u001b[1;31m请查看单元格中的代码,以确定故障的可能原因。\n",
|
||||
"\u001b[1;31m单击<a href='https://aka.ms/vscodeJupyterKernelCrash'>此处</a>了解详细信息。\n",
|
||||
"\u001b[1;31m有关更多详细信息,请查看 Jupyter <a href='command:jupyter.viewOutput'>log</a>。"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"for i in range(35,36):\n",
|
||||
" post(f\"{ip}/classAttendStu/createThisWeek\",headers=header,params={\"planId\":i},timeout=600).text"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "343a9e44",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"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
|
||||
}
|
||||
+774
-11
@@ -2,24 +2,787 @@
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 2,
|
||||
"id": "83d3f4d5",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from requests import get,post\n",
|
||||
"import pandas as pd\n",
|
||||
"import time\n",
|
||||
"teamId = 19\n",
|
||||
"ip = \"http://192.168.0.209:8100\"\n",
|
||||
"param = {\n",
|
||||
" \"username\": \"zhongwei\",\n",
|
||||
" \"password\": \"123456a\",\n",
|
||||
" \"client_id\": \"client\",\n",
|
||||
" \"grant_type\": \"password\",\n",
|
||||
" \"client_secret\": \"123456\",\n",
|
||||
"}\n",
|
||||
"data = get(url=f\"{ip}/oauth/token\",params=param).json()\n",
|
||||
"token = data[\"access_token\"]\n",
|
||||
"header = {\n",
|
||||
" \"content-type\": \"application/json\",\n",
|
||||
" \"authorization\": f\"Bearer {token}\",\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"id": "873025e5",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"ename": "",
|
||||
"evalue": "",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"\u001b[1;31m在当前单元格或上一个单元格中执行代码时 Kernel 崩溃。\n",
|
||||
"\u001b[1;31m请查看单元格中的代码,以确定故障的可能原因。\n",
|
||||
"\u001b[1;31m单击<a href='https://aka.ms/vscodeJupyterKernelCrash'>此处</a>了解详细信息。\n",
|
||||
"\u001b[1;31m有关更多详细信息,请查看 Jupyter <a href='command:jupyter.viewOutput'>log</a>。"
|
||||
]
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"{'scrawlMaxSize': 10485760,\n",
|
||||
" 'videoMaxSize': 104857600,\n",
|
||||
" 'imageInsertAlign': 'none',\n",
|
||||
" 'catcherMaxSize': 10485760,\n",
|
||||
" 'snapscreenUrlPrefix': '',\n",
|
||||
" 'videoActionName': 'video',\n",
|
||||
" 'fileActionName': 'file',\n",
|
||||
" 'imageCompressBorder': 5000,\n",
|
||||
" 'imageManagerUrlPrefix': '',\n",
|
||||
" 'imageManagerAllowFiles': ['.jpg', '.png', '.jpeg'],\n",
|
||||
" 'scrawlUrlPrefix': '',\n",
|
||||
" 'scrawlFieldName': 'file',\n",
|
||||
" 'imageMaxSize': 10485760,\n",
|
||||
" 'imageAllowFiles': ['.jpg', '.png', '.jpeg'],\n",
|
||||
" 'snapscreenActionName': 'snap',\n",
|
||||
" 'fileMaxSize': 104857600,\n",
|
||||
" 'catcherActionName': 'catch',\n",
|
||||
" 'fileFieldName': 'file',\n",
|
||||
" 'fileManagerAllowFiles': ['.zip', '.pdf', '.doc'],\n",
|
||||
" 'fileManagerActionName': 'listFile',\n",
|
||||
" 'snapscreenInsertAlign': 'none',\n",
|
||||
" 'fileUrlPrefix': '',\n",
|
||||
" 'scrawlActionName': 'crawl',\n",
|
||||
" 'imageManagerInsertAlign': 'none',\n",
|
||||
" 'videoFieldName': 'file',\n",
|
||||
" 'catcherLocalDomain': ['127.0.0.1', 'localhost'],\n",
|
||||
" 'fileManagerListSize': 20,\n",
|
||||
" 'imageActionName': 'image',\n",
|
||||
" 'imageCompressEnable': True,\n",
|
||||
" 'imageFieldName': 'file',\n",
|
||||
" 'imageUrlPrefix': '',\n",
|
||||
" 'videoUrlPrefix': '',\n",
|
||||
" 'scrawlInsertAlign': 'none',\n",
|
||||
" 'fileAllowFiles': ['.zip', '.pdf', '.doc'],\n",
|
||||
" 'catcherUrlPrefix': '',\n",
|
||||
" 'imageManagerListSize': 20,\n",
|
||||
" 'catcherFieldName': 'source',\n",
|
||||
" 'fileManagerUrlPrefix': '',\n",
|
||||
" 'catcherAllowFiles': ['.jpg', '.png', '.jpeg'],\n",
|
||||
" 'videoAllowFiles': ['.mp4'],\n",
|
||||
" 'formulaConfig': {'imageUrlTemplate': 'https://r.latexeasy.com/image.svg?{}'},\n",
|
||||
" 'imageManagerActionName': 'listImage'}"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"df.to_excel('重新分班模板 (4).xlsx',index=False)"
|
||||
"get(f\"{ip}/uc/project/ueditor\",headers=header).json()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "c747c26d",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"{'success': True,\n",
|
||||
" 'msg': '操作成功',\n",
|
||||
" 'code': 0,\n",
|
||||
" 'data': [{'id': 11365245,\n",
|
||||
" 'stuName': '郭嘉欣',\n",
|
||||
" 'serialNo': '0022681452',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776050001000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8864,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': None},\n",
|
||||
" {'id': 11365248,\n",
|
||||
" 'stuName': '雷江昊然',\n",
|
||||
" 'serialNo': '0022681580',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': None,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': None,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8867,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': None},\n",
|
||||
" {'id': 11365267,\n",
|
||||
" 'stuName': '吴梓萌',\n",
|
||||
" 'serialNo': '0022722732',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036853000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8886,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036842000},\n",
|
||||
" {'id': 11365241,\n",
|
||||
" 'stuName': '程柏涵',\n",
|
||||
" 'serialNo': '0022795772',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036329000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8860,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036336000},\n",
|
||||
" {'id': 11365249,\n",
|
||||
" 'stuName': '李然壹',\n",
|
||||
" 'serialNo': '0022795964',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776035905000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8868,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776035899000},\n",
|
||||
" {'id': 11365274,\n",
|
||||
" 'stuName': '杨雨嘉',\n",
|
||||
" 'serialNo': '0022799916',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036401000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8893,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036382000},\n",
|
||||
" {'id': 11365238,\n",
|
||||
" 'stuName': '蔡雨芮',\n",
|
||||
" 'serialNo': '0022822732',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776035453000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8857,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776035468000},\n",
|
||||
" {'id': 11365265,\n",
|
||||
" 'stuName': '魏俊洁',\n",
|
||||
" 'serialNo': '0022830076',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036331000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8884,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036311000},\n",
|
||||
" {'id': 11365277,\n",
|
||||
" 'stuName': '姚祉玲',\n",
|
||||
" 'serialNo': '0022834044',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036142000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8896,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036135000},\n",
|
||||
" {'id': 11365260,\n",
|
||||
" 'stuName': '汪昊涵',\n",
|
||||
" 'serialNo': '3107628753',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': None,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': None,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8879,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': None},\n",
|
||||
" {'id': 11365244,\n",
|
||||
" 'stuName': '郭佳',\n",
|
||||
" 'serialNo': '3108354337',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776035462000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8863,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776035455000},\n",
|
||||
" {'id': 11365270,\n",
|
||||
" 'stuName': '徐文昊',\n",
|
||||
" 'serialNo': '3108354417',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036866000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8889,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036861000},\n",
|
||||
" {'id': 11367018,\n",
|
||||
" 'stuName': '唐悠雯',\n",
|
||||
" 'serialNo': '3108388513',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': None,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': None,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 10981,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': None},\n",
|
||||
" {'id': 11365259,\n",
|
||||
" 'stuName': '万梓涵',\n",
|
||||
" 'serialNo': '3108390097',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': None,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': None,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8878,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': None},\n",
|
||||
" {'id': 11365279,\n",
|
||||
" 'stuName': '朱泓安',\n",
|
||||
" 'serialNo': '3108390369',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036955000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8898,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036996000},\n",
|
||||
" {'id': 11365240,\n",
|
||||
" 'stuName': '陈峻鑫',\n",
|
||||
" 'serialNo': '3108390481',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036695000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8859,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036686000},\n",
|
||||
" {'id': 11365242,\n",
|
||||
" 'stuName': '代晋铭',\n",
|
||||
" 'serialNo': '3108415505',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776047344000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8861,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776047354000},\n",
|
||||
" {'id': 11365257,\n",
|
||||
" 'stuName': '唐裕康',\n",
|
||||
" 'serialNo': '3108415697',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036869000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8876,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036873000},\n",
|
||||
" {'id': 11365253,\n",
|
||||
" 'stuName': '吕仕瑞',\n",
|
||||
" 'serialNo': '3108435409',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776035766000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8872,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036856000},\n",
|
||||
" {'id': 11365255,\n",
|
||||
" 'stuName': '彭雨绮',\n",
|
||||
" 'serialNo': '3108435585',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036569000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8874,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036555000},\n",
|
||||
" {'id': 11365256,\n",
|
||||
" 'stuName': '孙婧琪',\n",
|
||||
" 'serialNo': '3108441105',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036193000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8875,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036185000},\n",
|
||||
" {'id': 11365258,\n",
|
||||
" 'stuName': '涂凤扬',\n",
|
||||
" 'serialNo': '3108442785',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036470000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8877,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036497000},\n",
|
||||
" {'id': 11365246,\n",
|
||||
" 'stuName': '何俊达',\n",
|
||||
" 'serialNo': '3108460593',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036368000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8865,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036374000},\n",
|
||||
" {'id': 11365271,\n",
|
||||
" 'stuName': '徐梓轩',\n",
|
||||
" 'serialNo': '3108464465',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776035922000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8890,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776035916000},\n",
|
||||
" {'id': 11365278,\n",
|
||||
" 'stuName': '张紫涵',\n",
|
||||
" 'serialNo': '3108580737',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776035797000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8897,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776035794000},\n",
|
||||
" {'id': 11365252,\n",
|
||||
" 'stuName': '罗靖洁',\n",
|
||||
" 'serialNo': '3108583121',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': None,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': None,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8871,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': None},\n",
|
||||
" {'id': 11365261,\n",
|
||||
" 'stuName': '王露静',\n",
|
||||
" 'serialNo': '3108583313',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036402000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8880,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036386000},\n",
|
||||
" {'id': 11365247,\n",
|
||||
" 'stuName': '侯家鸿',\n",
|
||||
" 'serialNo': '3108588801',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776035778000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8866,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776035778000},\n",
|
||||
" {'id': 11365262,\n",
|
||||
" 'stuName': '王洋梓桐',\n",
|
||||
" 'serialNo': '3108598337',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776059188000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8881,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': None},\n",
|
||||
" {'id': 11365268,\n",
|
||||
" 'stuName': '夏紫萱',\n",
|
||||
" 'serialNo': '3108601489',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036824000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8887,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036812000},\n",
|
||||
" {'id': 11365250,\n",
|
||||
" 'stuName': '刘鸿维',\n",
|
||||
" 'serialNo': '3108601841',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036278000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8869,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036308000},\n",
|
||||
" {'id': 11365276,\n",
|
||||
" 'stuName': '姚谊诚',\n",
|
||||
" 'serialNo': '3108603729',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': None,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': None,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8895,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776035945000},\n",
|
||||
" {'id': 11365269,\n",
|
||||
" 'stuName': '谢汶良',\n",
|
||||
" 'serialNo': '3108605233',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036656000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8888,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036671000},\n",
|
||||
" {'id': 11365273,\n",
|
||||
" 'stuName': '杨佳颖',\n",
|
||||
" 'serialNo': '3108606065',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036436000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8892,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036424000},\n",
|
||||
" {'id': 11365239,\n",
|
||||
" 'stuName': '曹雅莉',\n",
|
||||
" 'serialNo': '3108606273',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036335000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8858,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036329000},\n",
|
||||
" {'id': 11365251,\n",
|
||||
" 'stuName': '刘蔚菘',\n",
|
||||
" 'serialNo': '3108606433',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036055000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8870,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036089000},\n",
|
||||
" {'id': 11365275,\n",
|
||||
" 'stuName': '杨子涵',\n",
|
||||
" 'serialNo': '3108607729',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': None,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': None,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8894,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036154000},\n",
|
||||
" {'id': 11365243,\n",
|
||||
" 'stuName': '符唐骏',\n",
|
||||
" 'serialNo': '3108614209',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776035795000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8862,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776035802000},\n",
|
||||
" {'id': 11365263,\n",
|
||||
" 'stuName': '位云馨',\n",
|
||||
" 'serialNo': '3108633697',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': None,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': None,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8882,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': None},\n",
|
||||
" {'id': 11365266,\n",
|
||||
" 'stuName': '吴琳楠',\n",
|
||||
" 'serialNo': '3108635073',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036323000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8885,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036316000},\n",
|
||||
" {'id': 11365272,\n",
|
||||
" 'stuName': '杨丰瑞',\n",
|
||||
" 'serialNo': '3108650865',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776036330000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8891,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776036322000},\n",
|
||||
" {'id': 11365254,\n",
|
||||
" 'stuName': '庞雨橦',\n",
|
||||
" 'serialNo': '3108679985',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': 1776035795000,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': 1,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8873,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': 1776035786000},\n",
|
||||
" {'id': 11365264,\n",
|
||||
" 'stuName': '魏本杨',\n",
|
||||
" 'serialNo': '3108682001',\n",
|
||||
" 'gradeId': 126,\n",
|
||||
" 'classId': 474,\n",
|
||||
" 'startTime': None,\n",
|
||||
" 'endTime': None,\n",
|
||||
" 'intoState': None,\n",
|
||||
" 'boarder': 2,\n",
|
||||
" 'attendDate': 1776009600000,\n",
|
||||
" 'stuId': 8883,\n",
|
||||
" 'teamId': 119,\n",
|
||||
" 'lockTime': None,\n",
|
||||
" 'gateTime': None,\n",
|
||||
" 'gateStartTime': None}]}"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"get(\n",
|
||||
" f\"{ip}/classAttend/into/pre\",\n",
|
||||
" headers=header,\n",
|
||||
" params={\n",
|
||||
" \"teamId\": 119,\n",
|
||||
" \"dateTime\": 1776009600000,\n",
|
||||
" \"teaName\": \"马靖\",\n",
|
||||
" \"serial\": 9,\n",
|
||||
" \"courseName\": \"26学部1班-班会\",\n",
|
||||
" },\n",
|
||||
").json()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "3d80ee07",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"attendDate: \"2026-04-13\"\n",
|
||||
"classRoom: \"2510\"\n",
|
||||
"color: \"#FB923C\"\n",
|
||||
"courseName: \"26学部1班-班会\"\n",
|
||||
"serial: \"第9节\"\n",
|
||||
"serialnum: \"9\"\n",
|
||||
"status: \"下节课\"\n",
|
||||
"teaName: \"马靖\"\n",
|
||||
"timeSlot: \"16:20-17:00\""
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import pymysql
|
||||
import snowflake
|
||||
from faker import Faker
|
||||
fake = Faker('zh_CN')
|
||||
import random
|
||||
# 创建数据库连接
|
||||
conn = pymysql.connect(
|
||||
host='11.1.1.5',
|
||||
user='root',
|
||||
password='@HXYD1109mysql',
|
||||
database='school_server',
|
||||
charset='utf8'
|
||||
)
|
||||
# 创建游标对象
|
||||
cursor = conn.cursor()
|
||||
def create_table(cursor,result):
|
||||
|
||||
data = []
|
||||
for i in result:
|
||||
list_list = list(i)
|
||||
des=cursor.description # 获取表详情,字段名,长度,属性等
|
||||
t = ",".join([item[0] for item in des])
|
||||
table_head = t.split(',') # # 查询表列名 用,分割
|
||||
|
||||
dict_result = dict(zip(table_head, list_list)) # 打包为元组的列表 再转换为字典
|
||||
data.append(dict_result) # 将字典添加到list_result中
|
||||
return data
|
||||
@@ -0,0 +1,216 @@
|
||||
from requests import get
|
||||
import time
|
||||
import os
|
||||
import pandas as pd
|
||||
import tqdm
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
teamId = 19
|
||||
ip = "http://band.hxzhxy.cn"
|
||||
param = {
|
||||
"username": "xtl",
|
||||
"password": "xia123456",
|
||||
"client_id": "client",
|
||||
"grant_type": "password",
|
||||
"client_secret": "123456",
|
||||
}
|
||||
|
||||
data = get(url=f"{ip}/oauth/token", params=param).json()
|
||||
token = data["access_token"]
|
||||
header = {
|
||||
"content-type": "application/json",
|
||||
"authorization": f"Bearer {token}",
|
||||
}
|
||||
|
||||
url = f"{ip}/pay/trads/findPayTtadsNews"
|
||||
output_dir = r"e:\project\python\工具\智慧校园\本部\消费数据\24-26消费信息"
|
||||
|
||||
FIELD_MAP = {
|
||||
"gradeName": "年级名称",
|
||||
"termName": "交易地点",
|
||||
"teamId": "团队ID",
|
||||
"stuId": "学生ID",
|
||||
"areaName": "设备区域名称",
|
||||
"bagName": "交易账户",
|
||||
"userNumb": "学号/工号",
|
||||
"dealCount": "交易流水号/笔次",
|
||||
"className": "班级名称",
|
||||
"remark": "备注/充值类型",
|
||||
"cardCode": "物理卡号",
|
||||
"dealType": "消费方式",
|
||||
"cardValue": "余额",
|
||||
"userXm": "姓名",
|
||||
"cardNo": "卡号",
|
||||
"createDate": "入库时间",
|
||||
"dealValue": "交易金额",
|
||||
"recordType": "记录类型",
|
||||
"id": "记录ID",
|
||||
"recordId": "终端原始记录ID",
|
||||
"userId": "用户唯一ID",
|
||||
"dealTime": "交易时间"
|
||||
}
|
||||
|
||||
OUTPUT_COLUMNS = list(FIELD_MAP.values())
|
||||
|
||||
|
||||
def day_range(start_date, end_date):
|
||||
current = start_date
|
||||
while current <= end_date:
|
||||
yield current
|
||||
current += timedelta(days=1)
|
||||
|
||||
|
||||
def month_range(start_date, end_date):
|
||||
current = datetime(start_date.year, start_date.month, 1)
|
||||
end_month = datetime(end_date.year, end_date.month, 1)
|
||||
while current <= end_month:
|
||||
yield current
|
||||
if current.month == 12:
|
||||
current = datetime(current.year + 1, 1, 1)
|
||||
else:
|
||||
current = datetime(current.year, current.month + 1, 1)
|
||||
|
||||
|
||||
def to_timestamp_ms(dt):
|
||||
return int(dt.timestamp() * 1000)
|
||||
|
||||
|
||||
def fetch_day_records(day_dt):
|
||||
day_start = datetime(day_dt.year, day_dt.month, day_dt.day, 0, 0, 0)
|
||||
day_end = datetime(day_dt.year, day_dt.month, day_dt.day, 23, 59, 59)
|
||||
|
||||
begin_time = to_timestamp_ms(day_start)
|
||||
end_time = to_timestamp_ms(day_end)
|
||||
|
||||
page_number = 0
|
||||
page_size = 100
|
||||
day_records = []
|
||||
|
||||
while True:
|
||||
params = {
|
||||
"teamId": teamId,
|
||||
"pageNumber": page_number,
|
||||
"pageSize": page_size,
|
||||
"screen": 1,
|
||||
"beginTime": begin_time,
|
||||
"endTime": end_time,
|
||||
"name": "",
|
||||
"recordType": 1,
|
||||
"termName": "",
|
||||
"type": 1,
|
||||
"classId": "",
|
||||
"gradeId": ""
|
||||
}
|
||||
|
||||
resp = get(url=url, params=params, headers=header, timeout=60)
|
||||
resp.raise_for_status()
|
||||
result = resp.json()
|
||||
|
||||
if not result.get("success"):
|
||||
raise Exception(f"接口返回失败: {result}")
|
||||
|
||||
data = result.get("data") or {}
|
||||
content = data.get("content") or []
|
||||
total_pages = data.get("totalPages", 0)
|
||||
total_elements = data.get("totalElements", 0)
|
||||
|
||||
day_records.extend(content)
|
||||
|
||||
print(
|
||||
f"{day_dt.strftime('%Y-%m-%d')} 第 {page_number + 1}/{max(total_pages, 1)} 页,"
|
||||
f"当前页 {len(content)} 条,当天累计 {len(day_records)} 条,总计 {total_elements} 条"
|
||||
)
|
||||
|
||||
page_number += 1
|
||||
if page_number >= total_pages or total_pages == 0:
|
||||
break
|
||||
|
||||
time.sleep(0.1)
|
||||
|
||||
return day_records
|
||||
|
||||
|
||||
def parse_date(date_str):
|
||||
return datetime.strptime(date_str, "%Y-%m-%d")
|
||||
|
||||
|
||||
def convert_records_to_df(records):
|
||||
rows = []
|
||||
for record in records:
|
||||
row = {}
|
||||
for en_key, cn_key in FIELD_MAP.items():
|
||||
row[cn_key] = record.get(en_key)
|
||||
rows.append(row)
|
||||
if not rows:
|
||||
return pd.DataFrame(columns=OUTPUT_COLUMNS)
|
||||
return pd.DataFrame(rows, columns=OUTPUT_COLUMNS)
|
||||
|
||||
|
||||
def get_month_start_end(month_dt, start_date, end_date):
|
||||
month_start = datetime(month_dt.year, month_dt.month, 1)
|
||||
if month_dt.month == 12:
|
||||
next_month = datetime(month_dt.year + 1, 1, 1)
|
||||
else:
|
||||
next_month = datetime(month_dt.year, month_dt.month + 1, 1)
|
||||
month_end = next_month - timedelta(days=1)
|
||||
|
||||
if month_start < start_date:
|
||||
month_start = start_date
|
||||
if month_end > end_date:
|
||||
month_end = end_date
|
||||
|
||||
return month_start, month_end
|
||||
|
||||
|
||||
def save_month_excel(month_dt, records):
|
||||
df = convert_records_to_df(records)
|
||||
file_name = f"{month_dt.strftime('%Y%m')}_学生消费记录.xlsx"
|
||||
file_path = os.path.join(output_dir, file_name)
|
||||
df.to_excel(file_path, index=False)
|
||||
return file_path, len(df)
|
||||
|
||||
|
||||
def main():
|
||||
print("开始拉取数据...")
|
||||
start_date_str = os.getenv("START_DATE", "2024-01-01")
|
||||
end_date_str = os.getenv("END_DATE", "2026-05-19")
|
||||
|
||||
start_date = parse_date(start_date_str)
|
||||
end_date = parse_date(end_date_str)
|
||||
|
||||
all_month_list = list(month_range(start_date, end_date))
|
||||
total_records = 0
|
||||
success_months = 0
|
||||
|
||||
with tqdm.tqdm(all_month_list, desc="按月拉取消费记录") as month_pbar:
|
||||
for month_dt in month_pbar:
|
||||
try:
|
||||
month_start, month_end = get_month_start_end(month_dt, start_date, end_date)
|
||||
month_records = []
|
||||
month_days = list(day_range(month_start, month_end))
|
||||
|
||||
for day_dt in month_days:
|
||||
day_records = fetch_day_records(day_dt)
|
||||
month_records.extend(day_records)
|
||||
time.sleep(0.2)
|
||||
|
||||
file_path, count = save_month_excel(month_dt, month_records)
|
||||
total_records += count
|
||||
success_months += 1
|
||||
month_pbar.set_postfix({
|
||||
"month": month_dt.strftime("%Y-%m"),
|
||||
"count": count,
|
||||
"total": total_records
|
||||
})
|
||||
print(f"已输出: {file_path}")
|
||||
except Exception as e:
|
||||
print(f"{month_dt.strftime('%Y-%m')} 拉取失败: {e}")
|
||||
|
||||
print("\n完成")
|
||||
print(f"成功月份: {success_months}")
|
||||
print(f"总记录数: {total_records}")
|
||||
print(f"输出目录: {output_dir}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,89 @@
|
||||
import pandas as pd
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
# 读取Excel文件
|
||||
file_path = r'e:\project\python\工具\智慧校园\本部\消费数据\2024学生.xlsx'
|
||||
df = pd.read_excel(file_path)
|
||||
|
||||
print("=" * 80)
|
||||
print("学生消费数据提取")
|
||||
print("=" * 80)
|
||||
|
||||
# 1. 提取年级ID和班级ID(供用户查表)
|
||||
grade_ids = sorted(df['gradeId'].unique().tolist())
|
||||
class_ids = sorted(df['classId'].unique().tolist())
|
||||
|
||||
print(f"\n【年级ID列表】(共{len(grade_ids)}个):")
|
||||
print(grade_ids)
|
||||
|
||||
print(f"\n【班级ID列表】(共{len(class_ids)}个):")
|
||||
print(class_ids)
|
||||
|
||||
# 2. 提取学生消费信息
|
||||
student_records = []
|
||||
|
||||
for _, row in df.iterrows():
|
||||
record = {
|
||||
'学号': str(row['stuNo']),
|
||||
'姓名': row['stuName'],
|
||||
'年级ID': row['gradeId'],
|
||||
'班级ID': row['classId'],
|
||||
'支付金额(元)': row['totalFee'] / 100, # 转换为元
|
||||
'支付状态': '支付成功' if row['payState'] == 1 else '其他',
|
||||
'创建时间': row['createTime'].strftime('%Y-%m-%d %H:%M:%S') if pd.notna(row['createTime']) else '',
|
||||
'支付时间': row['payTime'].strftime('%Y-%m-%d %H:%M:%S') if pd.notna(row['payTime']) else '',
|
||||
'物理卡号': str(row['serialNo']) if pd.notna(row['serialNo']) else '',
|
||||
'teamId': row['teamId']
|
||||
}
|
||||
student_records.append(record)
|
||||
|
||||
# 3. 统计信息
|
||||
print(f"\n【数据统计】")
|
||||
print(f"总记录数: {len(student_records)}")
|
||||
print(f"唯一学生数: {df['stuNo'].nunique()}")
|
||||
print(f"总金额: {df['totalFee'].sum() / 100:.2f} 元")
|
||||
|
||||
# 4. 按年级统计
|
||||
print(f"\n【按年级统计】")
|
||||
grade_stats = df.groupby('gradeId').agg({
|
||||
'stuNo': 'nunique',
|
||||
'totalFee': 'sum'
|
||||
}).reset_index()
|
||||
grade_stats.columns = ['年级ID', '学生人数', '总金额(分)']
|
||||
grade_stats['总金额(元)'] = grade_stats['总金额(分)'] / 100
|
||||
print(grade_stats.to_string(index=False))
|
||||
|
||||
# 5. 按班级统计
|
||||
print(f"\n【按班级统计】")
|
||||
class_stats = df.groupby('classId').agg({
|
||||
'stuNo': 'nunique',
|
||||
'totalFee': 'sum'
|
||||
}).reset_index()
|
||||
class_stats.columns = ['班级ID', '学生人数', '总金额(分)']
|
||||
class_stats['总金额(元)'] = class_stats['总金额(分)'] / 100
|
||||
print(class_stats.to_string(index=False))
|
||||
|
||||
# 6. 保存详细记录到JSON
|
||||
output_file = r'e:\project\python\工具\智慧校园\本部\消费数据\student_records.json'
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(student_records, f, ensure_ascii=False, indent=2)
|
||||
|
||||
print(f"\n【输出文件】")
|
||||
print(f"详细记录已保存到: {output_file}")
|
||||
|
||||
# 7. 保存ID映射表(等待用户补充年级和班级名称)
|
||||
id_mapping = {
|
||||
'grade_ids': grade_ids,
|
||||
'class_ids': class_ids,
|
||||
'note': '请查询数据库补充年级名称和班级名称'
|
||||
}
|
||||
|
||||
id_mapping_file = r'e:\project\python\工具\智慧校园\本部\消费数据\id_mapping.json'
|
||||
with open(id_mapping_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(id_mapping, f, ensure_ascii=False, indent=2)
|
||||
|
||||
print(f"ID映射表已保存到: {id_mapping_file}")
|
||||
print("\n请查询数据库,告诉我以下ID对应的名称:")
|
||||
print(f"年级ID: {grade_ids}")
|
||||
print(f"班级ID: {class_ids}")
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "72fd36ef",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "base",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python",
|
||||
"version": "3.12.4"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import pandas as pd
|
||||
import json
|
||||
|
||||
# 读取Excel文件
|
||||
df = pd.read_excel('e:/project/python/工具/智慧校园/本部/消费数据/2024学生.xlsx')
|
||||
|
||||
print("=== Excel文件基本信息 ===")
|
||||
print(f"数据形状: {df.shape}")
|
||||
print(f"\n列名: {df.columns.tolist()}")
|
||||
|
||||
print("\n=== 前10行数据 ===")
|
||||
print(df.head(10))
|
||||
|
||||
print("\n=== 数据类型 ===")
|
||||
print(df.dtypes)
|
||||
|
||||
# 提取唯一值
|
||||
print("\n=== 唯一值统计 ===")
|
||||
for col in df.columns:
|
||||
unique_count = df[col].nunique()
|
||||
print(f"{col}: {unique_count} 个唯一值")
|
||||
if unique_count <= 20:
|
||||
print(f" 值: {df[col].unique().tolist()}")
|
||||
|
||||
# 检查是否有年级和班级相关字段
|
||||
grade_class_cols = [col for col in df.columns if any(keyword in col.lower() for keyword in ['年级', '班级', 'grade', 'class'])]
|
||||
print(f"\n=== 年级/班级相关字段: {grade_class_cols} ===")
|
||||
|
||||
# 保存列名信息供后续使用
|
||||
with open('e:/project/python/工具/智慧校园/本部/消费数据/excel_info.json', 'w', encoding='utf-8') as f:
|
||||
info = {
|
||||
'columns': df.columns.tolist(),
|
||||
'shape': df.shape,
|
||||
'sample_data': df.head(5).to_dict('records')
|
||||
}
|
||||
json.dump(info, f, ensure_ascii=False, indent=2)
|
||||
|
||||
print("\n=== 信息已保存到 excel_info.json ===")
|
||||
@@ -0,0 +1,24 @@
|
||||
import pandas as pd
|
||||
import sys
|
||||
|
||||
# 读取Excel文件
|
||||
file_path = r'e:\project\python\工具\智慧校园\本部\消费数据\2024学生.xlsx'
|
||||
df = pd.read_excel(file_path)
|
||||
|
||||
print("数据形状:", df.shape)
|
||||
print("\n列名:")
|
||||
for i, col in enumerate(df.columns):
|
||||
print(f"{i+1}. {col}")
|
||||
|
||||
print("\n前5行数据:")
|
||||
print(df.head().to_string())
|
||||
|
||||
# 检查年级和班级相关字段
|
||||
print("\n查找年级/班级相关字段...")
|
||||
for col in df.columns:
|
||||
if any(keyword in str(col) for keyword in ['年级', '班级', 'grade', 'class', 'Grade', 'Class']):
|
||||
print(f"找到字段: {col}")
|
||||
print(f"唯一值: {df[col].unique()[:10]}") # 只显示前10个唯一值
|
||||
|
||||
print("\n数据类型:")
|
||||
print(df.dtypes)
|
||||
@@ -0,0 +1,17 @@
|
||||
import pandas as pd
|
||||
|
||||
# 读取年级表和班级表
|
||||
grade_df = pd.read_excel(r'e:\project\python\工具\智慧校园\本部\消费数据\年级表.xlsx')
|
||||
class_df = pd.read_excel(r'e:\project\python\工具\智慧校园\本部\消费数据\班级表.xlsx')
|
||||
|
||||
print("=== 年级表 ===")
|
||||
print(f"形状: {grade_df.shape}")
|
||||
print(f"列名: {grade_df.columns.tolist()}")
|
||||
print("\n前10行:")
|
||||
print(grade_df.head(10))
|
||||
|
||||
print("\n=== 班级表 ===")
|
||||
print(f"形状: {class_df.shape}")
|
||||
print(f"列名: {class_df.columns.tolist()}")
|
||||
print("\n前10行:")
|
||||
print(class_df.head(10))
|
||||
@@ -0,0 +1,140 @@
|
||||
import pandas as pd
|
||||
from datetime import datetime
|
||||
|
||||
# 读取所有数据
|
||||
print("正在读取数据...")
|
||||
consumption_df = pd.read_excel(r'e:\project\python\工具\智慧校园\本部\消费数据\2024学生.xlsx')
|
||||
grade_df = pd.read_excel(r'e:\project\python\工具\智慧校园\本部\消费数据\年级表.xlsx')
|
||||
class_df = pd.read_excel(r'e:\project\python\工具\智慧校园\本部\消费数据\班级表.xlsx')
|
||||
|
||||
print(f"消费数据: {consumption_df.shape[0]} 条记录")
|
||||
print(f"年级表: {grade_df.shape[0]} 个年级")
|
||||
print(f"班级表: {class_df.shape[0]} 个班级")
|
||||
|
||||
# 创建年级ID到名称的映射
|
||||
grade_map = dict(zip(grade_df['id'], grade_df['grade_name']))
|
||||
|
||||
# 创建班级ID到名称的映射
|
||||
class_map = dict(zip(class_df['id'], class_df['class_name']))
|
||||
|
||||
# 创建班级ID到年级ID的映射(用于验证)
|
||||
class_to_grade_map = dict(zip(class_df['id'], class_df['grade_id']))
|
||||
|
||||
print("\n正在处理消费数据...")
|
||||
|
||||
# 处理消费数据
|
||||
processed_data = []
|
||||
|
||||
for _, row in consumption_df.iterrows():
|
||||
grade_id = row['gradeId']
|
||||
class_id = row['classId']
|
||||
|
||||
# 获取年级和班级名称
|
||||
grade_name = grade_map.get(grade_id, f'未知年级({grade_id})')
|
||||
class_name = class_map.get(class_id, f'未知班级({class_id})')
|
||||
|
||||
# 处理时间格式
|
||||
create_time = row['createTime']
|
||||
pay_time = row['payTime']
|
||||
|
||||
if pd.notna(create_time):
|
||||
if isinstance(create_time, str):
|
||||
create_time_str = create_time
|
||||
else:
|
||||
create_time_str = create_time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
else:
|
||||
create_time_str = ''
|
||||
|
||||
if pd.notna(pay_time):
|
||||
if isinstance(pay_time, str):
|
||||
pay_time_str = pay_time
|
||||
else:
|
||||
pay_time_str = pay_time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
else:
|
||||
pay_time_str = ''
|
||||
|
||||
# 处理支付状态
|
||||
pay_state_map = {0: '确认中', 1: '支付成功', 2: '已取消', 3: '退款'}
|
||||
pay_state = pay_state_map.get(row['payState'], f'未知状态({row["payState"]})')
|
||||
|
||||
# 处理充值状态
|
||||
change_state_map = {0: '充值中', 1: '已取消', 2: '充值成功', 3: '充值失败'}
|
||||
change_state = change_state_map.get(row['changeState'], f'未知状态({row["changeState"]})')
|
||||
|
||||
record = {
|
||||
'学号': str(row['stuNo']),
|
||||
'姓名': row['stuName'],
|
||||
'年级ID': grade_id,
|
||||
'年级名称': grade_name,
|
||||
'班级ID': class_id,
|
||||
'班级名称': class_name,
|
||||
'支付金额(元)': row['totalFee'] / 100,
|
||||
'支付状态': pay_state,
|
||||
'充值状态': change_state,
|
||||
'创建时间': create_time_str,
|
||||
'支付时间': pay_time_str,
|
||||
'物理卡号': str(int(row['serialNo'])) if pd.notna(row['serialNo']) else '',
|
||||
'订单编号': row['outTradeNo'],
|
||||
'微信订单号': row['transactionId'] if pd.notna(row['transactionId']) else '',
|
||||
'支付手机号': str(row['wxPhone']),
|
||||
'teamId': row['teamId']
|
||||
}
|
||||
processed_data.append(record)
|
||||
|
||||
# 创建DataFrame
|
||||
result_df = pd.DataFrame(processed_data)
|
||||
|
||||
# 生成输出文件名
|
||||
output_file = r'e:\project\python\工具\智慧校园\本部\消费数据\学生消费记录整理.xlsx'
|
||||
|
||||
# 写入Excel,使用多个sheet
|
||||
with pd.ExcelWriter(output_file, engine='openpyxl') as writer:
|
||||
# Sheet 1: 详细记录
|
||||
result_df.to_excel(writer, sheet_name='详细记录', index=False)
|
||||
|
||||
# Sheet 2: 按年级汇总
|
||||
grade_summary = result_df.groupby(['年级ID', '年级名称']).agg({
|
||||
'学号': 'nunique',
|
||||
'支付金额(元)': 'sum',
|
||||
'姓名': 'count'
|
||||
}).reset_index()
|
||||
grade_summary.columns = ['年级ID', '年级名称', '学生人数', '总金额(元)', '消费笔数']
|
||||
grade_summary = grade_summary.sort_values('年级ID')
|
||||
grade_summary.to_excel(writer, sheet_name='按年级汇总', index=False)
|
||||
|
||||
# Sheet 3: 按班级汇总
|
||||
class_summary = result_df.groupby(['班级ID', '班级名称', '年级名称']).agg({
|
||||
'学号': 'nunique',
|
||||
'支付金额(元)': 'sum',
|
||||
'姓名': 'count'
|
||||
}).reset_index()
|
||||
class_summary.columns = ['班级ID', '班级名称', '年级名称', '学生人数', '总金额(元)', '消费笔数']
|
||||
class_summary = class_summary.sort_values(['年级名称', '班级ID'])
|
||||
class_summary.to_excel(writer, sheet_name='按班级汇总', index=False)
|
||||
|
||||
# Sheet 4: 按学生汇总
|
||||
student_summary = result_df.groupby(['学号', '姓名', '年级名称', '班级名称']).agg({
|
||||
'支付金额(元)': 'sum',
|
||||
'创建时间': 'count'
|
||||
}).reset_index()
|
||||
student_summary.columns = ['学号', '姓名', '年级名称', '班级名称', '总金额(元)', '消费笔数']
|
||||
student_summary = student_summary.sort_values(['年级名称', '班级名称', '学号'])
|
||||
student_summary.to_excel(writer, sheet_name='按学生汇总', index=False)
|
||||
|
||||
print(f"\n✅ 数据整理完成!")
|
||||
print(f"📁 输出文件: {output_file}")
|
||||
print(f"\n📊 统计信息:")
|
||||
print(f" - 总记录数: {len(result_df)}")
|
||||
print(f" - 唯一学生数: {result_df['学号'].nunique()}")
|
||||
print(f" - 总金额: {result_df['支付金额(元)'].sum():.2f} 元")
|
||||
print(f"\n📋 Excel包含以下工作表:")
|
||||
print(f" 1. 详细记录 - 所有消费明细")
|
||||
print(f" 2. 按年级汇总 - 各年级消费统计")
|
||||
print(f" 3. 按班级汇总 - 各班级消费统计")
|
||||
print(f" 4. 按学生汇总 - 各学生消费统计")
|
||||
|
||||
# 显示年级分布
|
||||
print(f"\n🏫 年级分布:")
|
||||
grade_dist = result_df.groupby('年级名称')['学号'].nunique().sort_values(ascending=False)
|
||||
for grade, count in grade_dist.items():
|
||||
print(f" {grade}: {count} 人")
|
||||
@@ -0,0 +1,309 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "318e7588",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
" "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "3c046d8d",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"'{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}'"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "27c18f0a",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"id": "343a9e44",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"grade_id = [110,120,124, 126,127,128, 114,119,129]\n",
|
||||
"sql = f'''\n",
|
||||
"select \n",
|
||||
" mm.id,\n",
|
||||
" mm.stu_no,\n",
|
||||
" mm.stu_name,\n",
|
||||
" bb.student_id,\n",
|
||||
" mm.plan_id -- 这里直接显示 plan_id\n",
|
||||
"from (\n",
|
||||
" select \n",
|
||||
" s.id,\n",
|
||||
" s.stu_no,\n",
|
||||
" s.stu_name,\n",
|
||||
" a.plan_id -- 子查询把 plan_id 带出来\n",
|
||||
" from student s \n",
|
||||
" inner join class_attend_stu a on s.id = a.student_id\n",
|
||||
" where s.grade_id in ({\",\".join(map(str,grade_id))}) \n",
|
||||
" and a.plan_id=41\n",
|
||||
" group by s.id, s.stu_no, s.stu_name, a.plan_id\n",
|
||||
") mm \n",
|
||||
"left join (\n",
|
||||
" select DISTINCT c.student_id \n",
|
||||
" from class_attend c \n",
|
||||
" where c.attend_date BETWEEN '2026-05-25' and '2026-05-31' \n",
|
||||
" and c.student_id in (\n",
|
||||
" select DISTINCT a.student_id \n",
|
||||
" from class_attend_stu a \n",
|
||||
" where a.plan_id=41\n",
|
||||
" )\n",
|
||||
") bb on mm.id = bb.student_id \n",
|
||||
"WHERE bb.student_id is null\n",
|
||||
"'''\n",
|
||||
"cursor.execute(sql)\n",
|
||||
"result = cursor.fetchall()\n",
|
||||
"data = create_table(cursor,result)\n",
|
||||
"print(data)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"id": "2584e86a",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n",
|
||||
"{\"success\":true,\"msg\":\"操作成功\",\"code\":0,\"data\":null}\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"for item in data:\n",
|
||||
" res = post(f\"{ip}/classAttendStu/createThisWeekStu\",headers=header,params={\"stuId\":item[\"id\"],\"planId\":item[\"plan_id\"]},timeout=600).text\n",
|
||||
" print(res)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"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
|
||||
}
|
||||
Reference in New Issue
Block a user