当前位置: 首页 > news >正文

香港理工大学实验室定时预约

香港理工大学实验室定时预约

文章目录

  • 香港理工大学实验室定时预约
  • 简介
  • 接单价格
  • 软件界面
  • 网站预约界面
  • 代码

对爬虫、逆向感兴趣的同学可以查看文章,一对一小班教学(系统理论和实战教程)、提供接单兼职渠道:https://blog.csdn.net/weixin_35770067/article/details/142514698

简介

香港理工大学实验室预约项目,由于平时预约人数较多,因此定制定时预约软件,学校网页非常简单,一个简单的post请求直接搞定。

接单价格

有第三方抽佣,个人到手660,供大家参考

软件界面

在这里插入图片描述

网站预约界面

在这里插入图片描述

代码

# -*- coding: utf-8 -*-
'''
@Time    : 2025-06-23 16:24
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple bs4
'''
import time
import warnings
from bs4 import BeautifulSoup
import requests
import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext
import threading
from datetime import datetime, timedelta
import ctypes
import sys
warnings.filterwarnings('ignore')
def hide_console():"""隐藏控制台窗口"""if sys.platform.startswith('win'):handle = ctypes.windll.kernel32.GetConsoleWindow()ctypes.windll.user32.ShowWindow(handle, 0)hide_console()def create_order(instrument, cookies, auth_token, reservation_details):"""Sends a POST request to create a reservation for the selected instrument."""# Dynamically set the URL and Referer based on the instrument choiceif instrument == "fNIRS1":target_url = "https://urfms.polyu.edu.hk/facilities/ubsn/instruments/NIRSport_2_1/single_reservations"referer_url = "https://urfms.polyu.edu.hk/facilities/ubsn/instruments/NIRSport_2_1/single_reservations/new"else:  # Default to fNIRS2target_url = "https://urfms.polyu.edu.hk/facilities/ubsn/instruments/NIRSport_2_2/single_reservations"referer_url = "https://urfms.polyu.edu.hk/facilities/ubsn/instruments/NIRSport_2_2/single_reservations/new"headers = {'Host': 'urfms.polyu.edu.hk','Cache-Control': 'max-age=0','Origin': 'https://urfms.polyu.edu.hk','Content-Type': 'application/x-www-form-urlencoded','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36','Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7','Sec-Fetch-Site': 'same-origin','Sec-Fetch-Mode': 'navigate','Referer': referer_url,  # Use the dynamic Referer'Cookie': cookies}data = {'authenticity_token': auth_token,'order_account': '2204','send_notification': '1','commit': 'Create',}data.update(reservation_details)try:res = requests.post(target_url, headers=headers, data=data, verify=False, timeout=5)  # Use the dynamic URLres.raise_for_status()return res.textexcept requests.exceptions.RequestException:return ""class ReservationApp:def __init__(self, root):self.root = root# --- Variables ---self.instrument_var = tk.StringVar(value="fNIRS2")  # Default selectionself.start_date_var = tk.StringVar(value="13 Jul 2025")self.start_hour_var = tk.StringVar(value="9")self.start_min_var = tk.StringVar(value="00")self.start_meridian_var = tk.StringVar(value="AM")self.end_date_var = tk.StringVar(value="13 Jul 2025")self.end_hour_var = tk.StringVar(value="10")self.end_min_var = tk.StringVar(value="00")self.end_meridian_var = tk.StringVar(value="AM")self.duration_display_var = tk.StringVar(value="1:00")self.cookie_var = tk.StringVar()self.auth_token_var = tk.StringVar()self.schedule_time_var = tk.StringVar(value=f"{(datetime.now() + timedelta(minutes=1)).strftime('%H:%M:%S')}")self.status_var = tk.StringVar(value="Status: Idle")self._update_title()  # Set initial titleself.root.geometry("850x420")  # Adjusted height for the new frameself.create_widgets()self.create_log_window()def _update_title(self):"""Updates the main window title based on the instrument selection."""selected_instrument = self.instrument_var.get()self.root.title(f"Reservation Scheduler {selected_instrument}")def create_log_window(self):self.log_window = tk.Toplevel(self.root)self.log_window.title("Live HTML Log")self.log_window.geometry("800x600")self.log_text = scrolledtext.ScrolledText(self.log_window, wrap=tk.WORD, state=tk.DISABLED)self.log_text.pack(expand=True, fill='both')self.log_window.protocol("WM_DELETE_WINDOW", self.log_window.withdraw)self.log_window.withdraw()def update_status(self, message):self.status_var.set(message)def log_to_gui(self, message):self.log_text.config(state=tk.NORMAL)self.log_text.insert(tk.END, message)self.log_text.see(tk.END)self.log_text.config(state=tk.DISABLED)def schedule_reservation(self):# Get all required values from GUIinstrument = self.instrument_var.get()cookies = self.cookie_var.get()auth_token = self.auth_token_var.get()schedule_time_str = self.schedule_time_var.get()if not cookies or not auth_token:messagebox.showerror("Invalid Input", "Cookie and Authenticity Token fields cannot be empty.")returntry:target_time = datetime.strptime(schedule_time_str, '%H:%M:%S').time()schedule_dt = datetime.combine(datetime.now().date(), target_time)if schedule_dt < datetime.now(): schedule_dt += timedelta(days=1)start_dt = schedule_dt - timedelta(seconds=5)delay = (start_dt - datetime.now()).total_seconds()if delay < 0:messagebox.showerror("Invalid Time", "Scheduled time is in the past.")returnexcept ValueError:messagebox.showerror("Invalid Format", "Schedule time must be in HH:MM:SS format.")returntry:duration_str = self.duration_display_var.get()h, m = map(int, duration_str.split(':')) if ':' in duration_str else (0, int(duration_str))total_minutes = h * 60 + mexcept ValueError:messagebox.showerror("Invalid Input", "Duration format is incorrect.")returnreservation_details = {'reservation[reserve_start_date]': self.start_date_var.get(),'reservation[reserve_start_hour]': self.start_hour_var.get(),'reservation[reserve_start_min]': self.start_min_var.get(),'reservation[reserve_start_meridian]': self.start_meridian_var.get(),'reservation[reserve_end_date]': self.end_date_var.get(),'reservation[reserve_end_hour]': self.end_hour_var.get(),'reservation[reserve_end_min]': self.end_min_var.get(),'reservation[reserve_end_meridian]': self.end_meridian_var.get(),'reservation[duration_mins]_display': self.duration_display_var.get(),'reservation[duration_mins]': str(total_minutes),}self.schedule_button.config(state=tk.DISABLED)self.update_status(f"Status: Scheduled for {schedule_dt.strftime('%Y-%m-%d %H:%M:%S')}. Waiting...")task_thread = threading.Thread(target=self._execute_task,args=(delay, instrument, cookies, auth_token, reservation_details), daemon=True)task_thread.start()def _execute_task(self, delay, instrument, cookies, auth_token, reservation_details):time.sleep(delay)self.root.after(0, self.update_status, f"Status: Executing for {instrument}... Check log.")self.root.after(0, self.log_window.deiconify)self.root.after(0, lambda: self.log_to_gui(f"--- Starting Reservation Attempts for {instrument} ---\n"))start_time = time.time()success = Falsewhile time.time() - start_time < 60:response_html = create_order(instrument, cookies, auth_token, reservation_details)timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')log_entry = f"\n{'=' * 80}\nATTEMPT TIMESTAMP: {timestamp}\n{'=' * 80}\n"if response_html:soup = BeautifulSoup(response_html, 'html.parser')log_entry += soup.prettify()if not soup.find('div', class_='errorExplanation222222'):self.root.after(0, self.update_status, "Status: Success! Reservation created.")self.root.after(0, lambda: messagebox.showinfo("Success", "Reservation created successfully!"))self.root.after(0, lambda: self.log_to_gui("\n\n--- RESERVATION SUCCESSFUL ---"))success = Trueelse:log_entry += "--- [INFO] No response from server or network error ---"self.root.after(0, self.log_to_gui, log_entry)if success: breaktime.sleep(0.2)if not success:self.root.after(0, self.update_status, "Status: Finished. 60-second window passed.")self.root.after(0, lambda: self.log_to_gui("\n\n--- 60-SECOND EXECUTION WINDOW FINISHED ---"))self.root.after(0, lambda: self.schedule_button.config(state=tk.NORMAL))def create_widgets(self):main_frame = ttk.Frame(self.root, padding="10")main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))# --- Instrument Selection Frame ---inst_frame = ttk.LabelFrame(main_frame, text="Select Instrument", padding=(10, 5))inst_frame.grid(row=0, column=0, columnspan=7, sticky=(tk.W, tk.E), pady=(0, 10))ttk.Radiobutton(inst_frame, text="fNIRS1", variable=self.instrument_var, value="fNIRS1",command=self._update_title).pack(side=tk.LEFT, padx=5)ttk.Radiobutton(inst_frame, text="fNIRS2", variable=self.instrument_var, value="fNIRS2",command=self._update_title).pack(side=tk.LEFT, padx=5)# --- Main content frame ---content_frame = ttk.Frame(main_frame)content_frame.grid(row=1, column=0, columnspan=7)ttk.Label(content_frame, text="Start Time", font=('Helvetica', 10, 'bold')).grid(row=0, column=0, sticky=tk.W,pady=2)ttk.Entry(content_frame, textvariable=self.start_date_var, width=15).grid(row=0, column=1)ttk.Combobox(content_frame, textvariable=self.start_hour_var, values=list(range(1, 13)), width=4).grid(row=0,column=2,padx=5)ttk.Combobox(content_frame, textvariable=self.start_min_var, values=[f"{i:02d}" for i in range(0, 60, 15)],width=4).grid(row=0, column=3)ttk.Combobox(content_frame, textvariable=self.start_meridian_var, values=["AM", "PM"], width=4).grid(row=0,column=4,padx=5)ttk.Label(content_frame, text="End Time", font=('Helvetica', 10, 'bold')).grid(row=1, column=0, sticky=tk.W,pady=2)ttk.Entry(content_frame, textvariable=self.end_date_var, width=15).grid(row=1, column=1)ttk.Combobox(content_frame, textvariable=self.end_hour_var, values=list(range(1, 13)), width=4).grid(row=1,column=2,padx=5)ttk.Combobox(content_frame, textvariable=self.end_min_var, values=[f"{i:02d}" for i in range(0, 60, 15)],width=4).grid(row=1, column=3)ttk.Combobox(content_frame, textvariable=self.end_meridian_var, values=["AM", "PM"], width=4).grid(row=1,column=4,padx=5)ttk.Label(content_frame, text="Duration", font=('Helvetica', 10, 'bold')).grid(row=0, column=5, padx=(20, 0),sticky=tk.S)ttk.Entry(content_frame, textvariable=self.duration_display_var, width=12).grid(row=0, column=6, padx=5,sticky=tk.S)ttk.Label(content_frame, text='Enter "total minutes" or "hours:minutes"').grid(row=1, column=5, columnspan=2,padx=(20, 0), sticky=tk.N,pady=(0, 10))ttk.Label(content_frame, text="Cookie", font=('Helvetica', 10, 'bold')).grid(row=2, column=0, sticky=tk.W,pady=5)ttk.Entry(content_frame, textvariable=self.cookie_var, width=90).grid(row=2, column=1, columnspan=6,sticky=tk.W, padx=5)ttk.Label(content_frame, text="Authenticity Token", font=('Helvetica', 10, 'bold')).grid(row=3, column=0,sticky=tk.W, pady=5)ttk.Entry(content_frame, textvariable=self.auth_token_var, width=90).grid(row=3, column=1, columnspan=6,sticky=tk.W, padx=5)ttk.Label(content_frame, text="Schedule Time (HH:MM:SS)", font=('Helvetica', 10, 'bold')).grid(row=4, column=0,sticky=tk.W,pady=10)ttk.Entry(content_frame, textvariable=self.schedule_time_var, width=15).grid(row=4, column=1, sticky=tk.W)self.schedule_button = ttk.Button(content_frame, text="Schedule Reservation", command=self.schedule_reservation)self.schedule_button.grid(row=5, column=5, columnspan=2, sticky=tk.E, pady=10)status_bar = ttk.Label(self.root, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)status_bar.grid(row=1, column=0, sticky=(tk.W, tk.E))if __name__ == '__main__':root = tk.Tk()app = ReservationApp(root)root.mainloop()sticky=tk.E, pady=10)status_bar = ttk.Label(self.root, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)status_bar.grid(row=1, column=0, sticky=(tk.W, tk.E))if __name__ == '__main__':root = tk.Tk()app = ReservationApp(root)root.mainloop()
http://www.lryc.cn/news/586797.html

