selenium

Selenium

Se enium 一个 自动化测试工具,利用它可以驱动浏览器执行特定的动作,如点击、下拉等操作,同时还可以获取浏览器当前呈现的页面的源代码 ,做到可见即可爬。

参考文档:

Selenium with Python中文翻译文档

selenium + python 中文文档

1. 安装

参考文档:

安装

安装

2. 快速入门

参考文档:

快速入门

开始

使用步骤:

  1. 导包
  2. 初始化浏览器对象
  3. 请求页面
  4. 与页面交互
  5. 关闭浏览器对象

3. 初始化浏览器对象

Se lenium 支持非常多的浏览器,如 hrome Firefox dge ,还有 Android Black.Berry 等手机端的浏览器。另外,也支持无界面浏览器 PhantomJS。

webdriver.Firefox
webdriver.FirefoxProfile
webdriver.Chrome
webdriver.ChromeOptions
webdriver.Ie
webdriver.Opera
webdriver.PhantomJS
webdriver.Remote
webdriver.DesiredCapabilities
webdriver.ActionChains
webdriver.TouchActions
webdriver.Proxy

这样就完成了浏览器对象的初始化并将其赋值为 browser 接下来,我 要做的就是调用 browser 对象,让其执行各个动作以模拟浏览器操作。

4. 请求页面

可以用 get()方法来请求网页,参数传入链接 URL 即可。

driver.get("http://www.google.com")

5. 与页面交互

我们比较喜欢做的事情就是和页面交互,准确的说,是和页面里的HTML元素交互。

5.1. 查找元素

详情查看:https://selenium-python-zh.readthedocs.io/en/latest/locating-elements.html

https://python-selenium-zh.readthedocs.io/zh_CN/latest/4.元素定位/

在一个页面中有很多不同的策略可以定位一个元素。在你的项目中, 你可以选择最合适的方法去查找元素。Selenium提供了下列的方法给你:

  • find_element_by_id
  • find_element_by_name
  • find_element_by_xpath
  • find_element_by_link_text
  • find_element_by_partial_link_text
  • find_element_by_tag_name
  • find_element_by_class_name
  • find_element_by_css_selector

一次查找多个元素 (这些方法会返回一个list列表):

  • find_elements_by_name
  • find_elements_by_xpath
  • find_elements_by_link_text
  • find_elements_by_partial_link_text
  • find_elements_by_tag_name
  • find_elements_by_class_name
  • find_elements_by_css_selector

除了上述的公共方法,下面还有两个私有方法,在你查找也页面元素的时候也许有用。 他们是 find_element 和 find_elements 。

用法示例:

from selenium.webdriver.common.by import By

driver.find_element(By.XPATH, '//button[text()="Some text"]')
driver.find_elements(By.XPATH, '//button')

下面是 By 类的一些可用属性:

ID = "id"
XPATH = "xpath"
LINK_TEXT = "link text"
PARTIAL_LINK_TEXT = "partial link text"
NAME = "name"
TAG_NAME = "tag name"
CLASS_NAME = "class name"
CSS_SELECTOR = "css selector"

5.2. 填写表单

5.2.1. 文本框处理

文本框中输入一些内容:

element.send_keys("some text")

你还可以通过”Keys”类来模式输入方向键:

element.send_keys(" and some", Keys.ARROW_DOWN)

对于任何元素,他可能都叫 send_keys ,这就使得它可以测试键盘快捷键, 比如当你使用Gmail的时候。但是有一个副作用是当你输入一些文本时,这些 输入框中原有的文本不会被自动清除掉,相反,你的输入会继续添加到已存在文本之后。 你可以很方便的使用 clear 方法去清除input或者textarea元素中的内容:

element.clear()

5.2.2. 选择框处理

WebDriver的支持类包括一个叫做Select的类,他提供有用的方法处理这些内容:

Select(element)

WebDriver 也提供一些有用的方法来取消选择已经选择的元素:

select = Select(driver.find_element_by_id('id'))
select.deselect_all()

获得所以选项:

options = select.options

5.2.3. 提交表单

