淺嘗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.pswp.cn/web/65513.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/65513.shtml
英文地址,請注明出處:http://en.pswp.cn/web/65513.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

計算機網絡之---物理層設備

什么是物理層設備 物理層設備是指負責數據在物理媒介上傳輸的硬件設備&#xff0c;它們主要處理數據的轉換、信號的傳輸與接收&#xff0c;而不涉及數據的內容或意義。常見的物理層設備包括網卡、集線器、光纖收發器、調制解調器等。 物理層設備有哪些 1、網卡&#xff08;N…

SQL中的數據庫對象

視圖&#xff1a;VIEW 概念 ① 虛擬表&#xff0c;本身不存儲數據&#xff0c;可以看做是存儲起來的SELECT語句 ② 視圖中SELECT語句中涉及到的表&#xff0c;稱為基表 ③ 針對視圖做DML操作&#xff0c;對影響到基表中的數據&#xff0c;反之亦然 ④ 創建、刪除視圖本身&#…

flink的EventTime和Watermark

時間機制 Flink中的時間機制主要用在判斷是否觸發時間窗口window的計算。 在Flink中有三種時間概念&#xff1a;ProcessTime、IngestionTime、EventTime。 ProcessTime&#xff1a;是在數據抵達算子產生的時間&#xff08;Flink默認使用ProcessTime&#xff09; IngestionT…

web服務器架構,websocket

1. 非前后端分離架構 1. 前端html后端servlet 被tomcat服務器打包&#xff0c;統一指定根目錄入口。通過原生表單發送到后端&#xff0c;后端根據請求數據進行重定向或請求轉發&#xff0c;這樣就不能進行動態渲染&#xff0c;也就必須存在很多靜態html對應每一個請求。 這里…

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、高性能、高擴展性、高可用①高性…

舉例說明AI模型怎么聚類,最后神經網絡怎么保存

舉例說明怎么聚類,最后神經網絡怎么保存 目錄 舉例說明怎么聚類,最后神經網絡怎么保存K - Means聚類算法實現神經元特征聚類劃分成不同專家的原理和過程 特征提取: 首先,需要從神經元中提取有代表性的特征。例如,對于一個多層感知機(MLP)中的神經元,其權重向量可以作為特…

ocrmypdf使用時的cannot import name ‘PdfMatrix‘ from ‘pikepdf‘問題

最近在做pdf的ocr,之前使用過ocrmypdf&#xff0c;打算再次使用&#xff0c;發現它更新了&#xff0c;所以就打算使用最新版 環境&#xff1a;win11anaconda 創建虛擬環境后安裝語句&#xff1a; pip install ocrmypdf -i https://pypi.tuna.tsinghua.edu.cn/simple pip in…

【JavaEE進階】獲取Cookie/Session

&#x1f340;Cookie簡介 HTTP協議自身是屬于 "?狀態"協議. "?狀態"的含義指的是: 默認情況下 HTTP 協議的客?端和服務器之間的這次通信,和下次通信之間沒有直接的聯系.但是實際開發中,我們很多時候是需要知道請求之間的關聯關系的. 例如登陸?站成…

Oracle:ORA-00904: “10“: 標識符無效報錯詳解

1.報錯Oracle語句如下 SELECT YK_CKGY.ID,YK_CKGY.DJH,YK_CKGY.BLRQ,YK_CKGY.ZBRQ,YK_CKGY.SHRQ,YK_CKGY.YT,YK_CKGY.ZDR,YK_CKGY.SHR,YK_CKGY.BZ,YK_CKGY.JZRQ,YK_CKGY.ZT,YK_CKGY.CKLX,(case YK_CKGY.CKLXwhen 09 then藥房調借when 02 then科室退藥when 03 then損耗出庫when…

Linux 磁盤管理命令:使用xfs 管理命令

文章目錄 Linux磁盤管理命令使用xfs 管理命令1.命令說明2&#xff0e;建立 XFS 文件系統4&#xff0e;調整 XFS 文件系統各項參數5&#xff0e;在線調整 XFS 文件系統的大小6&#xff0e;暫停和恢復 XFS 文件系統7&#xff0e;嘗試修復受損的 XFS 文件系統8&#xff0e;備份和恢…

《Spring Framework實戰》3:概覽

歡迎觀看《Spring Framework實戰》視頻教程 Spring Framework 為基于現代 Java 的企業應用程序提供了全面的編程和配置模型 - 在任何類型的部署平臺上。 Spring 的一個關鍵要素是應用程序級別的基礎設施支持&#xff1a;Spring 專注于企業應用程序的 “管道”&#xff0c;以便…

借助免費GIS工具箱輕松實現las點云格式到3dtiles格式的轉換

在當今數字化浪潮下&#xff0c;地理信息系統&#xff08;GIS&#xff09;技術日新月異&#xff0c;廣泛滲透到城市規劃、地質勘探、文化遺產保護等諸多領域。而 GISBox 作為一款功能強大且易用的 GIS 工具箱&#xff0c;以輕量級、免費使用、操作便捷等諸多優勢&#xff0c;為…

均值濾波從圖像復原角度的解釋

廖老師說若將圖像生成看作一個隨機過程&#xff0c;均值濾波&#xff08;Mean Filtering&#xff09;可以視為在高斯噪聲模型下的線性最小均方估計&#xff08;Linear Minimum Mean Squared Error, LMMSE&#xff09;或者極大似然估計&#xff08;Maximum Likelihood Estimatio…

高等數學學習筆記 ? 一元函數微分的基礎知識

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]。 本文不討論用戶界面的布局&…

Spring整合SpringMVC

目錄 【pom.xml】文件&#xff1b; 新建【applicationContext.xml】文件 新建【springmvc.xml】文件&#xff1b; 配置【src/main/webapp/WEB-INF/web.xml】文件&#xff1b; 新建【com.gupaoedu.service.IUserService】&#xff1b; 新建【com.gupaoedu.service.impl.Use…

【數據結構-堆】2233. K 次增加后的最大乘積

給你一個非負整數數組 nums 和一個整數 k 。每次操作&#xff0c;你可以選擇 nums 中 任一 元素并將它 增加 1 。 請你返回 至多 k 次操作后&#xff0c;能得到的 nums的 最大乘積 。由于答案可能很大&#xff0c;請你將答案對 109 7 取余后返回。 示例 1&#xff1a; 輸入&…