具体流程: 使用Selenium库来运行浏览器,打开网页,登录账号,自动填表及点击预约。 使用time,datetime库定时预约。使用库win32con,ctypes 加入快捷键启动。 使用库threading多单线程加快运行速度。使用库linecache读取txt中填表信息。
效果: 开发出网页自动预约程序,能够无人值守预约实验设备,并且预约速度远超手动预约,将预约流程的30-60s秒缩短为1~2s。
import datetime # 引入时间日期库
# import os
import time # 引入时间操作库
# import pyautogui
# import win32gui # findwindows
from selenium import webdriver # 引入selenium库
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException, TimeoutException, ElementNotInteractableException, \
ElementClickInterceptedException # 引入没有找到元素,和时间出错防止报错库
# import win32com.client # 大漠模块
import win32con # 引入全局快捷键
import ctypes
import ctypes.wintypes
import threading # 多线程模块
import linecache
# pyinstaller --ico=headbig.ico -F rush7.2测试.py
# import pywin32
# sample = "掺杂氟的SnO2导电玻璃钙钛矿薄膜"
# file_path = r"F:\python_project\自动化\abc.txt"
file_path = "rush_setting.txt"
# line_number = 2
def get_line_context(A, B):
return linecache.getline(A, B).strip()
print("by ZBC")
account = get_line_context(file_path, 2)
print("账号:" + account)
password = get_line_context(file_path, 4)
sample = get_line_context(file_path, 6)
print("样品数量:" + sample)
consist = get_line_context(file_path, 8)
print("样品成分:" + consist)
request = get_line_context(file_path, 10)
print("工艺要求:" + request)
name = get_line_context(file_path, 12)
print("签名:" + name)
select_chose = get_line_context(file_path, 14)
if select_chose == "yes":
select_time_1 = get_line_context(file_path, 15)
select_time_2 = get_line_context(file_path, 16)
print("选择时间1:" + select_time_1)
print("选择时间2:" + select_time_2)
else:
select_time_1 = get_line_context(file_path, 15)
print("选择时间1:" + select_time_1)
def is_element_exist_by_xpath(xpa): # 定义寻找元素函数
try:
driver.find_element_by_xpath(xpa)
# print("找到了")
return True # 找到就返回真
except NoSuchElementException as err0: # 用NoSuchElementException来防止运行报错,as加入错误原因
# print("找不到2", err0)
# print("\r正在寻找元素,请等待", end="")
return False # 找不到返回失败
def is_element_inter_by_xpath_send_keys(xpa, word): # 发送字符
try:
driver.find_element_by_xpath(xpa).send_keys(word)
# print("可以交互的")
return True # 找到就返回真
except ElementNotInteractableException:
# print("不可交互")
return False # 找不到返回失败
def is_element_inter_by_xpath_find(xpa): # 无法操作
try:
driver.find_element_by_xpath(xpa).click()
# print("可以交互的")
return True
except ElementNotInteractableException:
# print("不可交互")
return False
def is_element_inter_by_xpath_click(xpa): # 点击
try:
driver.find_element_by_xpath(xpa).click()
# print("可以交互的")
return True # 找到就返回真
except ElementClickInterceptedException:
# print("不可交互")
return False # 找不到返回失败
def set_time(h=1, m=0): # 定义定时函数
j = 0
while True:
now = datetime.datetime.now()
j = j + 1
# print(i)
n = j % 7
# print(n)
print("\r目前时间:" + str(now.hour) + ":" + str(now.minute) + " 设定时间:" + str(h) + ":" + str(m) + " 未到运行时间,请等待" + n * "·", end="")
if now.hour == h and now.minute == m:
break
time.sleep(1) # 每隔1秒检测一次
def refresh_wait(): # 定义刷新函数
try:
driver.refresh()
# print("\r刷新中...")
return True
except TimeoutException as e:
print("刷新失效", e)
return False
# finally:
# driver.refresh()
# FindWindow(lpClassName=None, lpWindowName=None) 窗口类名 窗口标题名
# dm = win32com.client.Dispatch('dm.dmsoft') # 调用大漠插件
# print(dm.ver()) # 输出版本号,成功输出代表安装了大漠插件
# # set_time(8, 55) # 设定启动时间
chrome_driver_path = r"D:\chromedriver.exe"
options = webdriver.ChromeOptions()
options.add_experimental_option("prefs", {"profile.managed_default_content_settings.images": 2}) # 不加载图片,加快访问速度
options.add_experimental_option('excludeSwitches', ['enable-automation']) # 此步骤很重要,设置为开发者模式,防止被各大网站识别出来使用了Selenium
driver = webdriver.Chrome(executable_path=chrome_driver_path, options=options)
# driver = webdriver.Chrome(r"D:\chromedriver.exe") # 启动chrome浏览器
driver.maximize_window() # 窗口最大化
driver.wait = WebDriverWait(driver, 10) # 超时时长为10s
driver.get("http://clxysy.szu.edu.cn/login") # 转到登录页面
driver.find_element_by_xpath("//input[@placeholder='请输入登陆账号']").send_keys(account) # 输入账号
driver.find_element_by_xpath("//input[@placeholder='输入您的密码']").send_keys(password) # 输入密码
driver.find_element_by_xpath("//button[@class='login-form-button ant-btn ant-btn-primary ant-btn-round']").click() # 点击预约按钮
time.sleep(1)
# driver.get("http://clxysy.szu.edu.cn/devicelist") # 转到预约页面
driver.get("http://clxysy.szu.edu.cn/mainstep?instrumentId=418&userId=3130") # 转到小电镜页面
RUN = False # 用来传递运行一次的参数
EXIT = False # 用来传递退出的参数
user32 = ctypes.windll.user32 # 加载user32.dll
id1 = 105 # 注册热键的唯一的id,用来区分热键
id2 = 106 # 注册热键的唯一的id,用来区分热键
class HotKey(threading.Thread):
def run(self):
global EXIT # 定义全局变量,这个可以在不同线程间共用。
global RUN # 定义全局变量,这个可以在不同纯种间共用。
# global i
i = 0
if not user32.RegisterHotKey(None, id1, 0, win32con.VK_F9): # 注册快捷键F9并判断是否成功,该热键用于执行一次需要执行的内容
print("Unable to register id", id1) # 返回一个错误信息
if not user32.RegisterHotKey(None, id2, 0, win32con.VK_F10): # 注册快捷键F10并判断是否成功,该热键用于结束,且最好这么结束,否则影响下一次注册热键
print("Unable to register id", id2)
# 以下为检测热键是否被按下,并在最后释放快捷键
try:
msg = ctypes.wintypes.MSG()
# print("按键检测")
while True:
if user32.GetMessageA(ctypes.byref(msg), None, 0, 0) != 0:
if msg.message == win32con.WM_HOTKEY:
if msg.wParam == id1:
RUN = True
elif msg.wParam == id2:
EXIT = True
while True:
if RUN:
# 这里放你要用热键启动执行的代码--------------------------------------------------------------------------------F9
print("F9已按下,执行自动填表")
xpa_research_group = "/html/body/app-root/div/app-nav/div/div[2]/div[2]/app-mainstep/nz-content/nz-layout/nz-layout/nz-content/div/nz-tabset/div[" \
"2]/div[2]/div[2]/div[2]/app-registration/nz-layout/nz-content/nz-content/form/div[1]/div[" \
"5]/nz-form-item/nz-form-control/div/span/nz-select/div/div/div "
group_select = driver.wait.until(EC.presence_of_element_located((By.XPATH, xpa_research_group)))
time.sleep(0.1)
group_select.click()
group_click = driver.wait.until(EC.presence_of_element_located((By.XPATH, '/html/body/div/div[4]/div/div/div/ul/li')))
group_click.click()
xpa_num_sample = "//input[@class='ant-input-number-input ng-untouched ng-pristine ng-valid']" # 样品数量xpa
num_sample = driver.wait.until(EC.presence_of_element_located((By.XPATH, xpa_num_sample)))
num_sample.send_keys(sample)
xpa_no_need = "//nz-row[@class='ant-row']//label[1]//span[1]//input[1]"
no_need = driver.wait.until(EC.presence_of_element_located((By.XPATH, xpa_no_need)))
no_need.click()
driver.find_element_by_xpath("//textarea[@name='sampledesc']").send_keys(consist) # 样品组成及描述
driver.find_element_by_xpath("//textarea[@name='requirements']").send_keys(request) # 样品要求
driver.find_element_by_xpath(
"//nz-tabset[@class='bottom_description ant-tabs ant-tabs-top ant-tabs-line ant-tabs-large']//div["
"@class='ant-row']//label[1]//span[1]//input[1]").click() # 样品自行取回
driver.find_element_by_xpath("//input[@placeholder='预约人签字']").send_keys(name) # 签名
# driver.find_element_by_xpath("//button[@class='ant-btn ant-btn-default ant-btn-round']").click() # 提交预约
print("预约成功")
RUN = False
break
elif EXIT: # 这里是用于退出循环的---------------------------------------------------------------------------------F10
print("F10已按下,开始自动刷新填表")
time_next_week = datetime.datetime.now() + datetime.timedelta(days=+7) # 加7天
print(time_next_week.strftime("%Y-%m-%d"))
time5 = time_next_week.strftime("%Y-%m-%d") # 使用简称
xpa_a = "//li[contains(text(),'" + time5 + "')]"
while True: # 不是最新日期就刷新,无限循环
# time_next_week = datetime.datetime.now() + datetime.timedelta(days=+7) # 加7天
# print(time_next_week.strftime("%Y-%m-%d"))
# time5 = time_next_week.strftime("%Y-%m-%d") # 使用简称
# xpa_a = "//li[contains(text(),'" + time5 + "')]"
while True:
if is_element_exist_by_xpath(
"/html/body/app-root/div/app-nav/div/div[2]/div[2]/app-mainstep/nz-content/nz-layout/nz-layout/nz-content/div/div/div[2]/nz-descriptions/div[2]/table/tbody/tr[6]/td/span[2]/nz-select/div/div/div"):
driver.find_element_by_xpath(
"/html/body/app-root/div/app-nav/div/div[2]/div[2]/app-mainstep/nz-content/nz-layout/nz-layout/nz-content/div/div/div[2]/nz-descriptions/div[2]/table/tbody/tr[6]/td/span[2]/nz-select/div/div/div").click() # 选择日期框
print("点击日期框成功")
break
else:
continue
if is_element_exist_by_xpath(xpa_a):
driver.find_element_by_xpath(xpa_a).click()
print("选择日期成功")
break # 打破循环
else:
i = i + 1
n = i % 7
print("\r正在刷新" + n * "·", end="")
refresh_wait() # 调用封装的刷新函数
time.sleep(0.2)
# --
while True:
if is_element_exist_by_xpath("//span[contains(text(),'9:00-9:30')]"):
if select_chose == "yes":
driver.find_element_by_xpath("//span[contains(text(),'" + select_time_1 + "')]").click() # 预约上午9:00-9:30
driver.find_element_by_xpath("//span[contains(text(),'" + select_time_2 + "')]").click() # 预约上午9:30-10:00
else:
driver.find_element_by_xpath("//span[contains(text(),'" + select_time_1 + "')]").click() # 预约上午9:00-9:30
# driver.find_element_by_xpath("//span[contains(text(),'10:00-10:30')]").click() # 预约上午10:00-10:30
# driver.find_element_by_xpath("//span[contains(text(),'10:30-11:00')]").click() # 预约上午10:30-11:00
# driver.find_element_by_xpath("//span[contains(text(),'11:00-11:30')]").click() # 预约上午11:00-11:30
# driver.find_element_by_xpath("//span[contains(text(),'11:30-12:00')]").click() # 预约上午11:30-12:00
# driver.find_element_by_xpath("//span[contains(text(),'14:00-14:30')]").click() # 预约上午14:00-14:30
# driver.find_element_by_xpath("//span[contains(text(),'14:30-15:00')]").click() # 预约上午14:30-15:00
# driver.find_element_by_xpath("//span[contains(text(),'15:00-15:30')]").click() # 预约上午15:00-15:30
# driver.find_element_by_xpath("//span[contains(text(),'15:30-16:00')]").click() # 预约上午15:30-16:00
# driver.find_element_by_xpath("//span[contains(text(),'16:00-16:30')]").click() # 预约上午16:00-16:30
# driver.find_element_by_xpath("//span[contains(text(),'16:30-17:00')]").click() # 预约上午16:30-17:00
# driver.find_element_by_xpath("//span[contains(text(),'17:00-17:30')]").click() # 预约上午17:00-17:30
# driver.find_element_by_xpath("//span[contains(text(),'18:30-19:00')]").click() # 预约上午18:30-19:00
# driver.find_element_by_xpath("//span[contains(text(),'19:00-19:30')]").click() # 预约上午19:00-19:30
# driver.find_element_by_xpath("//span[contains(text(),'19:30-20:00')]").click() # 预约上午19:30-20:00
# driver.find_element_by_xpath("//span[contains(text(),'20:00-20:30')]").click() # 预约上午20:00-20:30
break
else:
continue
# --
while True:
if is_element_exist_by_xpath("//button[@class='ant-btn ant-btn-primary ant-btn-round']"):
driver.find_element_by_xpath("//button[@class='ant-btn ant-btn-primary ant-btn-round']").click() # 提交预约
break
else:
continue
# --
xpa_research_group = "/html/body/app-root/div/app-nav/div/div[2]/div[2]/app-mainstep/nz-content/nz-layout/nz-layout/nz-content/div/nz-tabset/div[" \
"2]/div[2]/div[2]/div[2]/app-registration/nz-layout/nz-content/nz-content/form/div[1]/div[" \
"5]/nz-form-item/nz-form-control/div/span/nz-select/div/div/div "
group_select = driver.wait.until(EC.presence_of_element_located((By.XPATH, xpa_research_group)))
time.sleep(0.5)
group_select.click()
xpa_research_group1 = "/html/body/div/div[4]/div/div/div/ul/li"
group_click = driver.wait.until(EC.presence_of_element_located((By.XPATH, xpa_research_group1)))
time.sleep(0.5)
group_click.click()
xpa_num_sample = "//input[@class='ant-input-number-input ng-untouched ng-pristine ng-valid']" # 样品数量xpa
num_sample = driver.wait.until(EC.presence_of_element_located((By.XPATH, xpa_num_sample)))
num_sample.send_keys(sample)
xpa_no_need = "//nz-row[@class='ant-row']//label[1]//span[1]//input[1]"
no_need = driver.wait.until(EC.presence_of_element_located((By.XPATH, xpa_no_need)))
no_need.click()
driver.find_element_by_xpath("//textarea[@name='sampledesc']").send_keys(consist) # 样品组成及描述
driver.find_element_by_xpath("//textarea[@name='requirements']").send_keys(request) # 样品要求
driver.find_element_by_xpath(
"//nz-tabset[@class='bottom_description ant-tabs ant-tabs-top ant-tabs-line ant-tabs-large']//div["
"@class='ant-row']//label[1]//span[1]//input[1]").click() # 样品自行取回
driver.find_element_by_xpath("//input[@placeholder='预约人签字']").send_keys(name) # 签名
# driver.find_element_by_xpath("//button[@class='ant-btn ant-btn-default ant-btn-round']").click() # 提交预约
print("预约成功")
EXIT = False
break
user32.TranslateMessage(ctypes.byref(msg))
user32.DispatchMessageA(ctypes.byref(msg))
finally:
user32.UnregisterHotKey(None, id1) # 必须得释放热键,否则下次就会注册失败,所以当程序异堂退出,没有释放热键
# 那么下次很可能就没办法注册成功了,这时可以换一个热键测试
user32.UnregisterHotKey(None, id2)
hotkey = HotKey()
hotkey.run()
# driver.quit()