程式語言:Python
Package:selenium
官方網站
功能:控制瀏覽器
建議使用
例:
find_element_by_id => find_elements_by_id
find_element => find_elements
也有截圖 screenshot(filename) 若出現 error,表示瀏覽器不支援,可用 PIL 自行截取
詳細可參考
選擇值
提交
暗示型的等待
範例
事件種類
Selenium Documentation
Package:selenium
官方網站
功能:控制瀏覽器
from selenium import webdriver from selenium.common.exceptions import TimeoutException # available since 2.4.0 from selenium.webdriver.support.ui import WebDriverWait # available since 2.26.0 from selenium.webdriver.support import expected_conditions as EC # 建立 driver # 需下載 Browser Drivers http://www.seleniumhq.org/download/ # 若 geckodriver 有在 PATH 中, firefox 可不帶路徑參數 driver = webdriver.Firefox(executable_path=r'.\driver\geckodriver.exe') # 去 google driver.get("http://www.google.com") # 顯示標題 print(driver.title) # 找到搜尋框 inputElement = driver.find_element_by_name("q") # 搜尋框輸入字 inputElement.send_keys("cheese!") # 提交 inputElement.submit() try: # 直到標題有 cheese WebDriverWait(driver, 10).until(EC.title_contains("cheese!")) # 顯示標題,可看到 cheese print(driver.title) except TimeoutException: print('time out') finally: driver.quit()
建立 driver
詳細可參考driver = webdriver.Firefox() # 需下載 driver 才能用 http://www.seleniumhq.org/download/ # 若 geckodriver 有在 PATH 中, firefox 可不帶路徑參數 driver = webdriver.Firefox(executable_path=r'.\driver\geckodriver.exe') driver = webdriver.Chrome('/path/to/chromedriver') driver = webdriver.Ie('/path/to/Iedriver') # 可更改 firefox 的 profile profile = webdriver.FirefoxProfile() profile.native_events_enabled = True driver = webdriver.Firefox(profile) # 目前網址 driver.current_url # 截圖 driver.save_screenshot('/Screenshots/foo.png') # 原始碼 driver.page_source with open('test.html','wb') as f: f.write(driver.page_source.encode('utf-8')) # 標題 driver.title # 重新整理 driver.refresh() # 關閉目前視窗 driver.close() # 結束全部視窗 driver.quit()
如何選擇 element
找不到會回傳 NoSuchElementException建議使用
from selenium.common.exceptions import NoSuchElementExceptionPS. 複數選擇加上 s 即可
例:
find_element_by_id => find_elements_by_id
find_element => find_elements
- By id
<div id="coolestWidgetEvah">...</div>
element = driver.find_element_by_id("coolestWidgetEvah")
from selenium.webdriver.common.by import By element = driver.find_element(By.ID, "coolestWidgetEvah")
- By Class Name
<div class="coolestWidgetEvah">...</div>
element = driver.find_element_by_class_name("coolestWidgetEvah")
from selenium.webdriver.common.by import By element = driver.find_element(By.CLASS_NAME, "coolestWidgetEvah")
- By Tag Name
<iframe src="..."></iframe>
element = driver.find_element_by_tag_name("iframe")
from selenium.webdriver.common.by import By element = driver.find_element(By.TAG_NAME, "iframe")
- By Name
<div name="coolestWidgetEvah">...</div>
element = driver.find_element_by_name("coolestWidgetEvah")
from selenium.webdriver.common.by import By element = driver.find_element(by=By.NAME, value="coolestWidgetEvah")
- By Link Text
<a href="http://www.google.com/search?q=cheese">abc</a>>
element = driver.find_element_by_link_text("abc")
from selenium.webdriver.common.by import By element = driver.find_element(by=By.LINK_TEXT, value="abc")
- By Partial Link Text
<a href="http://www.google.com/search?q=cheese">abc</a>>
element = driver.find_element_by_partial_link_text("ab")
from selenium.webdriver.common.by import By element = driver.find_element(By.PARTIAL_LINK_TEXT, "ab")
- By CSS
- CSS Selector Reference
<div id="food"><span class="dairy aged">cheese</span></div>
element = driver.find_element_by_css_selector("#food span.dairy.aged")
from selenium.webdriver.common.by import By element = driver.find_element(By.CSS_SELECTOR, "#food span.dairy.aged")
- By XPath
- [Python] XPath 教學
<input type="text" name="example" />
element = driver.find_element_by_xpath("//input")
from selenium.webdriver.common.by import By element = driver.find_element(By.XPATH, "//input")
- Using JavaScript
element = driver.execute_script("return $('.cheese')[0]")
-
labels = driver.find_elements_by_tag_name("label") inputs = driver.execute_script( "var labels = arguments[0], inputs = []; for (var i=0; i < labels.length; i++){" + "inputs.push(document.getElementById(labels[i].getAttribute('for'))); } return inputs;", labels)
element 相關
同樣具有上面的尋找 function 跟 send_keys 的功能也有截圖 screenshot(filename) 若出現 error,表示瀏覽器不支援,可用 PIL 自行截取
詳細可參考
- clear()
- 清除內容
- click()
- 點擊
- get_attribute(name)
- 得到 attribute/property 的值
- is_active = "active" in target_element.get_attribute("class")
- id
- Internal ID 被 selenium 所使用
- 可用來比較兩者是否一樣
- is_displayed()
- 是否可見
- is_enabled()
- 是否可使用
- is_selected()
- 是否被選擇
- location
- 元件位置
- location_once_scrolled_into_view
- 可見的話回傳位置,不然為 None
- parent
- 元件的上一層
- rect
- 元件的位置與大小
- size
- 元件的大小
- submit()
- 提交
- tag_name
- tag 的名字
- text
- text 的值
- value_of_css_property(property_name)
- css 的值
- element.value_of_css_property("font-size")
填表的方式
填入值element.send_keys("pycon") element.clear() # 清除
選擇值
select = driver.find_element_by_tag_name("select") allOptions = select.find_elements_by_tag_name("option") for option in allOptions: print "Value is: " + option.get_attribute("value") option.click()
<select name="YourLocation" style="width:200px;"> <option value="Taipei">台北</option> <option value="Taoyuan">桃園</option> <option value="Hsinchu">新竹</option> <option value="Miaoli">苗栗</option> </select>
# available since 2.12 from selenium.webdriver.support.ui import Select # 選擇 select = Select(driver.find_element_by_name('YourLocation')) select.select_by_index(1) => 桃園 select.select_by_visible_text("新竹") select.select_by_value("Taipei") # 取消,只能用於多選,可用 select.is_multiple 判斷會為 True,但單選為 None select.deselect_by_index(1) select.deselect_by_visible_text("新竹") select.deselect_by_value("Taipei") select.deselect_all() # 目前選擇的項目 select.all_selected_options # 選單項目 select.options
提交
driver.find_element_by_id("submit").click() element.submit()
切換視窗的方法
需由程式產生的 driver,並由此 driver 生成的新視窗才有用driver.switch_to.window("windowName") for handle in driver.window_handles: driver.switch_to.window(handle) # 也可切 frame driver.switch_to.frame("frameName") driver.switch_to_frame("frameName.0.child") # 回到初始位置 driver.switch_to_default_content()
警告視窗
# 得到警告視窗 alert = driver.switch_to_alert() # 忽略 alert.dismiss() # 接受 alert.accept() # 輸入帳密 alert.authenticate(username, password)
瀏覽方法
# 取得網址,直到網頁完成才會繼續往下,但 AJAX 需用檢查元件存在的方式 driver.get("http://www.example.com") # 下一頁 driver.forward() # 上一頁 driver.back()
Cookies 操作
# 加入 driver.add_cookie({'name':'key', 'value':'value', 'path':'/'}) # 得到 for cookie in driver.get_cookies(): print "%s -> %s" % (cookie['name'], cookie['value']) # 刪除 driver.delete_cookie("CookieName") driver.delete_all_cookies()
執行操作
- click(on_element=None)
- 左鍵點擊
- 可傳入 element ,若為 None,則依滑鼠位置進行動作
- click_and_hold(on_element=None)
- 左鍵按住
- 可傳入 element ,若為 None,則依滑鼠位置進行動作
- context_click(on_element=None)
- 右鍵點擊
- 可傳入 element ,若為 None,則依滑鼠位置進行動作
- context_click(on_element=None)
- 右鍵點擊
- 可傳入 element ,若為 None,則依滑鼠位置進行動作
- double_click(on_element=None)
- 左鍵連擊
- 可傳入 element ,若為 None,則依滑鼠位置進行動作
- drag_and_drop(source, target)
- 拖曳並放開
- 拖曳 source 到 target 中
- drag_and_drop_by_offset(source, xoffset, yoffset)
- 拖曳並放開
- 拖曳 source 到遠離原本位置 (xoffset, yoffset) 的相對位置
- key_down(value, element=None)
- 按住鍵盤某個值
- 傳入值,也可傳入 element ,若為 None,則依目前 focused 的元件進行動作
- ctrl+c
- from selenium.webdriver.common.keys import Keys
ActionChains(driver).key_down(Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform() - key_up(value, element=None)
- 放開鍵盤某個值
- 傳入值,也可傳入 element ,若為 None,則依目前 focused 的元件進行動作
- move_by_offset(xoffset, yoffset)
- 移動滑鼠,為虛擬的,並非實際的滑鼠,所以看不到
- 可傳入 element ,若為 None,則依滑鼠位置進行動作
- move_to_element(to_element)
- 移動滑鼠至元件,為虛擬的,並非實際的滑鼠,所以看不到
- 傳入 element
- move_to_element_with_offset(to_element, xoffset, yoffset)
- 移動滑鼠至元件的相對位置,為虛擬的,並非實際的滑鼠,所以看不到
- 傳入 element 與相對位置 (xoffset, yoffset)
- perform()
- 執行動作
- 所以動作都必須執行,才會成立
- release(on_element=None)
- 放開左鍵
- 可傳入 element ,若為 None,則依滑鼠位置進行動作
- send_keys(*keys_to_send)
- 送出複數的鍵盤值
- 傳入值,可用 Keys 得到特殊鍵
from selenium.webdriver.common.keys import Keys - send_keys_to_element(element, *keys_to_send)
- 送出複數的鍵盤值給元件
- 傳入元件與值,可用 Keys 得到特殊鍵
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains menu = driver.find_element_by_css_selector(".nav") hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1") ActionChains(driver).move_to_element(menu).click(hidden_submenu).perform() menu = driver.find_element_by_css_selector(".nav") hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1") actions = ActionChains(driver) actions.move_to_element(menu) actions.click(hidden_submenu) # actions 已記錄上面動作,只需執行便可重覆之 actions.perform() # 拖曳放置 element = driver.find_element_by_name("source") target = driver.find_element_by_name("target") ActionChains(driver).drag_and_drop(element, target).perform()
等待
WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)from selenium.webdriver.support.ui import WebDriverWait # 可使用 until element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("someId")) # 可使用 until_not is_disappeared = WebDriverWait(driver, 30, 1, (ElementNotVisibleException)). until_not(lambda x: x.find_element_by_id("someId").is_displayed())明確型的等待
# 等待 10s 直到有 id 符合 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 TimeoutException driver = webdriver.Firefox() driver.get("http://somedomain/url_that_delays_loading") try: element = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "myDynamicElement")) ) except TimeoutException: print('time out') finally: driver.quit()
暗示型的等待
from selenium import webdriver driver = webdriver.Firefox() # 尋找時間初始值為 0 driver.implicitly_wait(10) # seconds driver.get("http://somedomain/url_that_delays_loading") myDynamicElement = driver.find_element_by_id("myDynamicElement")
期望條件
建立後,需傳入 driver 同下或是用 until 執行同上from selenium.webdriver.support import expected_conditions as EC test = EC.title_is("google") test(driver) # get resultlocator = (by, path),例:(By.NAME, "google")
- alert_is_present()
- 檢查是否有警告視窗
- element_located_selection_state_to_be(locator, is_selected)
- 檢查選擇的狀態
- element_located_to_be_selected(locator)
- 檢查是否被選擇
- element_selection_state_to_be(element, is_selected)
- 檢查選擇的狀態
- element_to_be_clickable(locator)
- 檢查是否 visible 且 enabled
- element_to_be_selected(element)
- 檢查是否被選擇
- frame_to_be_available_and_switch_to_it(locator)
- frame 是否可用,可用則切換過去
- invisibility_of_element_located(locator)
- 檢查是否不可見或不存在
- presence_of_all_elements_located(locator)
- 檢查是否存在,並回傳所有存在
- presence_of_element_located(locator)
- 檢查是否存在,並回傳第一個存在
- staleness_of(element)
- 等待直到元件不存在
- text_to_be_present_in_element(locator, text_)
- 檢查元件 text 是否包含特定字串
- text_to_be_present_in_element_value(locator, text_)
- 檢查元件 value 是否包含特定字串
- title_contains(title)
- 檢查標題是否包含特定字串
- title_is(title)
- 檢查標題是否為特定字串
- visibility_of(element)
- 檢查是否可見,可見:代表非隱藏,並且寬和高都不等於 0
- visibility_of_element_located(locator)
- 檢查是否可見,可見:代表非隱藏,並且寬和高都不等於 0
建立具有事件的 driver
但只有透過程式執行,才算數範例
from selenium.webdriver import Firefox from selenium.webdriver.support.events import EventFiringWebDriver, AbstractEventListener class MyListener(AbstractEventListener): def before_navigate_to(self, url, driver): print("Before navigate to %s" % url) def after_navigate_to(self, url, driver): print("After navigate to %s" % url) driver = Firefox() ef_driver = EventFiringWebDriver(driver, MyListener()) ef_driver.get("http://www.google.co.in/")
事件種類
- after_change_value_of(element, driver)
- after_click(element, driver)
- after_close(driver)
- after_execute_script(script, driver)
- after_find(by, value, driver)
- after_navigate_back(driver)
- after_navigate_forward(driver)
- after_navigate_to(url, driver)
- after_quit(driver)
- before_change_value_of(element, driver)
- before_click(element, driver)
- before_close(driver)
- before_execute_script(script, driver)
- before_find(by, value, driver)
- before_navigate_back(driver)
- before_navigate_forward(driver)
- before_navigate_to(url, driver)
- before_quit(driver)
- on_exception(exception, driver)
執行 JavaScript
- execute_async_script(script, *args)
- 非同步
- execute_script(script, *args)
- 同步
driver.execute_script(script) r.find_elements_by_tag_name("label") inputs = driver.execute_script(script)
顏色值轉換
from selenium.webdriver.support.color import Color # rgba(0, 255, 51, 1) print(Color.from_string('#00ff33').rgba) # #01ff03 print(Color.from_string('rgb(1, 255, 3)').hex) # rgb(0, 0, 255) print(Color.from_string('blue').rgb)
參考:
Selenium Python BindingsSelenium Documentation
好詳細謝謝大大
回覆刪除很棒的文章
回覆刪除