有一个方法就是去找到一个“submit” 按钮然后点击它:

# Assume the button has the ID "submit" :)
driver.find_element_by_id("submit").click()

或者,WebDriver对每一个元素都有一个叫做 “submit” 的方法,如果你在一个表单内的 元素上使用该方法,WebDriver会在DOM树上就近找到最近的表单,返回提交它。 如果调用的元素不再表单内,将会抛出NoSuchElementException异常:

element.submit()

5.3. 拖放

您可以使用拖放,无论是移动一个元素,或放到另一个元素内:

element = driver.find_element_by_name("source")
target = driver.find_element_by_name("target")

from selenium.webdriver import ActionChains
action_chains = ActionChains(driver)
action_chains.drag_and_drop(element, target).perform()

5.4.在窗口(window)和框架(frame)间移动

5.4.1.窗口间切换

方法一:**

现在的网页应用里没有页面框架或者只用一个窗口就包含了所有内容的已经很少了。WebDriver 支持在指定的窗口间移动,方法为switch_to_window

driver.switch_to_window("windowName")

现在所有的driver的调用都会指向这个给定的窗口,但是我们怎么知道窗口的名字是什么呢?可以看一看打开这个窗口的javascript脚本或者link链接:

<a href="somewhere.html" target="windowName">Click here to open a new window</a>

方法二:

传一个window handleswitch_to_window()方法,它就可以像这样迭代每一个打开的窗口:

for handle in driver.window_handles:
    driver.switch_to_window(handle)

5.4.2.切换到框架

你也可以在框架和框架之间切换 (or into iframes):

driver.switch_to_frame("frameName")

我们可以用.分离路径来访问子框架,并且可以指定它的索引:

driver.switch_to_frame("frameName.0.child")

这会跳到'frameName'框架内第一个名为'child'的子框架。All frames are evaluated as if from top.

一旦我们操作完了框架,我们可以通过下面的操作回到父框架:

driver.switch_to_default_content()

5.5.弹出对话框

Selenium内置支持处理弹出对话框,当你触发了弹框操作,你可以用下面的方法获得对话框元素:

alert = driver.switch_to_alert()

上述代码返回当前打开的对话框对象,有了这个对象 我们可以做确定、忽略、阅读提示文本或者甚至输入prompt,这个接口可以很好的操作alerts、confirms、prompts等对话框。更多内容参阅API文档

5.6.导航:历史记录和定位

前面我们可以使用get命令(driver.get("http://www.example.com"))导航到一个页面。如你所见,WebDriver有一些较小的,侧重任务的接口,导航是一个很有用的任务,要打开一个页面,你可以使用get方法:

driver.get("http://www.example.com")

要在浏览器的历史记录的后退或者前进:

driver.forward()
driver.back()

要记得这些函数完全依赖于底层驱动,如果你过去习惯某一个浏览器的运行状态,当切换到新的浏览器时,调用这些方法有可能会出现预料之外的情况。(原文:It’s just possible that something unexpected may happen when you call these methods if you’re used to the behaviour of one browser over another.)

5.7.Cookies

Before we leave these next steps。你可能会好奇如何使用cookie,首先你需要处在一个域名下,然后这样设置cookie:

# Go to the correct domain
driver.get("http://example.com")

# Now set the cookie. This one's valid for the entire domain
cookie = {'name':'foo','value':'bar'}
driver.add_cookie(cookie)

# And now output all the available cookies for the current URL
driver.get_cookies()

6.等待事件

现在很多Web应用都在使用AJAX技术。浏览器载入一个页面时,页面内的元素可能是在不同的时间载入的,这会加大定位元素的困难程度,因为元素不在DOM里,会抛出ElementNotVisibleException异常,使用waits,我们就可以解决这个问题。Waiting给(页面)动作的执行提供了一些时间间隔-通常是元素定位或者其他对元素的操作。

Selenium WebDriver提供了两类waits- 隐式和显式。显式的waits会让WebDriver在更深一步的执行前等待一个确定的条件触发,隐式的waits则会让WebDriver试图定位元素的时候对DOM进行指定次数的轮询。

