跳到主要內容

Python Selenium 瀏覽器自動化測試工具

 前言

Selenium 是一套「瀏覽器自動化測試工具」,主要用於: Web 自動化測試 網頁操作模擬 自動登入 自動填表 網頁資料爬取(Web Scraping)。它可以模擬使用者在瀏覽器中的操作,例如: 點擊按鈕 輸入文字 切換頁面


參考: https://www.selenium.dev/documentation/



安裝所需套件

pip3 install selenium


測試網頁

http://automated.pythonanywhere.com




測試代碼

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import WebDriverException
import time

def get_driver():
# 增加啓動chrome參數
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--headless") # 啓動無頭模式, 不會開啓瀏覽器視窗
chrome_options.add_argument("--disable-infobars")
chrome_options.add_argument('--start-maximized') # 啓動後最大化視窗
chrome_options.add_argument('--no-sandbox') # 以最高權限運行
chrome_options.add_argument('--disable-dev-shm-usage')
# 增加實驗性質的設置參數
chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])
chrome_options.add_argument("--disable-blink-features=AutomationControlled")
try:
driver = webdriver.Chrome(options=chrome_options)
driver.get('http://automated.pythonanywhere.com')
time.sleep(2)
return driver
except WebDriverException:
print("Selenium Manager failed to locate a driver. Falling back to webdriver-manager.")
except Exception as e:
print(f"Exception: {e}")

def main():
driver = get_driver()
try:
print(f"頁面標題: {driver.title}")
# find_element 抓取符合條件的第一個項目
element = driver.find_element(By.XPATH, "/html/body/div[1]/div/h1[1]")
print(element.text)

element = driver.find_element(By.XPATH, "/html/body/div[1]/div/h1[2]")
print(f"Average World Temperature Now: {clean_text(element.text)}")

except Exception as e:
print(f"Exception: {e}")

finally:
driver.quit()

def clean_text(text):
output = float(text.split(": ")[1])
return output

if __name__ == "__main__":
main()


測試




常見 add_argument() 參數 用途整理

--headless 無頭模式,是指瀏覽器在後台運行,不會彈出可見的視窗。
--incognito 無痕模式, 啟動進入隱身模式
--start-maximized 最大化視窗
--window-size=w,h 設定解析度
--disable-gpu 關閉 GPU
--disable-notifications 關閉通知
--disable-plugins 禁止載入所有外掛,可以增加速度。可以通過about:plugins頁面檢視效果
--disable-javascript 禁用JavaScript,如果覺得速度慢在加上這個
--disable-java 禁用java
--disable-popup-blocking 禁用彈出攔截
--lang=zh-TW 設定語言為繁體中文
--disable-blink-features=AutomationControlled 關閉自動化提示,降低網站偵測 Selenium
其他參數可查網站
或 
https://developer.chrome.com/docs/chromedriver/capabilities


進階 測試 www.pythonanywhere.com

流程從 [登入] -> [抓取某個欄位值]

1. 登入網站, 輸入欄位資料, 點擊 login





2. 取得 CPU Usage 的值




3. 取得 XPath 




測試代碼

from concurrent.futures import wait

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
from selenium.common.exceptions import NoSuchElementException, WebDriverException, TimeoutException
import time


def get_driver():
# 增加啓動chrome參數
chrome_options = webdriver.ChromeOptions()
#chrome_options.add_argument("--headless") # 啓動無頭模式, 不會開啓瀏覽器視窗
chrome_options.add_argument("--disable-infobars") # 隱藏 Chrome 瀏覽器頂部的「Chrome 正在被自動化測試工具控制」提示條
chrome_options.add_argument('--start-maximized') # 啓動後最大化視窗
chrome_options.add_argument('--no-sandbox') # 以最高權限運行
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])
chrome_options.add_argument("--disable-blink-features=AutomationControlled")
try:
driver = webdriver.Chrome(options=chrome_options)

driver.get('https://www.pythonanywhere.com/login/')
# # Wait for the page to load
time.sleep(2)
return driver
except WebDriverException:
print(f"Selenium Manager failed to locate a driver. Falling back to webdriver-manager. {WebDriverException}")
except Exception as e:
print(f"Exception: {e}")

def main():
driver = get_driver()
if not driver:
return
try:
print(f"頁面標題: {driver.title}")
# 顯性等待可以設定許多條件,來達到完全我們需要的場景,明確等待某個特定條件,等出現後才會去執行下一步的動作,這樣就不會因為網路或是其他因素導致元素還沒出現就去操作,從而導致錯誤。
wait = WebDriverWait(driver, 15, 0.5)
'''
時間、頻率、忽略例外錯誤
timeout,等待時間,以秒為單位,強制等待跟隱性等待的等待時間也是以秒為單位。
poll_frequency,指定等待條件檢查的頻率,以秒為單位,預設值是0.5秒,可以不設定,如果不設定的情況下,那WebDriver會按照預設值每0.5秒檢查一次元素是否出現,有設定則按照預設值。
'''

