python之selenium基础知识

内容总结自官方文档 https://www.selenium.dev/documentation/

Selenium WebDriver

WebDriver 被设计为一个简单而简洁的编程接口。WebDriver 是一个紧凑的面向对象 API。它有效地驱动浏览器。

Selenium 通过使用 WebDriver 支持市场上所有主要浏览器的自动化。WebDriver定义了一个用于控制 web 浏览器行为的语言-中间接口。每个浏览器都由一个特定的 WebDriver 实现支持,称为驱动程序。驱动程序是负责将任务委托给浏览器的组件,并处理与 Selenium 和浏览器之间的通信。
这种分离是有意识地让浏览器供应商为其浏览器的实现负责的一部分。Selenium 在可能的情况下使用这些第三方驱动程序,但在不现实的情况下,也提供了由项目维护的自己的驱动程序。

WebDriver 可以通过驱动程序与浏览器通信。通信是双向的:WebDriver 通过驱动程序将命令传递给浏览器,并通过相同的路由接收信息。
该驱动程序特定于浏览器,例如适用于谷歌 Chrome/Chromium 的 ChromeDriver、适用于 Mozilla Firefox 的 GeckoDriver 等。该驱动程序与浏览器在同一系统上运行。

Selenium 框架通过面向用户的界面将所有这些部分联系在一起,该界面使不同的浏览器后端能够透明地使用,从而实现了跨浏览器和跨平台的自动化。Selenium 的设置与其他商业工具的设置截然不同。在开始编写 Selenium 代码之前,您必须安装所选语言的语言绑定库、要使用的浏览器以及该浏览器的驱动程序。
 

元素相关

from selenium import webdriver
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.by import By
from selenium.webdriver.support.relative_locator import locate_with

driver = webdriver.Chrome()

# 通过类名定位元素
driver.find_element(By.CLASS_NAME, "information")
# 通过css选择器定位元素
driver.find_element(By.CSS_SELECTOR, "button")
driver.find_element(By.CSS_SELECTOR, "#fname")
# 通过id定位元素
driver.find_element(By.ID, "form")
# 通过name属性定位元素
driver.find_element(by=By.NAME, value="my-text")
# 通过标签名定位元素
driver.find_element(By.TAG_NAME, "button")
# 通过xpath定位元素
driver.find_element(By.XPATH, "//button[@type='submit']")
# 通过链接文本定位元素
driver.find_element(By.LINK_TEXT, "Selenium Official Page")
# 通过部分链接文本定位元素
driver.find_element(By.PARTIAL_LINK_TEXT, "Official Page")

# 相对定位器
email_locator = locate_with(By.TAG_NAME, "input").above({By.ID: "password"})
password_locator = locate_with(By.TAG_NAME, "input").below({By.ID: "email"})
cancel_locator = locate_with(By.TAG_NAME, "button").to_left_of({By.ID: "submit"})
submit_locator = locate_with(By.TAG_NAME, "button").to_right_of({By.ID: "cancel"})
email_locator = locate_with(By.TAG_NAME, "input").near({By.ID: "lbl-email"})
submit_locator = locate_with(By.TAG_NAME, "button").below({By.ID: "email"}).to_right_of({By.ID: "cancel"})

# 评估整个DOM
vegetable = driver.find_element(By.CSS_SELECTOR, "#fruits .tomatoes")
plants = driver.find_elements(By.TAG_NAME, "li")
# 评估DOM的子集
fruits = driver.find_element(By.ID, "fruits")
fruit = fruits.find_element(By.CLASS_NAME, "tomatoes")

# 获取活动元素
active_elem = driver.switch_to.active_element

# 点击元素
driver.find_element(By.NAME, "color_input").click()

# 清空输入框内容
driver.find_element(By.NAME, "text_input").clear()
# 输入文本
driver.find_element(By.NAME, "text_input").send_keys("aa")


# 是否被选中
value = driver.find_element(By.NAME, "checkbox_input").is_selected()
# 是否可用
value = driver.find_element(By.NAME, "button_input").is_enabled()
# 是否显示
is_email_visible = driver.find_element(By.NAME, "email_input").is_displayed()
# 获取元素文本内容
text = driver.find_element(By.ID, "justanotherlink").text
# 获取标签名
attr = driver.find_element(By.NAME, "email_input").tag_name
# 获取css值
cssValue = driver.find_element(By.ID, "namedColor").value_of_css_property("background-color")
# 获取大小和位置
res = driver.find_element(By.NAME, "range_input").rect
# 获取属性或特性
driver.find_element(By.NAME, "email_input").get_attribute("value")
driver.find_element(By.NAME, "email_input").get_property("id")
# 选择下拉框选项
select = Select(driver.find_element(By.ID, "city"))
select.select_by_visible_text("北京")
select.select_by_index(1)
select.select_by_value("BJ")
option_list = select.options
selected_option_list = select.all_selected_options
select.deselect_by_value("eggs")  # 取消选择选项

