# Selenium 的網頁測試應用(含免安裝解決方案)
<br>
## **概述**
Selenium 是支援 Python 的網路爬蟲套件,透過辨識頁面元素,能支援操作鍵盤輸入、下拉選單、滑鼠操作等動作,從而取代手動動作,實現自動化的網頁操作甚至產出測試報告
Selenium 由三部分構成:WebDriver+IDE+Selenium Grid
* **IDE** : 方便編輯**語法**或錄製操作流程,未必要用 Selenium 的
* **WebDriver** : Selenium 針對不同瀏覽器有支援的 WebDriver (或下載想用的瀏覽器開源 driver 來使用)
* **Selenium Grid** : 佈署多台電腦同時測試才會用到,本篇文章不說明
<br>
![](https://i.imgur.com/A0u7aPm.png)
<br>
## **為 Selenium 安裝 driver**
查看自己瀏覽器版本並下載對應 WebDriver,或使用 Selenium IDE
[Chrome]( https://sites.google.com/chromium.org/driver/downloads )
[FireFox]( https://github.com/mozilla/geckodriver/releases )
[Edge]( https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ )
下載後呼叫使用→
```python=
from selenium import webdriver
driver = webdriver.Chrome("放置driver的路徑")
```
或直接 import Selenium 的 driver 來用→
```java=
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
...
WebDriver driver = new FirefoxDriver();
```
<br>
## **Selenium 應用**
### **主要寫法分為「指定元素操作」、「ActionChains」**
### 針對指定元素呼叫方法
抓特定元素建成物件,再調用方法動作
```python=
from selenium import webdriver
from selenium.webdriver.support.select import Select # 使用 Select 對應下拉選單
import time
driver = webdriver.Chrome('./chromedriver')
driver.get('https://example.oxxostudio.tw/python/selenium/demo.html') # 開啟範例網址
a = driver.find_element_by_id('a') # 取得 id 為 a 的網頁元素 ( 按鈕 A )
b = driver.find_element_by_class_name('btn') # 取得 class 為 btn 的網頁元素 ( 按鈕 B )
c = driver.find_element_by_css_selector('.test') # 取得 class 為 test 的網頁元素 ( 按鈕 C )
d = driver.find_element_by_name('dog') # 取得屬性 name 為 dog 的網頁元素 ( 按鈕 D )
h1 = driver.find_element_by_tag_name('h1') # 取得 tag h1 的網頁元素
link1 = driver.find_element_by_link_text('我是超連結,點擊會開啟 Google 網站') # 取得指定超連結文字的網頁元素
link2 = driver.find_element_by_partial_link_text('Google') # 取得超連結文字包含 Google 的網頁元素
select = Select(driver.find_element_by_xpath('/html/body/select')) # 取得 html > body > select 這個網頁元素
a.click() # 點擊 a
print(a.text) # 印出 a 元素的內容
time.sleep(0.5)
b.click() # 點擊 b
print(b.text) # 印出 b 元素的內容
time.sleep(0.5)
c.click() # 點擊 c
print(c.text) # 印出 c 元素的內容
time.sleep(0.5)
d.click() # 點擊 d
print(d.text) # 印出 d 元素的內容
time.sleep(0.5)
select.select_by_index(2) # 下拉選單選擇第三項 ( 第一項為 0 )
time.sleep(0.5)
h1.click() # 點擊 h1
time.sleep(0.5)
link1.click() # 點擊 link1
time.sleep(0.5)
link2.click() # 點擊 link2
print(link2.get_attribute('href')) # 印出 link2 元素的 href 屬性
```
<br>
**↓**
<br>
![](https://steam.oxxostudio.tw/webp/python/spider/selenium-04.gif)
<br>
### 使用 ActionChains 將想做的動作串成「鍊」
```python=
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Chrome('./chromedriver')
driver.get('https://example.oxxostudio.tw/python/selenium/demo.html')
a = driver.find_element_by_id('a')
show = driver.find_element_by_id('show')
actions = ActionChains(driver)
actions.click(show).send_keys(['1','2','3','4','5']) # 輸入 1~5 的鍵盤值 ( 必須是字串 )
actions.pause(1) # 等待一秒
actions.click(a) # 點擊按鈕 A
actions.pause(1) # 等待一秒
actions.send_keys_to_element(show, ['A','B','C','D','E']) # # 輸入 A~E 的鍵盤值
actions.perform() # 送出動作
```
<br>
**↓**
<br>
![image alt](https://steam.oxxostudio.tw/webp/python/spider/selenium-06.gif)
<br>
## **常見解決方案**
要利用 Selenium 至少有下列方法:
* **安裝微軟 Power Automate 使用 Selenium IDE 流程**
* **安裝 Anaconda 直接寫 Python**
* **在 console pip install 裝來用**
* **裝 Selenium IDE 或 Katalon Recorder**
<br>
### 微軟 Power Automate 使用 Selenium IDE 流程
1. 以往只要在 Power Automate 線上建立**其他桌面流程**即可選擇 **Selenium IDE 流程**來錄製腳本
https://asia.flow.microsoft.com/zh-tw/
2. 然而**其他桌面流程**選項已消失(應該是整併到**桌面流程**內),而所有桌面流程均要求下載**電腦版 Power Automate**才可使用;透過**雲端流程**則無法選擇 **Selenium IDE 流程**
3. 相關限制如下
> 不支援多重要素驗證 (MFA),請使用不需要 MFA 的租用戶。
>
> 不支援這些 Selenium IDE 命令:Run、AnswerOnNextPrompt、ChooseCancelOnNextConfirmation、ChooseCancelOnNextPrompt、ChooseOkOnNextConfirmation、Debugger、ClickAt、DoubleClickAt、Echo、MouseOut、MouseUpAt,以及 MouseDownAt。
>
> Selenium IDE 動作或步驟要執行,就不能超過一分鐘。 請改用 Power Automate。
>
> **不支援按一下滑鼠右鍵。**
>
> 當您使用 Foreach 命令時,系統會產生額外的 Selenium IDE 流程輸入。 若要解決此問題,請在額外的欄位中輸入所有值。 這不會影響播放。
>
> **直接在 Selenium IDE 中播放可能不會如預期般運作。** 不過,在執行階段會正確播放。
結論,不是很推薦使用。若做功課有爬到這條路基本上不用優先考慮
<br>
### 安裝 Anaconda 直接寫 Python
1. [安裝 Anaconda](https://steam.oxxostudio.tw/category/python/info/anaconda.html)
2. 在 Anaconda Jupyter 下指令 !pip install selenium
3. 安裝 driver,瀏覽器開源的或官方的都可以
4. 撰寫 python 以執行一系列操作
例如 driver.get('URL') 來連線特定 URL
![](https://i.imgur.com/F4VwJ5A.png)
<br>
### 裝 Selenium IDE 或 Katalon Recorder
[Katalon Recorder](https://chrome.google.com/webstore/detail/katalon-recorder-selenium/ljdobmomdgdljniojadhoplhkpialdid)
[Selenium IDE](https://chrome.google.com/webstore/detail/selenium-ide/mooikfkahbdckldjjndioackbalphokd)
![](https://i.imgur.com/ffBBi46.png)
![](https://i.imgur.com/51JbY0t.png)
**(DEMO環節)**
<br>
## **其他酷東西**
### XPATH做元素定位(利用Ruto、ChroPath等插件工具)
XPATH:HTML 經過編譯成 XML 後找出的對應位置,且分為絕對位置與相對位置
> 相對位置://div[@class='ytp-tooltip-text-wrapper']
> 絕對位置: /html[1]/body[1]/ytd-app[1]/div[1]/ytd-page-manager[1]/ytd-watch-flexy[1]/div[5]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/ytd-player[1]/div[1]/div[1]/div[10]/div[1]
**安裝[RUTO](https://chrome.google.com/webstore/detail/ruto-xpath-finder/ilcoelkkcokgeeijnopjnolmmighnppp?hl=zh-TW)**
![](https://i.imgur.com/jRFe2bn.png)
**安裝[ChroPath](https://chrome.google.com/webstore/detail/chropath/ljngjbnaijcbncmcnjfhigebomdlkcjo?hl=zh-TW)**
F12後多出ChroPath頁籤方便查找元素:
![](https://i.imgur.com/jhcSCXB.png)
<br>
### 拍截圖
```python=
body = driver.find_element_by_tag_name('body')
body.screenshot('./test.png')
```
### 跑 JavaScript
```python=
h1 = driver.find_element_by_tag_name('h1')
h3 = driver.find_element_by_tag_name('h3')
script = '''
let h1 = arguments[0];
let h3 = arguments[1];
alert(h1, h3)
'''
driver.execute_script(script, h1, h3) # 執行 JavaScript,印出元素
sleep(2)
Alert(driver).accept() # 點擊提示視窗的確認按鈕,關閉提示視窗
```
### 切換視窗
```python=
driver.switch_to.window("windowName")
```
### 使用既有 Profile
若要使用 Google Chrome 中既有的 Profile 來進行測試,可將其作為參數加入 WebDriver:
```python=
from selenium import webdriver
# 設定檔案路徑參數成為自訂的 WebDriver (命名為 options)
options = webdriver.ChromeOptions()
options.add_argument("--user-data-dir=C:UsersOfficeGuideAppDataLocalGoogleChromeUser Data")
options.add_argument("--profile-directory=Profile 1")
# 使用自訂的 WebDriver
browser = webdriver.Chrome(options=options)
```
<br>
### 列印 PDF 報表(Goodinfo!為例)
```python=
import json
from time import sleep
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
settings = {"recentDestinations": [{"id": "Save as PDF", "origin": "local", "account": ""}],
"selectedDestinationId": "Save as PDF", "version": 2,
"isCssBackgroundEnabled": True, "scalingType": 3, "scaling": 100}
#此處記得設定您本地電腦可以存檔的路徑
prefs = {"printing.print_preview_sticky_settings.appState": json.dumps(settings),
"savefile.default_directory": "C:/Users/user/Downloads"}
options.add_experimental_option('prefs', prefs)
options.add_argument('--kiosk-printing')
#這兩句處理 driver,請設定事前存好的driver 或 remote call來用
webdriver_path = 'D:/Python/CultivationGrid/selenium/chromedriver.exe'
driver = webdriver.Chrome(executable_path=webdriver_path, options=options)
driver.get("https://goodinfo.tw/StockInfo/index.asp")
driver.find_element_by_id("txtStockCode").click()
driver.find_element_by_id("txtStockCode").clear()
driver.find_element_by_id("txtStockCode").send_keys("0050")
driver.find_element_by_xpath(u"//input[@value='股票查詢']").click()
driver.find_element_by_id("imgKC").click()
sleep(5)
driver.execute_script('window.print();')
driver.close()
```
<br>
### 若有多支py可用BeautifulReport產報表來看
1. 下載BeautifulReport
https://github.com/TesterlifeRaymond/BeautifulReport
2. 資料夾名稱改為 BeautifulReport,放到 python 的 library
例 C:\Users\你的使用者名稱\AppData\Local\Programs\Python\Python39\Lib\site-packages\
3.
```python=
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support import expected_conditions as EC
from BeautifulReport import BeautifulReport
from webdriver_manager.chrome import ChromeDriverManager
import time
import unittest
## 設定Chrome的瀏覽器彈出時遵照的規則
## 這串設定是防止瀏覽器上頭顯示「Chrome正受自動控制」
options = webdriver.ChromeOptions()
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
## 關閉自動記住密碼的提示彈窗
options.add_experimental_option("prefs", {
"profile.password_manager_enabled": False,
"credentials_enable_service": False
})
## 如果要將CASE拆成幾個不同的方法,需要用一個Unitest Class包覆起來,然後加上修飾符@classmethod
class Test(unittest.TestCase):
@classmethod
def setUpClass(self):
self.driver = webdriver.Chrome(chrome_options=options)
self.action = ActionChains(self.driver)
## 開啟Chrome新視窗,前往Youtube網址並最大化視窗
self.URL = "https://youtube.com"
self.driver.get(self.URL)
self.driver.maximize_window()
@classmethod
def tearDownClass(self):
self.driver.quit() #全部做完後關閉瀏覽器
## Test Case 的命名方式務必以「test_01_* ~ test_99_*」為主,讓爬蟲依照順序走
def test_01_search(self):
"""
測項1
"""
def test_02_open_target(self):
"""
測項2
"""
def test_03_back_to_list(self):
"""
測項3
"""
# basedir就是存放所有TEST Case的目錄,讓它爬 pattern = '*.py',所以要做哪個類別的測試就指定哪個前贅
basedir = "D:/auto_test/"
if __name__ == '__main__':
# 取得資料夾目錄底下,符合後面任何副檔名為.py,並進行所有test的測試項目
test_suite = unittest.defaultTestLoader.discover(
basedir, pattern='*.py')
# 測試結果加入到 BeautifulReport 套件內
result = BeautifulReport(test_suite)
# 結果產生Report 檔案名稱為 filename, 敘述為 description, log_path 預設放在跟目錄底下就行
result.report(filename='report',
description='我的第一個測試', log_path='D:/auto_test/')
```
**↓**
![](https://i.imgur.com/2aMtny1.png)
<br>
### 做好的腳本可以用 Robointern 在本地電腦排程執行
[Robointern](https://robointern.tech/#screens)
<br>
## **參考資料**
[Microsoft Build 建立及測試 Selenium IDE 流程](https://docs.microsoft.com/zh-tw/power-automate/desktop-flows/create-web)
[ Steam教育網 Selenium 函式庫 ]( https://steam.oxxostudio.tw/category/python/spider/selenium.html )
[Selenium 是什麼?用 Python Selenium 自動爬網頁抓報表,初學者必看的簡單教學 ]( https://igoamazing.com/python-selenium/#1_%E9%8C%84%E8%A3%BD%E4%B8%A6%E8%87%AA%E5%8B%95%E7%94%A2%E7%94%9F%E7%A8%8B%E5%BC%8F%E7%A2%BC )
[Python Selenium with VSCODE 教學筆記 ]( https://hackmd.io/@FortesHuang/S1V6jrvet#Python-Selenium-with-VSCODE-%E6%95%99%E5%AD%B8%E7%AD%86%E8%A8%98 )
###### tags: `Java`,`Python`,`Selenium`