6.1.强制等待(无条件等待)

使用方法:time.sleep(delay)

delay的单位为,delay设置多少秒页面就会等待多少秒(死等),这个方法很容易让线程挂掉,使程序抛异常,所以要慎用此方法。

time.sleep(5)

6.2.显式等待(有条件等待)

当等待的条件满足后(一般用来判断需要等待的元素是否加载出来),就继续下一步操作。等不到就一直等,如果在规定的时间之内都没找到,那么就跳出Exception。

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

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"))
    )
finally:
    driver.quit()

这段代码会等待10秒,如果10秒内找到元素则立即返回,否则会抛出TimeoutException异常,WebDriverWait默认每500毫秒调用一下ExpectedCondition直到它返回成功为止。ExpectedCondition类型是布尔的,成功的返回值就是true,其他类型的ExpectedCondition成功的返回值就是 not null

预期条件

自动化网页操作时,有许多频繁使用到的通用条件。下面列出的是每一个条件的实现。Selenium + Python 提供了许多方便的方法,因此你不需要自己编写expected_condition的类,或者创建你自己的通用包。

  • title_is
  • title_contains
  • presence_of_element_located
  • visibility_of_element_located
  • visibility_of
  • presence_of_all_elements_located
  • text_to_be_present_in_element
  • text_to_be_present_in_element_value
  • frame_to_be_available_and_switch_to_it
  • invisibility_of_element_located
  • element_to_be_clickable - 元素展示并且可用
  • staleness_of
  • element_to_be_selected
  • element_located_to_be_selected
  • element_selection_state_to_be
  • element_located_selection_state_to_be
  • alert_is_present
from selenium.webdriver.support import expected_conditions as EC

wait = WebDriverWait(driver,10)
element = wait.until(EC.element_to_be_clickable((By.ID,'someid')))

expected_conditions模块包含了一系列预定义的条件来和WebDriverWait使用

6.3.隐式等待(无条件等待,在一个时间段内等待)

当我们要找一个或者一些不能立即可用的元素的时候,隐式waits会告诉WebDriver轮询DOM指定的次数,默认设置是0次。一旦设定,WebDriver对象实例的整个生命周期的隐式调用也就设定好了。

from selenium import webdriver

driver = webdriver.Firefox()
driver.implicitly_wait(10) # seconds
driver.get("http://somedomain/url_that_delays_loading")
myDynamicElement = driver.find_element_by_id('myDynamicElement')

以下根据stackoverflow网友回答添加:原问题链接 推荐一直用显式的,忘记还有隐式吧(Always use explicit wait. Forget that implicit wait exists)

显示waits: 明确的行为表现 在本地的selenium运行(你选择的编程语言) 可以在任何你能想到的条件下工作 返回成功或者超时 可以定义元素的缺失为条件 可以定制重试间隔,可以忽略某些异常

隐式waits: 不明确的行为表现,同一个问题依赖于不同的操作系统,不同的浏览器,不同的selenium版本会有各种不同的表现 在远程的selenium上运行(控制浏览器的那部分). 只能在寻找元素的函数上工作 返回找到元素或者(在超时以后)没有找到 如果检查元素缺失那么总是会等待到超时 除了时间啥都不能指定

如果是只需等待页面中的一个元素加载就用显示等待,等待整个网页加载就用隐式等待。

7.行为链

class selenium.webdriver.common.action_chains.ActionChains(driver)

ActionChains可以完成简单的交互行为,例如鼠标移动,鼠标点击事件,键盘输入,以及内容菜单交互。这对于模拟那些复杂的类似于鼠标悬停和拖拽行为很有用

当你在ActionChains对象上调用行为方法时,这些行为会存储在ActionChains对象的一个队列里。调用perform()时,这些动作就以他们队列的顺序来触发

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)
action.perform()