# 文件上传
file_input = driver.find_element(By.CSS_SELECTOR, "input[type='file']")
file_input.send_keys("/path/to/file")
driver.find_element(By.ID, "file-submit").click()

浏览器相关

from selenium import webdriver
import subprocess
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.webdriver.common.print_page_options import PrintOptions

# 选项
options = webdriver.ChromeOptions()
# 添加参数
options.add_argument("--start-maximized")
# 使用chromedriver驱动各基于Chromium的浏览器
options.binary_location = "/path/to/chrome_bin"
# 添加扩展
options.add_extension("/path/to/extension_file_path")
# 保持浏览器打开
options.add_experimental_option("detach", True)
# 排除默认参数
options.add_experimental_option("excludeSwitches", ["disable-popup-blocking"])

# 日志输出到文件并设置文件特征
service = webdriver.ChromeService(service_args=["--append-log", "--readable-timestamp"], log_output="/path/to/log_path")
# 日志输出到标准输出并设置日志级别
service = webdriver.ChromeService(service_args=["--log-level=DEBUG"], log_output=subprocess.STDOUT)

driver = webdriver.Chrome(options=options, service=service)


# 获取浏览器信息
# 获取标题
title = driver.title
# 获取当前URL
url = driver.current_url


# 浏览器导航
# 前进
driver.forward()
# 后退
driver.back()
# 刷新
driver.refresh()


# cookie操作
# 获取cookie
print(driver.get_cookie("age"))
print(driver.get_cookies())
# 添加cookie
driver.add_cookie({"name": "age", "value": 22})
driver.add_cookie({"name": "foo", "value": "value", "sameSite": "Strict"})
# 删除cookie
driver.delete_cookie("age")
# 删除所有cookie
driver.delete_all_cookies()


# iframe
driver.switch_to.frame(driver.find_element(By.CSS_SELECTOR, "#modal > iframe"))
driver.switch_to.frame("buttonframe")  # id
driver.switch_to.frame(driver.find_elements(By.TAG_NAME, "iframe")[1])
driver.switch_to.default_content()  # 切换回默认内容


# 窗口操作
# 当前窗口
curr_window = driver.current_window_handle
# 所有窗口
all_windows = driver.window_handles
# 切换到另一个窗口
another_window = all_windows[0]
driver.switch_to.window(another_window)
# 切换到新的窗口或者tab
driver.switch_to.new_window("tab")
driver.switch_to.new_window("tab")
# 关闭当前标签页面
driver.close()
# 关闭浏览器
driver.quit()
# 最大化窗口
driver.maximize_window()
# 全屏窗口
driver.fullscreen_window()
# 最小化窗口
driver.minimize_window()
# 获取窗口大小
size = driver.get_window_size()
width = size.get("width")
height = size.get("height")
# 设置窗口大小
driver.set_window_size(1024, 768)
# 获取窗口位置
position = driver.get_window_position()
x = position.get("x")
y = position.get("y")
# 设置窗口位置
driver.set_window_position(0, 0)
# 窗口截图
driver.save_screenshot("./image.png")
# 元素截图
driver.find_element(By.CSS_SELECTOR, "div").screenshot("./image.png")


def test_window():
    with webdriver.Firefox() as driver:
        driver.get("https://seleniumhq.github.io")
        wait = WebDriverWait(driver, 10)
        original_window = driver.current_window_handle
        assert len(driver.window_handles) == 1

        driver.find_element(By.LINK_TEXT, "new window").click()
        wait.until(EC.number_of_windows_to_be(2))

        for window_handle in driver.window_handles:
            if window_handle != original_window:
                driver.switch_to.window(window_handle)
                break

        wait.until(EC.title_is("SeleniumHQ Browser Automation"))


# 执行脚本
driver.execute_script("alert('hello')")


# 打印页面
print_options = PrintOptions()
print_options.page_ranges = ["1-2"]
base64code = driver.print_page(print_options)


# 提示框
def test_alert():
    element = driver.find_element(By.LINK_TEXT, "See an example alert")
    element.click()

    wait = WebDriverWait(driver, timeout=2)
    alert = wait.until(lambda d: d.switch_to.alert)

    text = alert.text
    alert.accept()
    assert text == "Sample alert"


# 提示框
def test_confirm():
    element = driver.find_element(By.LINK_TEXT, "See a sample confirm")
    driver.execute_script("arguments[0].click();", element)

    wait = WebDriverWait(driver, timeout=2)
    alert = wait.until(lambda d: d.switch_to.alert)
    text = alert.text
    alert.dismiss()
    assert text == "Are you sure?"


# 提示框
def test_prompt():
    element = driver.find_element(By.LINK_TEXT, "See a sample confirm")
    driver.execute_script("arguments[0].click();", element)

    wait = WebDriverWait(driver, timeout=2)
    alert = wait.until(lambda d: d.switch_to.alert)
    alert.send_keys("Selenium")
    text = alert.text
    alert.accept()
    assert text == "What is your tool of choice?"