相关文章:

  • 前端框架状态管理对比:Redux、MobX、Vuex 等的优劣与选择
  • 关于 java:11. 项目结构、Maven、Gradle 构建系统
  • 用 Node.js 构建模块化的 CLI 脚手架工具,从 GitHub 下载远程模板
  • Python 学习之路(十)--常见算法实现原理及解析
  • LabVIEW调用外部DLL
  • [CH582M入门第六步]软件IIC驱动AHT10
  • 【数据结构】图 ,拓扑排序 未完
  • Docker(02) Docker-Compose、Dockerfile镜像构建、Portainer
  • 快速生成 Android 的 Splash 的 9 Patch 图片
  • Docker 搭建本地Harbor私有镜像仓库
  • SpringBoot单元测试类拿不到bean报空指针异常
  • 从架构到代码:飞算JavaAI电商订单管理系统技术解构
  • 决策树的相关理论学习
  • FusionOne HCI 23 超融合实施手册(超聚变超融合)
  • 【C++】多线程同步三剑客介绍
  • 代码随想录算法训练营第十七天
  • 【C++】第十五节—一文详解 | 继承
  • JVM 垃圾收集算法全面解析
  • DC-DC变换器最基本拓扑 -Buck电路和Boost电路
  • ROS2---NodeOptions
  • MacOS使用Multipass快速搭建轻量级k3s集群
  • mac上BRPC的CMakeLists.txt优化:解决Protobuf路径问题
  • TensorFlow深度学习实战(24)——变分自编码器详解与实现
  • Vue 3 动态ref问题
  • 封装---统一封装处理页面标题
  • C++模版编程:类模版与继承
  • Qt 3D模块加载复杂模型
  • vue应用如何实现在 A 标签页登出,希望 B 标签页也自动感知并退出登录
  • 语音识别的速度革命:从 Whisper 到 Whisper-CTranslate2,我经历了什么?
  • 数据库3.0