不管怎样,这些动作总是一个接一个按他们被调用的顺序执行。

  • click(on_element=None)

    点击一个元素

    参数: * on_element:要点击的元素,如果是None,点击鼠标当前的位置

  • click_and_hold(on_element=None)

    鼠标左键点击一个元素并且保持

    参数: * on_element:同click()类似

  • double_click(on_element=None)

    双击一个元素

    参数: * on_element:同click()类似

  • drag_and_drop(source, target)

    鼠标左键点击source元素,然后移动到target元素释放鼠标按键

    参数: source:鼠标点击的元素

    ​ target:鼠标松开的元素

  • drag_and_drop_by_offset(source, xoffset,yoffset)

    拖拽目标元素到指定的偏移点释放

    参数: source:点击的参数

    ​ xoffset:X偏移量

    ​ * yoffset:Y偏移量

  • key_down(value,element=None)

    只按下键盘,不释放。我们应该只对那些功能键使用(Contril,Alt,Shift)

    参数: value:要发送的键,值在Keys类里有定义 element:发送的目标元素,如果是None,value会发到当前聚焦的元素上

  • key_up(value,element=None)

    释放键。参考key_down的解释

  • move_by_offset(xoffset,yoffset)

    将当前鼠标的位置进行移动

    参数: xoffset:要移动的X偏移量,可以是正也可以是负

    ​ yoffset:要移动的Y偏移量,可以是正也可以是负

  • move_to_element(to_element)

    把鼠标移到一个元素的中间

    参数: *to_element:目标元素

  • move_to_element_with_offset(to_element,xoffset,yoffset)

    鼠标移动到元素的指定位置,偏移量以元素的左上角为基准

    参数: to_element:目标元素

    ​ xoffset:要移动的X偏移量

    ​ *yoffset:要移动的Y偏移量

  • perform()

    执行所有存储的动作

  • release(on_element=None)

    释放一个元素上的鼠标按键,

    参数: * on_element:如果为None,在当前鼠标位置上释放

  • send_keys(*keys_to_send)

    向当前的焦点元素发送键

    参数: * keys_to_send:要发送的键,修饰键可以到Keys类里找到

  • send_keys_to_element(element,*keys_to_send)

    向指定的元素发送键

8.警告框

class selenium.webdriver.common.alert.Alert(driver)

允许对警告框进行操作

使用这个类和警告提醒框进行交互,这个类包含了忽略、接受、输入以及从提示框内获取文本的方法

  • accept()

    确认提示框,用法:

    Alert(driver).accept() #Confirm a alert dialog
    
  • authenticate(username,password)

    向一个认证的对话框发送用户名和密码,会自动点击确认:

    driver.switch_to.alert.authenticate('cheese','secretGouda')
    
    

    参数: username:username区域要填写的字符串 password:password区域要填写的字符串

  • dismiss()

    忽略弹框

  • send_keys()

    弹框中输入字符

    name_prompt = Alert(driver)
    name_prompt.send_keys("Willian Shakephere")
    name_prompt.accept()
    
  • .text

    读取弹框的提示字符

    alert_text = Alert(driver).text
    self.assertEqual("Do you wish to quit?",alert_text)
    

9.特殊字符(Keys)

class selenium.webdriver.common.keys.Keys

下面是一些特殊字符的代码:

ADD = u'\ue025'

ALT = u'\ue00a'

ARROW_DOWN = u'\ue015'

ARROW_LEFT = u'\ue012'

ARROW_RIGHT = u'\ue014'

ARROW_UP = u'\ue013'

BACKSPACE = u'\ue003'

BACK_SPACE = u'\ue003'

CANCEL = u'\ue001'

CLEAR = u'\ue005'

COMMAND = u'\ue03d'

CONTROL = u'\ue009'

DECIMAL = u'\ue028'

DELETE = u'\ue017'

DIVIDE = u'\ue029'

DOWN = u'\ue015'

END = u'\ue010'

ENTER = u'\ue007'

EQUALS = u'\ue019'

ESCAPE = u'\ue00c'

F1 = u'\ue031'

F10 = u'\ue03a'

F11 = u'\ue03b'

F12 = u'\ue03c'

F2 = u'\ue032'

F3 = u'\ue033'

F4 = u'\ue034'

F5 = u'\ue035'

F6 = u'\ue036'