动作

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.actions.action_builder import ActionBuilder
from selenium.webdriver.common.keys import Keys


driver = webdriver.Chrome()
clickable = driver.find_element(By.ID, "clickable")
# 暂停
ActionChains(driver).move_to_element(clickable).pause(1).click_and_hold().pause(1).send_keys("abc").perform()


# 释放所有操作
ActionBuilder(driver).clear_actions()


# 键盘动作
# 按键按下
ActionChains(driver).key_down(Keys.SHIFT).send_keys("abc").perform()
# 按键松开
ActionChains(driver).key_down(Keys.SHIFT).send_keys("a").key_up(Keys.SHIFT).send_keys("b").perform()
# 发送按键内容
text_input = driver.find_element(By.ID, "textInput")
ActionChains(driver).send_keys_to_element(text_input, "abc").perform()
ActionChains(driver).send_keys("abc").perform()


# 鼠标动作
clickable = driver.find_element(By.ID, "clickable")
# 单击并按住
ActionChains(driver).click_and_hold(clickable).perform()
# 单击
ActionChains(driver).click(clickable).perform()
# 右击
ActionChains(driver).context_click(clickable).perform()
# 双击
ActionChains(driver).double_click(clickable).perform()
# 移动到元素
ActionChains(driver).move_to_element(clickable).perform()
ActionChains(driver).move_to_element_with_offset(clickable, 8, 0).perform()
# 移动到位置
action = ActionBuilder(driver)
action.pointer_action.move_to_location(8, 0)
action.perform()
ActionChains(driver).move_by_offset(13, 15).perform()
# 拖拽元素
draggable = driver.find_element(By.ID, "draggable")
droppable = driver.find_element(By.ID, "droppable")
ActionChains(driver).drag_and_drop(draggable, droppable).perform()

等待

浏览器自动化最常见的挑战是确保 web 应用程序处于按需执行特定 Selenium 命令的状态。这些进程通常会以竞争状态结束,有时浏览器会先进入正确的状态(事情按预期工作),有时 Selenium 代码会先执行(事情不按预期运行)。这是测试不稳定的主要原因之一。

在驱动程序将控制权返回给代码之前,所有导航命令都会等待基于页面加载策略的特定 readyState 值(默认等待值为“complete”)。readyState 只关心加载 HTML 中定义的资源,但加载的 JavaScript 资源通常会导致网站发生变化,当代码准备执行下一个 Selenium 命令时,需要交互的元素可能还没有出现在页面上。
同样,在许多单页应用程序中,元素会动态添加到页面中,或者根据单击更改可见性。一个元素必须同时存在并显示在页面上,以便 Selenium 与之交互。

隐式等待
Selenium 有一种内置的自动等待元素的方法,称为隐式等待。隐式等待值可以通过浏览器选项中的超时功能或驱动程序方法设置。
这是一个全局设置,适用于整个会话的每个元素位置调用。默认值为 0,这意味着如果找不到元素,它将立即返回错误。如果设置了隐式等待,驱动程序将在返回错误之前等待提供值的持续时间。请注意,一旦找到元素,驱动程序将返回元素引用,代码将继续执行,因此较大的隐式等待值不一定会增加会话的持续时间。
警告:不要混合隐式和显式等待。这样做可能会导致不可预测的等待时间。例如,设置 10 秒的隐式等待和 15 秒的显式等待可能会导致 20 秒后发生超时。

显式等待
显式等待是添加到代码中的循环,它在应用程序退出循环并继续执行代码中的下一个命令之前,轮询应用程序以确定特定条件是否为真。如果在指定的超时值之前未满足条件,则代码将给出超时错误。由于应用程序不处于所需状态的方式有很多,因此显式等待是一个很好的选择,可以指定在每个需要等待的地方等待的确切条件。另一个很好的特性是,默认情况下,Selenium Wait 类会自动等待指定元素的存在。
from selenium import webdriver
from selenium.common import NoSuchElementException, ElementNotInteractableException
from selenium.webdriver.support.ui import Select, WebDriverWait
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()


# 隐式等待
driver.implicitly_wait(10)


# 显式等待
wait = WebDriverWait(driver, 10)
elem = wait.until(expected_conditions.presence_of_element_located(By.ID, "elem_id"))
elem = wait.until(expected_conditions.element_to_be_clickable(By.ID, "elem_id"))
elem = wait.until_not(expected_conditions.visibility_of_element_located(By.ID, "elem_id"))


wait = WebDriverWait(driver, timeout=2)
wait.until(lambda d: elem.is_displayed())


errors = [NoSuchElementException, ElementNotInteractableException]
wait = WebDriverWait(driver, timeout=2, poll_frequency=0.2, ignored_exceptions=errors)
wait.until(lambda d: elem.send_keys("Displayed") or True)

 

posted @ 2024-08-13 15:02  carol2014  阅读(4)  评论(0编辑  收藏  举报