浅尝Selenium自动化框架

浅尝Selenium自动化框架

  • Selenium基本介绍
  • Selenium原理
  • Selenium学习要点
  • 写个Selenium Demo
  • 结束

Selenium基本介绍

Selenium 是一个开源的自动化测试工具,只用于测试 Web 应用程序。它支持多种编程语言(如 Java、Python、C# 等)来编写测试脚本,同时兼容主流的浏览器(如 Chrome、Firefox、Edge 等)。
👉👉👉官网 官方文档
直白点一句话总结:Selenium用来做桌面端(win/mac)上的浏览器web自动化。

Selenium原理

+-------------------------------------+
|          Test Script (Client)       |
|     (Python, Java, C#, etc.)        |
+-------------------+-----------------+|WebDriver API (JSON Wire Protocol)|
+-------------------+-----------------+
|          Browser Drivers            |
| (ChromeDriver, GeckoDriver, etc.)   |
+-------------------+-----------------+|Browsers(Chrome, Firefox, Edge, etc.)
  • Test Script
    用户通过编程语言调用 WebDriver API 来编写测试用例。
  • WebDriver API
    提供了浏览器操作的方法(如 .click(), .get())。
    WebDriver 使用 JSON Wire Protocol 与浏览器驱动通信,将测试用例中的操作翻译成浏览器能够理解的命令。
  • Browser Drivers
    浏览器驱动(中间层),将 API 的调用翻译为浏览器可理解的指令。
    不同浏览器需要不同的驱动程序(如 ChromeDriver、GeckoDriver 等)。
    驱动程序将 WebDriver 发出的命令传递给浏览器。
  • Browsers 浏览器
    浏览器根据驱动程序的指令执行实际的操作(如打开页面、点击按钮等),并返回执行结果。

Selenium学习要点

我是基于python学习的,步骤非常简单。

pip install selenium

然后要学一下XPath这种XML查询语言,就可以开始写代码啦。

写个Selenium Demo

最近蛀牙了,做根管治疗,要经常定期挂号,但是那医生又有点人气,放号又是随机时间,经常约不到号,就很尴尬。所以就想做一个自动通知挂号的脚本。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
import random
from typing import Optional, List
from datetime import datetimedef find_doctor_and_nextpage(driver, doctor_name, hospital_name, department_name):page_index = 0while True:page_index += 1doctors = driver.find_elements(By.XPATH, '//*[@id="expert_div_1"]/div[*]/div[1]/div[2]')for doctor in doctors:text = doctor.textif doctor_name in text and hospital_name in text and department_name in text:try:# 在当前医生元素中查找链接link_element = doctor.find_element(By.XPATH, './ul/li[1]/span[1]/a')  # 相对 XPathhref = link_element.get_attribute("href")  # 获取链接的 href 属性print(f"Found the link to the doctor at page {page_index}. href={href}")return hrefexcept Exception as e:print(f"Do not find the doctor link, doctor.text={text}. {e}")# 搜索下一页try:switch_page_bar = driver.find_element(By.XPATH, '//*[@id="page1"]')next_page_btn = switch_page_bar.find_element(By.XPATH, './/*[contains(text(), "下一页")]')href = next_page_btn.get_attribute('href')if href:print(f"Page {page_index} has been searched completely with no matches found, proceeding to the next page.")time.sleep(random.randint(2, 5))next_page_btn.click()else:print(f"The search has reached the last page {page_index} and no matches found.")return Falseexcept Exception as e:print(f"find_doctor_and_nextpage Error. {e}")return Falsedef search_doctor(driver, base_url, doctor_name, hospital_name, department_name):try:# 打开搜索页面(基网址传入)driver.get(base_url)# 定位搜索框并输入医生doctor_input = driver.find_element(By.XPATH, "//*[@id='txtSearch']")doctor_input.clear()doctor_input.send_keys(doctor_name)# 点击搜索按钮search_button = driver.find_element(By.XPATH, "/html/body/div[3]/div/div[3]/div/input[3]")search_button.click()try:# 等待跳转到结果页面WebDriverWait(driver, 5).until(EC.presence_of_all_elements_located((By.XPATH, "//*[@id='expert_div_1']/div[1]")))except Exception as e:print(f"Search the doctor timeout, name={doctor_name}. {e}")return Falsedoctor_link = find_doctor_and_nextpage(driver, doctor_name, hospital_name, department_name)# print(f"doctor_link={doctor_link}")return doctor_linkexcept Exception as e:print(f":Search the doctor failed, name={doctor_name}. {e}")return Falsedef convert_to_datetime(date_str):try:return datetime.strptime(date_str, "%m-%d")except ValueError:return Nonedef parse_target_date(target_date) -> List[datetime]:"""解析入参 target_date,支持单个日期、多个日期和日期范围。'01-05''01-05, 01-07, 01-19''01-05~02-02'返回日期对象列表。"""if isinstance(target_date, str):if '~' in target_date:  # 日期范围start_date_str, end_date_str = target_date.split('~')start_date = convert_to_datetime(start_date_str)end_date = convert_to_datetime(end_date_str)return [start_date, end_date] if start_date and end_date else []elif ',' in target_date:  # 多个日期date_str_list = [date.strip() for date in target_date.split(',')]converted_dates = [convert_to_datetime(date_str) for date_str in date_str_list]return [date for date in converted_dates if date]else:  # 单个日期single_date = convert_to_datetime(target_date)return [single_date] if single_date else []return []def check_availability(driver, doctor_link, target_date, target_time: Optional[str]):"""在网页中检查是否有目标日期时间的号源"""can_be_appointments = Falsetry:driver.get(doctor_link)try:# 等待跳转到结果页面doctor_subscribe = WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.XPATH, '//*[@class="doctorsubscribe"]')))except Exception as e:print(f"Open link {doctor_link} timeout. {e}")return False# 匹配日期date_items = doctor_subscribe.find_elements(By.XPATH, './div[1]/ul/li/span[1]')parsed_dates = parse_target_date(target_date.strip())matched_indices = []if '~' in target_date:  # 日期范围if len(parsed_dates) == 2 and isinstance(parsed_dates[0], datetime) and isinstance(parsed_dates[1],datetime):  # 日期范围start_date, end_date = parsed_datesfor idx, item in enumerate(date_items):item_date = convert_to_datetime(item.text)if item_date and start_date <= item_date <= end_date:matched_indices.append(idx)elif len(parsed_dates) > 1:  # 多个日期for idx, item in enumerate(date_items):item_date = convert_to_datetime(item.text)if item_date and item.text in [date.strftime("%m-%d") for date in parsed_dates]:matched_indices.append(idx)elif len(parsed_dates) == 1:  # 单个日期for idx, item in enumerate(date_items):item_date = convert_to_datetime(item.text)if item_date and item.text == parsed_dates[0].strftime("%m-%d"):matched_indices.append(idx)if len(matched_indices) > 0:print(f"Found the matched date index {matched_indices}")else:print(f"No matched date can be found.")return Falsewhliesubscribe = doctor_subscribe.find_elements(By.XPATH, './div[2]/ul/li')for index in matched_indices:if index < len(whliesubscribe):element = whliesubscribe[index]if "预约" in element.text:can_be_appointments = Trueprint(f"There are available slots on  {date_items[index].text}, and appointments can be made.")return True# 匹配时间print(f"can_be_appointments={can_be_appointments}")except Exception as e:print(f"check_availability Error. {e}")return Falsedef book_appointment(driver):"""执行挂号流程"""try:# 点击预约按钮book_button = driver.find_element(By.ID, "book_button")  # 替换为实际 IDbook_button.click()# 填写必要的预约信息patient_name = driver.find_element(By.ID, "patient_name_input")  # 替换为实际 IDpatient_phone = driver.find_element(By.ID, "patient_phone_input")  # 替换为实际 IDpatient_name.send_keys("测试患者")  # 替换为实际患者姓名patient_phone.send_keys("12345678901")  # 替换为实际联系电话# 确认预约confirm_button = driver.find_element(By.ID, "confirm_button")  # 替换为实际 IDconfirm_button.click()print("挂号成功!")except Exception as e:print(f"挂号出错: {e}")def main(base_url, doctor_name, hospital, department, target_date, target_time):"""主程序入口"""driver = webdriver.Chrome()  # 浏览器驱动try:# 步骤 1:搜索医生doctor_link = search_doctor(driver, base_url, doctor_name, hospital, department)if not doctor_link:print("Search doctor failed.")return# doctor_link = 'https://www.xxx.com/UrpOnline/Home/Doctor/2439FC00A213861E30C599CDDD0833B8'# 步骤 2:检查是否有目标日期的号源if check_availability(driver, doctor_link, target_date, target_time):print(f"找到 {target_date} 的号源,开始预约...")else:print(f"没有找到 {target_date} 的号源。")finally:# 关闭浏览器driver.quit()# 示例调用
if __name__ == "__main__":main(base_url="https://www.xxx.com/UrpOnline/Home/DoctorList/",doctor_name="医师",# doctor_name="张三",hospital="中山医院",department="皮肤科",# department="便民门诊2",# department="消化内科asdf午间门诊", # 第4页# target_date="01-05~01-06",target_date="01-05~02-01",target_time=None)

结束

有什么问题可以留言或者私信哦!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/65513.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络之---物理层设备

什么是物理层设备 物理层设备是指负责数据在物理媒介上传输的硬件设备&#xff0c;它们主要处理数据的转换、信号的传输与接收&#xff0c;而不涉及数据的内容或意义。常见的物理层设备包括网卡、集线器、光纤收发器、调制解调器等。 物理层设备有哪些 1、网卡&#xff08;N…

flink的EventTime和Watermark

时间机制 Flink中的时间机制主要用在判断是否触发时间窗口window的计算。 在Flink中有三种时间概念&#xff1a;ProcessTime、IngestionTime、EventTime。 ProcessTime&#xff1a;是在数据抵达算子产生的时间&#xff08;Flink默认使用ProcessTime&#xff09; IngestionT…

Ubuntu 下测试 NVME SSD 的读写速度

在 Ubuntu 系统下&#xff0c;测试 NVME SSD 的读写速度&#xff0c;有好多种方法&#xff0c;常用的有如下几种&#xff1a; 1. Gnome-disks Gnome-disks&#xff08;也称为“Disks”&#xff09;是 GNOME 桌面环境中的磁盘管理工具&#xff0c;有图形界面&#xff0c;是测试…

SpringBoot之核心配置

学习目标&#xff1a; 1.熟悉Spring Boot全局配置文件的使用 2.掌握Spring Boot配置文件属性值注入 3.熟悉Spring Boot自定义配置 4.掌握Profile多环境配置 5.了解随机值设置以及参数间引用 1.全局配置文件 Spring Boot使用 application.properties 或者application.yaml 的文…

后端服务集成ElasticSearch搜索功能技术方案

文章目录 一、为什么选用ElasticSearch二、ElasticSearch基本概念1、文档和字段2、索引和映射3、倒排索引、文档和词条4、分词器 三、ElasticSearch工作原理1、Term Dictionary、Term index2、Stored Fields3、Docs Values4、Segment5、Lucene6、高性能、高扩展性、高可用①高性…

【JavaEE进阶】获取Cookie/Session

&#x1f340;Cookie简介 HTTP协议自身是属于 "⽆状态"协议. "⽆状态"的含义指的是: 默认情况下 HTTP 协议的客⼾端和服务器之间的这次通信,和下次通信之间没有直接的联系.但是实际开发中,我们很多时候是需要知道请求之间的关联关系的. 例如登陆⽹站成…

《Spring Framework实战》3:概览

欢迎观看《Spring Framework实战》视频教程 Spring Framework 为基于现代 Java 的企业应用程序提供了全面的编程和配置模型 - 在任何类型的部署平台上。 Spring 的一个关键要素是应用程序级别的基础设施支持&#xff1a;Spring 专注于企业应用程序的 “管道”&#xff0c;以便…

借助免费GIS工具箱轻松实现las点云格式到3dtiles格式的转换

在当今数字化浪潮下&#xff0c;地理信息系统&#xff08;GIS&#xff09;技术日新月异&#xff0c;广泛渗透到城市规划、地质勘探、文化遗产保护等诸多领域。而 GISBox 作为一款功能强大且易用的 GIS 工具箱&#xff0c;以轻量级、免费使用、操作便捷等诸多优势&#xff0c;为…

高等数学学习笔记 ☞ 一元函数微分的基础知识

1. 微分的定义 &#xff08;1&#xff09;定义&#xff1a;设函数在点的某领域内有定义&#xff0c;取附近的点&#xff0c;对应的函数值分别为和&#xff0c; 令&#xff0c;若可以表示成&#xff0c;则称函数在点是可微的。 【 若函数在点是可微的&#xff0c;则可以表达为】…

linux之自动挂载

如果想要实现自动挂载&#xff0c;应该挂在客户端&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 客户端&#xff1a; [rootlocalhost ~]# yum install nfs-utils -y &#xff08;下载软件&#xff09; [rootlocalhost ~]# systemctl start nfs-utils.servic…

用户界面软件01

Jens Coldewey 著&#xff0c;Tom.X 译 本文中的模式语言逐步深入地探讨用户界面架构的设计&#xff0c;它基于人机工程学&#xff0c;足以形成一套完整的体系。如果你对这方面有兴趣&#xff0c;请参考[Tog92]&#xff0c;[Coo95]和[Col95]。 本文不讨论用户界面的布局&…

2025.1.8(c++对c语言的扩充——堆区空间,引用,函数)

笔记 上一笔记接续&#xff08;练习2的答案&#xff09; 练习&#xff1a;要求在堆区连续申请5个int的大小空间用于存储5名学生的成绩&#xff0c;分别完成空间的申请、成绩的录入、升序排序、成绩输出函数以及空间释放函数&#xff0c;并在主程序中完成测试 要求使用new和d…

(长期更新)《零基础入门 ArcGIS(ArcScene) 》实验七----城市三维建模与分析(超超超详细!!!)

城市三维建模与分析 三维城市模型已经成为一种非常普遍的地理空间数据资源,成为城市的必需品,对城市能化管理至关重要。语义信息丰富的三维城市模型可以有效实现不同领域数据与IS相信息的高层次集成及互操作,从而在城市规划、环境模拟、应急响应和辅助决策等众多领域公挥作用、…

Harmony开发【笔记1】报错解决(字段名写错了。。)

在利用axios从网络接收请求时&#xff0c;发现返回obj的code为“-1”&#xff0c;非常不解&#xff0c;利用console.log测试&#xff0c;更加不解&#xff0c;可知抛出错误是 “ E 其他错误: userName required”。但是我在测试时&#xff0c;它并没有体现为空&#xff0c;…

(2023|NIPS,LLaVA-Med,生物医学 VLM,GPT-4 生成自指导指令跟随数据集,数据对齐,指令调优)

LLaVA-Med: Training a Large Language-and-Vision Assistant for Biomedicine in One Day 目录 LLaVA-Med: Training a Large Language-and-Vision Assistant for Biomedicine in One Day 0. 摘要 1. 简介 2. 相关工作 3. 生物医学视觉指令数据 4. 将多模态对话模型适配…

(概率论)无偏估计

参考文章&#xff1a;(15 封私信 / 51 条消息) 什么是无偏估计&#xff1f; - 知乎 (zhihu.com) 首先&#xff0c;第一个回答中&#xff0c;马同学图解数学讲解得很形象&#xff0c; 我的概括是&#xff1a;“注意&#xff0c;有一个总体的均值u。然后&#xff0c;如果抽样n个&…

国产游戏崛起,燕云十六移动端1.9上线,ToDesk云电脑先开玩

游戏爱好者的利好消息出新了&#xff01;网易大型武侠仙游《燕云十六声》正式官宣&#xff0c;移动端要在1月9日正式上线了&#xff01;你期待手游版的燕云吗&#xff1f;不妨评论区留言说说你的看法。小编分别花了几个小时在台式机电脑和手机上都试了下&#xff0c;欣赏画面还…

VS2022引入sqlite数据库交互

法一&#xff1a;用官网编译好的动态库(推荐) 下载所需文件 sqlite官网地址&#xff1a;https://www.sqlite.org/howtocompile.html 下载以下的2个压缩包 第一个压缩包 sqlite-amalgamation-xxxx.zip&#xff0c;xxxx是版本号,保持一致即可&#xff0c;这里面有sqite3.h 第…

Java后端常用的4种请求方式(通俗易懂)

文章目录 前言通用接口类(ControllerDemo)通用实体类(UserEntity)通用响应类(HttpClientResult)成功截图(先启动项目,然后右键执行main方法) HttpClientHttpClient 的主要类代码案例导入依赖工具类(HttpClientUtil)测试类 HttpURLConnection简介调用步骤代码案例导入依赖工具类…

STM32烧写失败之Contents mismatch at: 0800005CH (Flash=FFH Required=29H) !

一&#xff09;问题&#xff1a;用ULINK2给STM32F103C8T6下载程序&#xff0c;下载方式设置如下&#xff1a; 出现下面两个问题&#xff1a; 1&#xff09;下载问题界面如下&#xff1a; 这个错误的信息大概可以理解为&#xff0c;在0x08000063地址上读取到flash存储为FF&am…