F7 = u'\ue037'

F8 = u'\ue038'

F9 = u'\ue039'

HELP = u'\ue002'

HOME = u'\ue011'

INSERT = u'\ue016'

LEFT = u'\ue012'

LEFT_ALT = u'\ue00a'

LEFT_CONTROL = u'\ue009'

LEFT_SHIFT = u'\ue008'

META = u'\ue03d'

MULTIPLY = u'\ue024'

NULL = u'\ue000'

NUMPAD0 = u'\ue01a'

NUMPAD1 = u'\ue01b'

NUMPAD2 = u'\ue01c'

NUMPAD3 = u'\ue01d'

NUMPAD4 = u'\ue01e'

NUMPAD5 = u'\ue01f'

NUMPAD6 = u'\ue020'

NUMPAD7 = u'\ue021'

NUMPAD8 = u'\ue022'

NUMPAD9 = u'\ue023'

PAGE_DOWN = u'\ue00f'

PAGE_UP = u'\ue00e'

PAUSE = u'\ue00b'

RETURN = u'\ue006'

RIGHT = u'\ue014'

SEMICOLON = u'\ue018'

SEPARATOR = u'\ue026'

SHIFT = u'\ue008'

SPACE = u'\ue00d'

SUBTRACT = u'\ue027'

TAB = u'\ue004'

UP = u'\ue013'

10.异常

