diff --git a/python/selenium.md b/python/selenium.md new file mode 100644 index 0000000..af1d333 --- /dev/null +++ b/python/selenium.md @@ -0,0 +1,575 @@ +- [selenium](#selenium) + - [Components](#components) + - [Driver](#driver) + - [WebDriver](#webdriver) + - [Getting Started](#getting-started) + - [安装](#安装) + - [常用操作](#常用操作) + - [开启浏览器会话](#开启浏览器会话) + - [通过webdriver执行操作](#通过webdriver执行操作) + - [请求浏览器信息](#请求浏览器信息) + - [指定等待策略](#指定等待策略) + - [获取页面上的元素](#获取页面上的元素) + - [针对页面上的元素执行操作](#针对页面上的元素执行操作) + - [访问元素上的信息](#访问元素上的信息) + - [关闭会话](#关闭会话) + - [提交表单样例](#提交表单样例) + - [Driver](#driver-1) + - [Browser Options](#browser-options) + - [browserName](#browsername) + - [Driver Service](#driver-service) + - [使用默认service实例](#使用默认service实例) + - [指定driver port](#指定driver-port) + - [Remote Web Driver](#remote-web-driver) + - [元素交互](#元素交互) + - [文件上传](#文件上传) + - [文件定位](#文件定位) + - [在整个dom中进行查找](#在整个dom中进行查找) + - [基于已定位的元素进行查找](#基于已定位的元素进行查找) + - [css选择器](#css选择器) + - [查找所有匹配的元素](#查找所有匹配的元素) + - [同web元素进行交互](#同web元素进行交互) + - [click](#click) + - [send\_keys](#send_keys) + - [clear](#clear) + - [获取元素信息](#获取元素信息) + - [is\_displayed](#is_displayed) + - [is\_enabled](#is_enabled) + - [is\_selected](#is_selected) + - [tag\_name](#tag_name) + - [元素位置和大小](#元素位置和大小) + - [获取css的值](#获取css的值) + - [获取文本内容](#获取文本内容) + - [获取元素属性](#获取元素属性) + - [浏览器交互](#浏览器交互) + - [获取当前页签的title](#获取当前页签的title) + - [获取当前url](#获取当前url) + - [浏览器导航](#浏览器导航) + - [跳转到页面](#跳转到页面) + - [返回到上一个页签](#返回到上一个页签) + - [forward](#forward) + - [刷新当前页签](#刷新当前页签) + - [alert](#alert) + - [confirm](#confirm) + - [prompt](#prompt) + - [新增cookie](#新增cookie) + - [iframe](#iframe) + - [winodws/tab 交互](#winodwstab-交互) + - [获取当前窗口句柄](#获取当前窗口句柄) + - [切换窗口句柄](#切换窗口句柄) + - [创建新窗口/tab](#创建新窗口tab) + - [关闭tab](#关闭tab) + - [关闭会话](#关闭会话-1) + - [获取窗口大小](#获取窗口大小) + - [设置窗口大小](#设置窗口大小) + - [获取窗口位置](#获取窗口位置) + - [设置窗口位置](#设置窗口位置) + - [最大化窗口](#最大化窗口) + - [最小化窗口](#最小化窗口) + - [全屏窗口](#全屏窗口) + - [截屏](#截屏) + - [为元素截屏](#为元素截屏) + - [执行js脚本](#执行js脚本) + - [打印页面](#打印页面) + + +# selenium +## Components +### Driver +Driver负责控制实际的浏览器,大多数driver是由浏览器供应商提供的。 + +### WebDriver +WebDriver通过Driver和浏览器通信,通过driver, webDriver将命令发送给浏览器,并且通过driver收到浏览器的返回信息。 + +> Drvier和浏览器运行在同一个操作系统上,WebDriver和`drvier&浏览器`可能并不运行在同一系统上。WebDriver会远程调用driver,driver再调用处于同一系统的浏览器。 + +## Getting Started +### 安装 +```bash +pip install selenium +``` +### 常用操作 +#### 开启浏览器会话 +```py +driver = webdriver.Chrome() +``` +#### 通过webdriver执行操作 +```py +driver.get("https://www.selenium.dev/selenium/web/web-form.html") +``` + +#### 请求浏览器信息 +```py +# driver.title代表浏览器当前页签的标题 +title = driver.title +``` + +#### 指定等待策略 +再获取元素之前,需要确保元素存在于当前页面上,并且与元素进行交互时,必须确保当前元素是可交互的(页签加载需要时间)。 + +此时,可以通过自定义等待时间来解决。 +```py +driver.implicitly_wait(0.5) +``` + +#### 获取页面上的元素 +```py +text_box = driver.find_element(by=By.NAME, value="my-text") +submit_button = driver.find_element(by=By.CSS_SELECTOR, value="button") +``` + +#### 针对页面上的元素执行操作 +```py +text_box.send_keys("Selenium") +submit_button.click() +``` + +#### 访问元素上的信息 +```py +text = message.text +``` + +#### 关闭会话 +```py +driver.quit() +``` + +#### 提交表单样例 +```py +from selenium import webdriver +from selenium.webdriver.common.by import By + + +def test_eight_components(): + driver = webdriver.Chrome() + + driver.get("https://www.selenium.dev/selenium/web/web-form.html") + + title = driver.title + assert title == "Web form" + + driver.implicitly_wait(0.5) + + text_box = driver.find_element(by=By.NAME, value="my-text") + submit_button = driver.find_element(by=By.CSS_SELECTOR, value="button") + + text_box.send_keys("Selenium") + submit_button.click() + + message = driver.find_element(by=By.ID, value="message") + value = message.text + assert value == "Received!" + + driver.quit() +``` +## Driver +开启和关闭session代表着开启和关闭浏览器。 + +### Browser Options +对于remote driver sessions,需要为其指定options对象,指定的options对象将会决定使用远程的哪个浏览器。 + +每个浏览器都会有其独属的额外选项,可以为每个浏览器额外指定。 + +#### browserName +当使用options对象时,browserName选项会被默认指定: + +### Driver Service +Service用于管理local driver的启动和停止,service无法被用于remote webdriver session。 + +service允许指定driver的信息,例如driver位置和使用的端口号,也可以通过service指定日志信息。 + +#### 使用默认service实例 +```py +service = webdriver.ChromeService() +driver = webdriver.Chrome(service=service) +``` + +#### 指定driver port +如果想要driver运行在指定的端口,可以通过service进行指定。 +```py +service = webdriver.ChromeService(port=1234) +``` + +### Remote Web Driver +Selenium允许调用位于远程机器上的浏览器,需要远程机器上安装Selenium Grid。 +```py +options = webdriver.ChromeOptions() +driver = webdriver.Remote(command_executor=server, options=options) +``` + +## 元素交互 +### 文件上传 +通过元素的`send_keys`方法,支持支持文件上传。 +```py +file_input = driver.find_element(By.CSS_SELECTOR, "input[type='file']") +file_input.send_keys(upload_file) +driver.find_element(By.ID, "file-submit").click() +``` + +### 文件定位 +#### 在整个dom中进行查找 +可以通过调用`driver.find_element`来在整个dom中对元素进行查找,其会返回匹配的第一个元素 +```py +vegetable = driver.find_element(By.CLASS_NAME, "tomatoes") +``` +#### 基于已定位的元素进行查找 +如果想要在已经定位元素的子节点中进行查找,可以调用如下方法: +```py +fruits = driver.find_element(By.ID, "fruits") +fruit = fruits.find_element(By.CLASS_NAME,"tomatoes") +``` +#### css选择器 +selenium支持通过css选择器的语法来进行查找: +```py +fruit = driver.find_element(By.CSS_SELECTOR,"#fruits .tomatoes") +``` +#### 查找所有匹配的元素 +可以通过`find_elements`方法来获取所有匹配的元素,而不是第一个匹配的元素 +```py +plants = driver.find_elements(By.TAG_NAME, "li") +``` + +### 同web元素进行交互 +可以针对元素指定如下类型的交互 +- click(可使用任何元素) +- send_keys(只针对文本输入框或内容可编辑的元素) +- clear(只针对文本输入框或内容可编辑的元素) +- submit(只针对表单元素) +- select(只针对下拉框类型元素) + +#### click +```py +# Navigate to url +driver.get("https://www.selenium.dev/selenium/web/inputs.html") + +# Click on the element +driver.find_element(By.NAME, "color_input").click() +``` +#### send_keys +```py +# Navigate to url +driver.get("https://www.selenium.dev/selenium/web/inputs.html") + +# Clear field to empty it from any previous data +driver.find_element(By.NAME, "email_input").clear() + +# Enter Text +driver.find_element(By.NAME, "email_input").send_keys("admin@localhost.dev" ) +``` +#### clear +```py +# Navigate to url +driver.get("https://www.selenium.dev/selenium/web/inputs.html") + +# Clear field to empty it from any previous data +driver.find_element(By.NAME, "email_input").clear() +``` +### 获取元素信息 +#### is_displayed +```py +# Navigate to the url +driver.get("https://www.selenium.dev/selenium/web/inputs.html") + +# Get boolean value for is element display +is_email_visible = driver.find_element(By.NAME, "email_input").is_displayed() +``` +#### is_enabled +```py +# Navigate to url +driver.get("https://www.selenium.dev/selenium/web/inputs.html") + +# Returns true if element is enabled else returns false +value = driver.find_element(By.NAME, 'button_input').is_enabled() +``` +#### is_selected +```py +# Navigate to url +driver.get("https://www.selenium.dev/selenium/web/inputs.html") + +# Returns true if element is checked else returns false +value = driver.find_element(By.NAME, "checkbox_input").is_selected() +``` +#### tag_name +```py +# Navigate to url +driver.get("https://www.selenium.dev/selenium/web/inputs.html") + +# Returns TagName of the element +attr = driver.find_element(By.NAME, "email_input").tag_name +``` +#### 元素位置和大小 +```py +# Navigate to url +driver.get("https://www.selenium.dev/selenium/web/inputs.html") + +# Returns height, width, x and y coordinates referenced element +res = driver.find_element(By.NAME, "range_input").rect +``` +#### 获取css的值 +```py +# Navigate to Url +driver.get('https://www.selenium.dev/selenium/web/colorPage.html') + +# Retrieves the computed style property 'color' of linktext +cssValue = driver.find_element(By.ID, "namedColor").value_of_css_property('background-color') +``` +#### 获取文本内容 +```py +# Navigate to url +driver.get("https://www.selenium.dev/selenium/web/linked_image.html") + +# Retrieves the text of the element +text = driver.find_element(By.ID, "justanotherlink").text +``` +#### 获取元素属性 +```py +# Navigate to the url +driver.get("https://www.selenium.dev/selenium/web/inputs.html") + +# Identify the email text box +email_txt = driver.find_element(By.NAME, "email_input") + +# Fetch the value property associated with the textbox +value_info = email_txt.get_attribute("value") +``` +## 浏览器交互 +### 获取当前页签的title +```py +String title = driver.getTitle(); +``` +### 获取当前url +```py +String url = driver.getCurrentUrl(); +``` +### 浏览器导航 +#### 跳转到页面 +```py +driver.get("https://www.selenium.dev/selenium/web/index.html") +``` +#### 返回到上一个页签 +```py +driver.back() +``` +#### forward +```py +driver.forward() +``` +#### 刷新当前页签 +```py +driver.refresh() +``` +#### alert +```py +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 +alert.accept() +``` +#### confirm +```py +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() +``` +#### prompt +```py +element = driver.find_element(By.LINK_TEXT, "See a sample prompt") +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() +``` +### 新增cookie +```py +from selenium import webdriver + +driver = webdriver.Chrome() + +driver.get("http://www.example.com") + +# Adds the cookie into current browser context +driver.add_cookie({"name": "key", "value": "value"}) +``` +### iframe +想要与iframe中的内容进行交互,需要先移动到iframe区域 +```py + # Store iframe web element +iframe = driver.find_element(By.CSS_SELECTOR, "#modal > iframe") + + # switch to selected iframe +driver.switch_to.frame(iframe) + + # Now click on button +driver.find_element(By.TAG_NAME, 'button').click() +``` +### winodws/tab 交互 +#### 获取当前窗口句柄 +```py +driver.current_window_handle +``` +#### 切换窗口句柄 +可以通过`driver.switch_to.window(windows_handle)`来进行切换页签 +```py +from selenium import webdriver +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC + +with webdriver.Firefox() as driver: + # Open URL + driver.get("https://seleniumhq.github.io") + + # Setup wait for later + wait = WebDriverWait(driver, 10) + + # Store the ID of the original window + original_window = driver.current_window_handle + + # Check we don't have other windows open already + assert len(driver.window_handles) == 1 + + # Click the link which opens in a new window + driver.find_element(By.LINK_TEXT, "new window").click() + + # Wait for the new window or tab + wait.until(EC.number_of_windows_to_be(2)) + + # Loop through until we find a new window handle + for window_handle in driver.window_handles: + if window_handle != original_window: + driver.switch_to.window(window_handle) + break + + # Wait for the new tab to finish loading content + wait.until(EC.title_is("SeleniumHQ Browser Automation")) +``` +#### 创建新窗口/tab +```py + # Opens a new tab and switches to new tab +driver.switch_to.new_window('tab') + + # Opens a new window and switches to new window +driver.switch_to.new_window('window') +``` +#### 关闭tab +调用`driver.close`会关闭当前的页签 +```py + #Close the tab or window +driver.close() + + #Switch back to the old tab or window +driver.switch_to.window(original_window) +``` + +#### 关闭会话 +当不再使用浏览器会话后,应该调用`driver.quit()`方法。 + +如果未调用该方法或是调用该方法失败,将会导致driver进程和端口号一直不被释放。 + + +#### 获取窗口大小 +```py + # Access each dimension individually +width = driver.get_window_size().get("width") +height = driver.get_window_size().get("height") + + # Or store the dimensions and query them later +size = driver.get_window_size() +width1 = size.get("width") +height1 = size.get("height") +``` +#### 设置窗口大小 +```py +driver.set_window_size(1024, 768) +``` + +#### 获取窗口位置 +```py + # Access each dimension individually +x = driver.get_window_position().get('x') +y = driver.get_window_position().get('y') + + # Or store the dimensions and query them later +position = driver.get_window_position() +x1 = position.get('x') +y1 = position.get('y') +``` + +#### 设置窗口位置 +```py + # Move the window to the top left of the primary monitor +driver.set_window_position(0, 0) +``` +#### 最大化窗口 +```py +driver.maximize_window() +``` + +#### 最小化窗口 +```py +driver.minimize_window() +``` + +#### 全屏窗口 +```py +driver.fullscreen_window() +``` +#### 截屏 +```py +from selenium import webdriver + +driver = webdriver.Chrome() + +driver.get("http://www.example.com") + + # Returns and base64 encoded string into image +driver.save_screenshot('./image.png') + +driver.quit() +``` + +#### 为元素截屏 +```py +from selenium import webdriver +from selenium.webdriver.common.by import By + +driver = webdriver.Chrome() + +driver.get("http://www.example.com") + +ele = driver.find_element(By.CSS_SELECTOR, 'h1') + + # Returns and base64 encoded string into image +ele.screenshot('./image.png') + +driver.quit() +``` +#### 执行js脚本 +```py + # Stores the header element +header = driver.find_element(By.CSS_SELECTOR, "h1") + + # Executing JavaScript to capture innerText of header element +driver.execute_script('return arguments[0].innerText', header) +``` +#### 打印页面 +```py + from selenium.webdriver.common.print_page_options import PrintOptions + + print_options = PrintOptions() + print_options.page_ranges = ['1-2'] + + driver.get("printPage.html") + + base64code = driver.print_page(print_options) +```