代码: // required jquery.min.js $(function() { var $current_tab_menu =…
Python: selenium使用基本步骤, webdriver 自动化, 模拟浏览器登录

- selenium是什么:一个自动化测试工具(大家都是这么说的)
- selenium应用场景:用代码的方式去模拟浏览器操作过程(如:打开浏览器、在输入框里输入文字、回车等),在爬虫方面很有必要
安装:
下载python的selenium安装包
你可以从这里 下载python的selenium安装包,但是更好的办法是用pip
来安装。 Python3.7
的标准库里就有现成的pip
工具,可以用pip
安装selenium:
pip install selenium
你可能会想用虚拟机来安装一个独立的Python
环境,Python的pyvenc功能和虚拟机基本上是一样的。
windows用户的详细说明
注意:你需要联网来完成这个安装
- 安装python3.7 安装地址
- 用
cmd.exe
开启命令行,并用下面的命令安装selenium
C:\Python34\Scripts\pip.exe install selenium
现在你可以用python
来运行你的测试脚本了。例如,如果你创建了一个Selenium脚本然后保存到文件C:\my_selenium_script.py
,然后运行它:
C:\Python34\python.exe C:\my_selenium_script.py
安装chromedriver:
https://chromedriver.chromium.org/downloads
基本步骤:
1、导入模块:
from selenium import webdriver # 启动浏览器需要用到 from selenium.webdriver.common.keys import Keys # 提供键盘按键支持(最后一个K要大写)
2、创建一个WebDriver实例:
driver = webdriver.Chrome("chromedriver驱动程序路径")
options = webdriver.ChromeOptions() options.add_argument( '--user-agent=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36') browser = webdriver.Chrome(executable_path='/var/www/html/selenium/chromedriver', chrome_options=options)
3、打开一个页面:
driver.get("http://www.python.org") # 这个时候chromedriver会打开一个Chrome浏览器窗口,显示的是网址所对应的页面
4、关闭页面
driver.close() # 关闭浏览器一个Tab # or driver.quit() # 关闭浏览器窗口
高级-查找元素/定位元素:
在打开页面和关闭页面中间,就是各种操作!而查找元素这一点,和爬虫常见的HTML页面解析,定位到具体的某个元素基本一样,只不过,调用者是driver
element = driver.find_element_by_name("q")
有多种策略可以在页面中定位元素。您可以根据自己的情况选择最合适的一种。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
查找多个元素(这些方法将返回一个列表):
- 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')
这些是按类可用的属性:
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"
通过XPath定位
XPath是用于在XML文档中定位节点的语言。由于HTML可以是XML(XHTML)的实现,因此Selenium用户可以利用这种强大的语言来定位Web应用程序中的元素。XPath扩展了(同时支持)通过id或name属性进行定位的简单方法,并开辟了各种新的可能性,例如在页面上定位了第三个复选框。
使用XPath的主要原因之一是当您没有想要查找的元素的合适的id或name属性时。您可以使用XPath以绝对术语(不建议使用)定位元素,也可以相对于具有id或name属性的元素定位。XPath定位器还可用于通过id和name以外的属性指定元素。
绝对XPath包含来自根(html)的所有元素的位置,因此,仅对应用程序进行一点点调整就可能导致失败。通过查找具有id或name属性的附近元素(最好是父元素),您可以根据关系找到目标元素。这种更改的可能性要小得多,并且可以使您的测试更可靠。
例如,考虑以下页面来源:
<html>
<body>
<form id="loginForm">
<input name="username" type="text" />
<input name="password" type="password" />
<input name="continue" type="submit" value="Login" />
<input name="continue" type="button" value="Clear" />
</form>
</body>
<html>
表单元素可以这样定位:
login_form = driver.find_element_by_xpath("/html/body/form[1]")
login_form = driver.find_element_by_xpath("//form[1]")
login_form = driver.find_element_by_xpath("//form[@id='loginForm']")
- 绝对路径(如果仅对HTML进行少许更改,则会中断)
- HTML中的第一个表单元素
- 具有名为id的属性和值为loginForm的表单元素
username元素可以这样定位:
username = driver.find_element_by_xpath("//form[input/@name='username']")
username = driver.find_element_by_xpath("//form[@id='loginForm']/input[1]")
username = driver.find_element_by_xpath("//input[@name='usern
- 具有输入子元素的第一个表单元素,该子元素具有名为name的属性和值为username的属性
- 表单元素的第一个输入子元素,其属性名为 id,值为loginForm
- 第一个输入元素具有名为“ name”的属性和值 username
“清除”按钮元素可以这样定位:
clear_button = driver.find_element_by_xpath("//input[@name='continue'][@type='button']")
clear_button = driver.find_element_by_xpath("//form[@id='loginForm']/input[4]")
- 输入属性名称为name且值继续,属性名称为type且值按钮
- form元素的第四个输入子元素,其属性名为 id,值为loginForm
这些示例涵盖了一些基础知识,但是为了了解更多信息,建议您参考以下内容:
- W3Schools XPath教程
- W3C XPath建议
- XPath教程 -带有交互式示例。
还有两个非常有用的附加组件,可以帮助发现元素的XPath:
- XPath Checker-建议使用XPath,可用于测试XPath结果。
- Firebug -XPath建议只是该非常有用的附件的许多强大功能之一。
- XPath Helper-适用于Google Chrome
通过链接文本查找超链接
例如,考虑以下页面来源:
<html>
<body>
<p>Are you sure you want to do this?</p>
<a href="continue.html">Continue</a>
<a href="cancel.html">Cancel</a>
</body>
<html>
continue.html链接可以这样定位:
continue_link = driver.find_element_by_link_text('Continue')
continue_link = driver.find_element_by_partial_link_text('Conti')
当您要通过CSS选择器语法查找元素时,请使用此选项。使用此策略,将返回具有匹配CSS选择器的第一个元素。如果没有元素具有匹配的CSS选择器,NoSuchElementException
则将引发a。
例如,考虑以下页面来源:
<html> <body> <p class="content">Site content goes here.</p> </body> <html>
“ p”元素可以这样定位:
content = driver.find_element_by_css_selector('p.content')
Sauce Labs 在CSS选择器方面有很好的文档。
高级-页面交互:
找到元素后,就是进行“交互”,如键盘输入(需提前导入模块)
element.send_keys(“some text”) # 往一个可以输入对象中输入“some text”
甚至
element.send_keys(Keys.RETURN) # 模拟键盘回车
一般来说,这种方式输入后会一直存在,而要清空某个文本框中的文字,就需要:
element.clear() # 清空element对象中的文字
from selenium import webdriver from selenium.webdriver.common.keys import Keys driver = webdriver.Firefox() driver.get("http://www.python.org") assert "Python" in driver.title elem = driver.find_element_by_name("q") elem.clear() elem.send_keys("pycon") elem.send_keys(Keys.RETURN) assert "No results found." not in driver.page_source driver.close()
上面的脚本可以保存到文件中(例如: -python_org_search.py),然后可以像这样运行:
python python_org_search.py
您正在运行的python应该已经安装了selenium模块。
这是使用unittest模块的修改后的示例。这是对python.org搜索功能的测试:
import unittest from selenium import webdriver from selenium.webdriver.common.keys import Keys class PythonOrgSearch(unittest.TestCase): def setUp(self): self.driver = webdriver.Firefox() def test_search_in_python_org(self): driver = self.driver driver.get("http://www.python.org") self.assertIn("Python", driver.title) elem = driver.find_element_by_name("q") elem.send_keys("pycon") elem.send_keys(Keys.RETURN) assert "No results found." not in driver.page_source def tearDown(self): self.driver.close() if __name__ == "__main__": unittest.main()
您可以从这样的外壳运行上述测试用例:
python test_python_org_search.py
.
----------------------------------------------------------------------
Ran 1 test in 15.566s
OK
以上结果表明测试已成功完成。
遍历示例
最初,所有必需的基本模块都已导入。该单元测试模块是内置Python基于Java的JUnit。该模块提供了组织测试用例的框架。该selenium.webdriver模块提供了所有的webdriver实现。当前支持的WebDriver实现是Firefox,Chrome,IE和Remote。该键类提供键在键盘像RETURN,F1,ALT等。
import unittest from selenium import webdriver from selenium.webdriver.common.keys import Keys
测试用例类继承自unittest.TestCase。从TestCase类继承是告诉unittest模块这是一个测试用例的方法:
class PythonOrgSearch(unittest.TestCase):
该的setUp是初始化的一部分,此方法将你要在这个测试用例类写的每一个测试函数之前被调用。在这里,您将创建Firefox WebDriver的实例。
def setUp(self):
self.driver = webdriver.Firefox()
这是测试用例方法。测试用例方法应始终以字符test开头。此方法内的第一行创建对在setUp方法中创建的驱动程序对象的本地引用。
def test_search_in_python_org(self):
driver = self.driver
该driver.get方法将定位在给定的URL的网页。WebDriver将等待页面完全加载(即,已触发“ onload”事件),然后再将控制权返回给测试或脚本。值得注意的是,如果您的页面在加载时使用了很多AJAX,则WebDriver可能不知道何时完全加载。
driver.get("http://www.python.org")
下一行是一个断言,以确认标题中包含“ Python”一词:
self.assertIn("Python", driver.title)
WebDriver提供了多种使用find_element_by_ *方法之一查找元素的 方法。例如,可以使用find_element_by_name 方法通过其name属性找到输入文本元素。查找元素的详细说明可在“ 查找元素”一章中 找到:
elem = driver.find_element_by_name("q")
接下来,我们要发送密钥,这类似于使用键盘输入密钥。可以使用从selenium.webdriver.common.keys导入的Keys类 发送特殊密钥:
elem.send_keys("pycon")
elem.send_keys(Keys.RETURN)
提交页面后,如果有搜索结果,则应按照搜索得到结果。为了确保找到一些结果,请声明:
assert "No results found." not in driver.page_source
该拆卸方法将每个测试方法之后被调用。这是执行所有清理操作的地方。在当前方法中,浏览器窗口关闭。您也可以调用quit方法而不是 close。该退出将退出整个浏览器,而关闭 将关闭一个标签,但如果它是唯一选项卡中打开,默认情况下大多数浏览器将完全退出:
def tearDown(self):
self.driver.close()
最后一行是一些运行测试套件的样板代码:
if __name__ == "__main__":
unittest.main()
将Selenium与远程WebDriver一起使用
要使用远程WebDriver,您应该正在运行Selenium服务器。要运行服务器,请使用以下命令:
java -jar selenium-server-standalone-2.x.x.jar
在运行Selenium服务器时,您可能会看到类似以下的消息:
15:43:07.541 INFO - RemoteWebDriver instances should connect to: http://127.0.0.1:4444/wd/hub
上一行说,您可以使用此URL连接到远程WebDriver。这里有些例子:
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
driver = webdriver.Remote(
command_executor='http://127.0.0.1:4444/wd/hub',
desired_capabilities=DesiredCapabilities.CHROME)
driver = webdriver.Remote(
command_executor='http://127.0.0.1:4444/wd/hub',
desired_capabilities=DesiredCapabilities.OPERA)
driver = webdriver.Remote(
command_executor='http://127.0.0.1:4444/wd/hub',
desired_capabilities=DesiredCapabilities.HTMLUNITWITHJS)
所需的功能是字典,因此可以使用显式指定值,而不是使用默认字典:
driver = webdriver.Remote(
command_executor='http://127.0.0.1:4444/wd/hub',
desired_capabilities={'browserName': 'htmlunit',
'version': '2',
'javascriptEnabled': True})
高级-等待页面加载(wait)
应用场景:含有ajax加载的page!因为在这种情况下,页面内的某个节点并不是在一开始就出现了,而在这种情况下,就不能“查找元素”,元素选择不到,就不好进行交互操作!
等待页面加载这两个模块经常是一起导入的:
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC
1. 休眠等待
添加休眠非常简单,只需要引入python的time包,调用其中的sleep()方法。
这一种休眠方式会强制休眠对应的时间长度,不管页面或元素是否显示,因此会出现影响运行效率的问题,长时间的休眠不建议使用。
用法:
# -*- coding:utf-8 -*- from selenium import webdriver import time time.sleep(0.1) # 休眠0.1秒 time.sleep(3) # 休眠3秒
2. 智能等待-隐式等待
通过添加implicitly_wait()方法就可以实现智能等待,其为是 webdirver 提供的一个超时等待,文档中的解释:隐式地等待一个元素被发现,或命令来完成。
当使用了隐式等待执行测试的时候,如果 WebDriver没有在 DOM中找到元素,将继续等待,超出设定时间后则抛出找不到元素的异常。
换句话说,当查找元素或元素并没有立即出现的时候,隐式等待将等待一段时间再查找 DOM。一旦设置了隐式等待,则它存在整个 WebDriver 对象实例的声明周期中,隐式的等到会让一个正常响应的应用的测试变慢,它将会在寻找每个元素的时候都进行等待,这样会增加整个测试执行的时间。
用法:
driver.implicitly_wait(30)
3. 智能等待-显示等待
WebDriverWait()类: webdirver 提供的方法。简单来说就是WebDriver每隔一段时间就对页面元素进行检测,直到达到设定条件或超过设定时间,默认会抛出NoSuchElementException的异常。
文档解释:
WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None) driver - WebDriver 的驱动程序(Ie, Firefox, Chrome 或远程) timeout - 超时时间,默认以秒为单位 poll_frequency - 休眠时间的间隔(步长)时间,默认为 0.5 秒 ignored_exceptions - 超时后的异常信息,默认情况下抛 NoSuchElementException 异常。
WebDriverWait()一般由 until()或 until_not()方法配合使用,下面是 until()和 until_not()方法的说明。 until(method, message=’’) 调用该方法提供的驱动程序作为一个参数,直到返回值不为 False。 until_not(method, message=’’) 调用该方法提供的驱动程序作为一个参数,直到返回值为 False。
文档中提供的实例
from selenium.webdriver.support.ui import WebDriverWait element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("someId")) is_disappeared = WebDriverWait(driver, 30, 1, (ElementNotVisibleException)).until_not(lambda x: x.find_element_by_id("someId").is_displayed())
同城WebDriverWait要和expected_conditions.py文件配合使用,expected_conditions.py提供了一系列用于元素判断的方法,按需使用对应的方法即可。
几个方法实例:
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By # 等待元素出现在DOM WebDriverWait(self._driver).until(EC.presence_of_element_located((By.ID, value))) # 等待元素显示在页面 WebDriverWait(self._driver,10).until(EC.visibility_of_element_located((By.NAME, value))) # 等待元素从页面消失 WebDriverWait(self._driver, 10, 0.2).until_not(EC.visibility_of_element_located((By.CLASS_NAME, value)))) # 等待页面的title显示 WebDriverWait(self._driver, 5,0.2).until(EC.title_contains(title))
WebDriverWait
wait模块的WebDriverWait类是显性等待类,先看下它有哪些参数与方法:
selenium.webdriver.support.wait.WebDriverWait(类) __init__ driver: 传入WebDriver实例,即我们上例中的driver timeout: 超时时间,等待的最长时间(同时要考虑隐性等待时间) poll_frequency: 调用until或until_not中的方法的间隔时间,默认是0.5秒 ignored_exceptions: 忽略的异常,如果在调用until或until_not的过程中抛出这个元组中的异常, 则不中断代码,继续等待,如果抛出的是这个元组外的异常,则中断代码,抛出异常。默认只有NoSuchElementException。 until method: 在等待期间,每隔一段时间调用这个传入的方法,直到返回值不是False message: 如果超时,抛出TimeoutException,将message传入异常 until_not 与until相反,until是当某元素出现或什么条件成立则继续执行, until_not是当某元素消失或什么条件不成立则继续执行,参数也相同,不再赘述。 method message
看了以上内容基本上很清楚了,调用方法如下:
WebDriverWait(driver, 超时时长, 调用频率, 忽略异常).until(可执行方法, 超时时返回的信息)
这里需要特别注意的是until或until_not中的可执行方法method参数,很多人传入了WebElement对象,如下:
WebDriverWait(driver, 10).until(driver.find_element_by_id('kw')) # 错误
这是错误的用法,这里的参数一定要是可以调用的,即这个对象一定有 __call__()
方法,否则会抛出异常:
TypeError: 'xxx' object is not callable
在这里,你可以用selenium提供的 expected_conditions
模块中的各种条件,也可以用WebElement的 is_displayed()
、is_enabled()
、is_selected()
方法,或者用自己封装的方法都可以,那么接下来我们看一下selenium提供的条件有哪些:
expected_conditions
expected_conditions类所提供的预期条件判断的方法如下:
- title_is(title):预期页面标题匹配title
- title_contains(title):预期页面标题包含title
- presence_of_element_located(locator):预期指定位置的元素出现在DOM中
- url_contains(url):预期url包含在当前页面的url中
- url_to_be(url):预期url与当前页面url完全匹配
- url_changes(url):预期url不等于当前页面url
- visibility_of_element_located(locator):预期指定位置的元素可显示出来
- visibility_of(element):预期指定元素对象可见
- text_to_be_present_in_element(locator, text_):预期指定文本与指定元素的文本相同
- text_to_be_present_in_element_value(locator, text_):预期指定文本与指定元素的属性value值相同
- frame_to_be_available_and_switch_to_it(locator):预期指定的iframe是可以被切换的,并且自动切换到iframe中
- invisibility_of_element_located(locator):预期指定元素即不可见也不存在DOM中。
- element_to_be_clickable(locator):预期指定位置的元素是可见,并且可被点击的。
- element_to_be_selected(element):预期指定元素是已选中的
- element_located_to_be_selected(locator):预期指定位置的元素是已
- alert_is_present():预期当前存在alert弹窗
上面是所有17个condition,与until、until_not组合能够实现很多判断,如果能自己灵活封装,将会大大提高脚本的稳定性。
今天就分享这些内容,有什么问题可以留言给我交流,希望能帮助到有需要的同学。
- 中文:https://selenium-python-zh.readthedocs.io/en/latest/getting-started.html
- 英文:https://selenium-python.readthedocs.io/installation.html
- 官方API文档:https://seleniumhq.github.io/selenium/docs/api/py/api.html
本文:Python: selenium使用基本步骤, webdriver 自动化, 模拟浏览器登录