所有的页面驱动代码里都可能抛出异常。

  • exception selenium.common.exceptions.ElementNotSelectableException(msg=None,screen=None,stacktrace=None)

    基于 selenium.common.exceptions.InvalidElementStateException

    当试图选中一个不能选中的元素时抛出 例如,选中一个script元素

  • exception selenium.common.exceptions.ElementNotVisibleException(msg=None,screen=None,stacktrace=None)

    基于 selenium.common.exceptions.InvalidElementStateException

    当DOM上存在元素但是不可用时,它是不可以进行交互的

    最常见的场景是试图点击或者阅读一个隐藏的元素

  • exception selenium.common.exceptions.ErrorInResponseException(response,msg)

    基于 selenium.common.exception.WebDriverException

    服务端发生错误

    这个异常可能会在 和 firefox扩展或者远程驱动服务交互时产生

  • exception selenium.common.exceptions.ImeActivationFailedException(msg=None,screen=None,stacktrace=None)

    基于 selenium.common.exceptions.WebDriverException

    激活一个 IME引擎失败

  • exception selenium.common.exceptions.ImeNotAvailableException(msg=None,screen=None,stacktrace=None)

    基于 selenium.common.exceptions.WebDriverException

    IME支持不可用。 如果 机器上IME支持不可用,这个异常会在所有和IME相关的方法里抛出

  • exception selenium.common.exceptions.InvalidCookieDomainException(msg=None, screen=None, stacktrace=None)

    基于:selenium.common.exceptions.WebDriverException

    试图在一个和当前不同的域名下添加cookie

  • exception selenium.common.exceptions.InvalidElementStateException(msg=None, screen=None, stacktrace=None)

    基于:selenium.common.exceptions.WebDriverException

    元素状态无效

  • exception selenium.common.exceptions.InvalidSelectorException(msg=None, screen=None, stacktrace=None)

    基于:selenium.common.exceptions.NoSuchElementException

    选择器用来寻找元素,但返回的不是一个 WebElement时。 目前只会在XPath表达式选择器里产生,XPath表达式语法错误或者没有选择WebElement时(例:count(//input))

  • exception selenium.common.exceptions.InvalidSwitchToTargetException(msg=None, screen=None, stacktrace=None)

    基于:selenium.common.exceptions.WebDriverException

    要切换的窗口或者框架不存在时

  • exception selenium.common.exceptions.MoveTargetOutOfBoundsException(msg=None, screen=None, stacktrace=None)

    基于:selenium.common.exceptions.WebDriverException

    提供给ActionsChains move()方法的目标不可用。

  • exception selenium.common.exceptions.NoAlertPresentException(msg=None, screen=None, stacktrace=None)

    基于:selenium.common.exceptions.WebDriverException

    屏幕没有警告框时,切换到警告框

  • exception selenium.common.exceptions.NoSuchAttributeException(msg=None, screen=None, stacktrace=None)

    基于:selenium.common.exceptions.WebDriverException

    元素找不到这个属性。

    你可能会想在另外一个浏览器上检查某个属性是否存在,有些浏览器相同的属性有不同的属性名(IE8的 innerText和 Firefox的 textContent)

  • exception selenium.common.exceptions.NoSuchElementException(msg=None, screen=None, stacktrace=None)

    基于:selenium.common.exceptions.WebDriverException

    找不到元素

    如果你发现这个错误,你可能会想要检查下面的东西: 检查你find_by...函数里用的选择器 查找元素的时候页面上还没有这个元素

    (页面正在加载)请查阅selenium.webdriver.support.wait.WebDriverWait()来了解如何等待元素的出现

  • exception selenium.common.exceptions.NoSuchFrameException(msg=None, screen=None, stacktrace=None)

    基于:selenium.common.exceptions.InvalidSwitchToTargetException

    要切换的目标框架不存在

  • exception selenium.common.exceptions.NoSuchWindowException(msg=None, screen=None, stacktrace=None)

    基于:selenium.common.exceptions.InvalidSwitchToTargetException

    要切换的目标窗口不存在。

    要找到当前活动窗口的句柄,你可以用下面的方法来获取一个句柄列表:

    print(driver.window_handles)
    
  • exception selenium.common.exceptions.RemoteDriverServerException(msg=None, screen=None, stacktrace=None)

    基于:selenium.common.exceptions.WebDriverException

    当一个元素的引用变旧

    变旧的意思是这个元素不在出现在页面的DOM里

    可能出现这个异常的原因包括但不限于: 你不在同一个页面,或者你获取到元素之后页面被刷新了 元素被定位后 被移动了又重新加到屏幕上,这样元素就被重置了。典型的例子是javascript框架当值改变,节点就被重建了 *,元素所在的框架或者其他内容被刷新了

  • exception selenium.common.exceptions.TimeoutException(msg=None, screen=None, stacktrace=None)

    基于:selenium.common.exceptions.WebDriverException

    规定时间内一个命令没有执行完

  • exception selenium.common.exceptions.UnableToSetCookieException(msg=None, screen=None, stacktrace=None)

    基于:selenium.common.exceptions.WebDriverException

    驱动设置cookie失败

  • exception selenium.common.exceptions.UnexpectedAlertPresentException(msg=None, screen=None, stacktrace=None)

    基于:selenium.common.exceptions.WebDriverException

    预料之外的警告框。当一个警告框阻塞了webdriver,不能执行任何命令的时候。

  • exception selenium.common.exceptions.UnexpectedTagNameException(msg=None, screen=None, stacktrace=None)

    基于:selenium.common.exceptions.WebDriverException

    当一个支持的类没有拿到预料的web元素时

  • exception selenium.common.exceptions.WebDriverException(msg=None, screen=None, stacktrace=None)

    基于:exceptions.Exception

    基本的 webdriver 异常

11.页面对象

这章是对 页面对象设计模型的特别指导。一个页面对象代表了你要测试的用户接口交互的区域。

使用页面对象模型的好处: 可以写出能在多个测试案例里复用的代码 减少重复代码 * 如果用户接口更改,只需要在一个地方做相应修改即可

测试案例

下面这个测试案例测试了在python.org网页上搜索一个单词并确认有相应的搜索结果:

import unittest
from selenium import webdriver
import page

class PythonOrgSearch(unittest.TestCase):
    """一个简单展示页面对象如何工作的类"""

    def setUp(self):
        self.driver = webdriver.Firefox()
        self.driver.get("http://www.python.org")

    def test_search_in_python_org(self):
        """
        测试 python.org网站的搜索功能。搜索一个单词“pycon”然后验证某些结果会展示出来。
        注意这个测试不会在搜索结果页里寻找任何细节文本,它只会验证结果为非空
        """

        #载入主页面,这个例子里是 Python.org的首页
        main_page = page.MainPage(self.driver)
        #检查页面的标题是否包含"python"单词
        assert main_page.is_title_matches(), "python.org title doesn't match."
        #将搜索框的文本设置为"pycon"
        main_page.search_text_element = "pycon"
        main_page.click_go_button()
        search_results_page = page.SearchResultsPage(self.driver)
        #验证结果页非空
            assert search_results_page.is_results_found(), "No results found."

    def tearDown(self):
        self.driver.close()

if __name__ == "__main__":
    unittest.main()

页面对象类

页面对象模型旨在给每一个Web页面创造一个对象。运用这个技术我们可以在测试代码和技术实现之间创建一个分离层,page.py会是这样的:

from element import BasePageElement
from locators import MainPageLocators

class SearchTextElement(BasePageElement):
    """这个类从指定的定位器里获取到搜索文本"""

    #已经输入搜索字符串的搜索框的定位器
    locator = 'q'


class BasePage(object):
    """初始化所有页面都会调用的基本页类"""

    def __init__(self, driver):
        self.driver = driver


class MainPage(BasePage):
    """主页操作方法放这里"""

    #定义一个变量存放检索文本
    search_text_element = SearchTextElement()

    def is_title_matches(self):
        """验证硬编码字符"python"出现在页面标题里"""
        return "Python" in self.driver.title

    def click_go_button(self):
        """触发搜索功能"""
        element = self.driver.find_element(*MainPageLocators.GO_BUTTON)
        element.click()


class SearchResultsPage(BasePage):
    """搜索结果页操作方法放这里"""

    def is_results_found(self):
        # 或许应该在具体的页面元素里搜索文本,不过目前为止这样运行没什么问题
        return "No results found." not in self.driver.page_source

页面元素

element.py类大致是这样的:

from selenium.webdriver.support.ui import WebDriverWait


class BasePageElement(object):
    """初始化每个页面对象类的基本页类"""

    def __set__(self, obj, value):
        """用给定的值设置文本"""
        driver = obj.driver
        WebDriverWait(driver, 100).until(
            lambda driver: driver.find_element_by_name(self.locator))
        driver.find_element_by_name(self.locator).send_keys(value)

    def __get__(self, obj, owner):
        """从具体的对象里获取文本"""
        driver = obj.driver
        WebDriverWait(driver, 100).until(
            lambda driver: driver.find_element_by_name(self.locator))
        element = driver.find_element_by_name(self.locator)
        return element.get_attribute("value")

定位器

One of the practices is to separate the locator strings from the place where they are being used.在这个例子里,同页面的定位器是同一个类

The locators.py will look like this:

from selenium.webdriver.common.by import By

class MainPageLocators(object):
    """一个主页面定位器类,所有的页面定位器应该来自这里"""
    GO_BUTTON = (By.ID, 'submit')

class SearchResultsPageLocators(object):
    """一个搜索结果定位器类,所有搜索结果定位器应该来自这里"""
    pass

12.其他

12.1.怎么滚动到页面的底部?

相关链接:http://blog.varunin.com/2011/08/scrolling-on-pages-using-selenium.html

你可以使用execute_script方法来在载入的页面上执行JS,因此,你可以调用JS的API来滚动到页面的底部或者其他任意位置。

下面是一个滚动到底部的实例:

driver.execute_script("window.scrollTo(0,document.body.scrollHeight);")

DOM的窗口对象有一个 scrollTo 方法来在打开的窗口中滚动到任意位置, scrollHeight是所有元素的一个通用属性,document.body.scrollHeight是页面整个body的高度

12.2.怎么向文件上传表单上传文件?

选中元素,调用send_keys()方法,传递文件的路径。可以传递绝对路径或者相对测试脚本的路径。要注意windows和Unix系统路径名的差异

12.3.怎样给当前窗口截图?

使用webdriver提供的save_screenshot方法:

from selenium import webdriver

driver = webdriver.Firefox()
driver.get('http://www.python.org/')
driver.save_screenshot('screenshot.png')
driver.quit()
posted @   昵称已经被使用  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示