# 輸入帳號,密碼
username_input = wait.until(
EC.presence_of_element_located((By.ID, "id_auth-username")))
username_input.send_keys('你的帳號')
password_input = wait.until(
EC.visibility_of_element_located((By.ID, "id_auth-password")))
password_input.send_keys('你的密碼')
# 2. 點擊login
next_button = wait.until(EC.element_to_be_clickable((By.ID, "id_next")))
next_button.click()

time.sleep(5)
print(f"最終登入後的 URL: {driver.current_url}")
driver.find_element(By.XPATH, "/html/body/div[1]/nav[2]/div/div[2]/ul/li[1]/a").click()
time.sleep(2)
cpu_usage_percent = driver.find_element(By.XPATH, "/html/body/div[1]/main/div/div[2]/div[1]/p[1]/span[1]/span[1]").text
print(f"CPU 使用率: {cpu_usage_percent}")
except TimeoutException as te:
print(f"等待元素超時: {te}")
except Exception as e:
print(f"流程中斷,異常原因: {e}")


def clean_text(text):
output = float(text.split(": ")[1])
return output

if __name__ == "__main__":
main()


測試 操作模擬 自動登入 自動填表 取得網頁資料結果::

留言

這個網誌中的熱門文章

初探 Vue 呼叫 API 出現 CORS 跨來源資源共享 問題原因

提要:   在 {初探Vue 與 Spring boot 的對話} 專案 ,前端 Vue 應用程式 串接 後端 API 伺服器 ,axios 呼叫 API 時出現以下,”無法取得回應內容 (No 'Access-Control-Allow-Origin' header is present on the requested resource):” 錯誤訊息,根據查找相關資料 ,出現以下原因。 瀏覽器開發工具 錯誤訊息 畫面 錯誤原因: “ Access to XMLHttpRequest at ” from origin ‘http://localhost:8080’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource” 瀏覽器為了安全考量,實施了同源政策。 當您的前端應用程式 (http://localhost:8080) 嘗試呼叫一個不同來源 (不同協議、不同域名或不同埠號) 的 API 伺服器 (http://localhost:8088) 時,瀏覽器會主動阻止這個請求,除非伺服器明確地允許這個跨來源的存取。 同源政策限制(Same-Origin Policy): 同源政策限制了程式碼和不同網域資源間的互動,同源是指兩份網頁具備相同協定、埠號(如果有指定)以及主機位置 範例: 表列哪些 URL 與 URL http://www.example.com/api/p1 屬於同源: URL                                                   | 結果   | 原因 --------------------------------------------------------------------- http://www.example.com/api/p2     |...

初探 Vue 與 Spring boot 的對話之Frontend (Vue-Frontend)

  Front-end Vue 使用 REST API 建立 Vite 專案 可參考 { Vue 3 初探}  文章 danny@Danny-Yu projects % npm create vite@latest Need to install the following packages: create-vite@8.2.0 Ok to proceed? (y) y > npx > "create-vite" │ ◇   Project name: │   vue-frontend │ ◇   Select a framework: │   Vue │ ◇   Select a variant: │   TypeScript │ ◇   Use rolldown-vite (Experimental)?: │   No │ ◇   Install with npm and start now? │   Yes │ ◇   Scaffolding project in /Users/danny/Desktop/projects/vue-frontend... │ ◇   Installing dependencies with npm... added 47 packages, and audited 48 packages in 27s 6 packages are looking for funding   run `npm fund` for details found 0 vulnerabilities │ ◇   Starting dev server... > vue-frontend@0.0.0 dev > vite   VITE v7.2.4   ready in 411 ms   ➜   Local:   http://localhost:5173/   ➜   Network: use --host to expose   ➜   press h + enter to show...

初探 Spring 中的循環依賴

原因: 當兩個或多個 bean 直接或間接地相互依賴時, 就會出現 Circular Dependency (循環依賴) 如: Bean A -> Bean B -> Bean A import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class BeanA {          @Autowired     private BeanB beanB;     public String sayHi() {         return "Hi! 我是 Class A.";     } } import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class BeanB {          @Autowired     private BeanA beanA;     public String sayHi() {         return "Hi! 我是 Class B.";     } } 編譯時不會出現問題 danny@Danny-Yu demo % mvn clean install -Dmaven.test.skip=true                           ... ... [INFO] Installing /Users/danny/Desktop/projects/demo/target/dem...