selenium是一个用于web应用程序测试工具,selenium测试直接运行在浏览器中,就像真正的用户在操作一样,支持的浏览器包括IE(7,8,9,10,11),mozilla firefox,safari,google chrom,opera等,可使用java,python等多种语言编写用例脚本。
Selenium Python绑定提供了一个简单的API,可以使用Selenium WebDriver编写功能/验收测试。 通过Selenium Python API,您可以直观地访问Selenium WebDriver的所有功能。
Selenium Python绑定提供了一个方便的API来访问Selenium WebDrivers,如Firefox,Ie,Chrome,Remote等。目前支持的Python版本是2.7,3.5及更高版本
pip安装:
pip install selenium
wheel安装:
#下载wheel安装文件:https://pypi.python.org/pypi/selenium/#downloads pip install selenium-3.13.0-py2.py3-none-any.whl
chrome浏览器支持的chromeDriver驱动配置:
注意:此前必须安装好chrome浏览器
chromedriver下载地址: https://sites.google.com/a/chromium.org/chromedriver/downloads
首先查看chrome浏览器版本,然后选定支持浏览器版本的chromDriver选择适合的平台包进行下载,下载完后需要配置环境:
在windows系统中可以将chromedriver.exe文件直接拖到python的scripts目录中即可,也可以将路径加入到环境变量中。
在linux下需要将可执行文件配置到环境变量或将文件移动到属于环境变量的目录中
验证安装是否成功,可执行命令chromedriver,如果可以看到chromeDriver的版本号说明安装成功
使用python脚本测试:
from selenium import webdriver browser=webdriver.Chrome() #如果能弹出一个空白的chrome浏览器页面,说明配置成功
其他浏览器的驱动安装配置一样,附上其他浏览器的驱动下载链接地址:
Firefox: https://github.com/mozilla/geckodriver/releases
safari: https://webkit.org/blog/6900/webdriver-support-in-safari-10/
edge: https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
我们还可以使用phantomJS一个无界面的webkit浏览器引擎,它原生支持多种web标准:DOM操作,CSS选择器,JSON,Canvas以及SVG
下载地址: http://phantomjs.org/download.html
下载完成后,将PhantomJS可执行文件所在的路径配置到环境变量中,如在windows下降下载的文件解压之后打开会看到一个bin文件夹,里面包含一个可执行文件phantomjs.exe,我们需要将它直接放在配置好的环境变量路径下或者将它所在的路径配置到环境变量里,或直接将它复制到python的scripts文件夹下
测试安装:
(virtualenv-36) C:\Users\Administrator\PycharmProjects\untitled\pachong>phantomjs -v 2.1.1 #在python的terminal环境下执行命令phantomjs -v,如果能打印版本信息说明安装成功
Selenium支持PhantomJS,不过phantomJS官方说明已不再更新了,在selenium中使用phantomJS将弹出警告信息,建议使用chrome或firefox无头版,下面将重点介绍chrome和firefox
Selenium支持很多浏览器包括chrome、Firefox、Edge、Safari等,各浏览器初始化对象方法:
from selenium import webdriver #browser=webdriver.Firefox() browser=webdriver.Chrome() #browser=webdriver.Edge() #browser=webdriver.Safari() print(type(browser)) #返回的是一个WebDriver对象 <class 'selenium.webdriver.chrome.webdriver.WebDriver'>
WebDriver对象的方法和属性 :(获取节点方法在后续介绍)
from selenium import webdriver driver=webdriver.Chrome() driver.get('https://www.baidu.com') driver.execute_script("alert('are you sure');") #它基本可以实现JavaScript的所有功能
from selenium import webdriver browser=webdriver.Chrome() browser.get('http://selenium-python.readthedocs.io') browser.execute_script('window.open("https://www.baidu.com");') #在标签页打开URL browser.execute_script('window.open("https://www.taobao.com");') browser.back() #后退到前一个页面 browser.set_page_load_timeout(5) browser.forward() #前进到下一个页面 print(browser.name) print(browser.title) print(browser.current_url) print(browser.current_window_handle) print(browser.get_cookies()) print(type(browser)) chrome Selenium with Python — Selenium Python Bindings 2 documentation http://selenium-python.readthedocs.io/ CDwindow-243FD31239F20FCC0195DD522A60A0DA [{'domain': '.readthedocs.io', 'expiry': 1530766561, 'httpOnly': False, 'name': '_gid', 'path': '/', 'secure': False, 'value': 'GA1.2.1126774326.1530680157'}, {'domain': '.readthedocs.io', 'expiry': 1593752161, 'httpOnly': False, 'name': '_ga', 'path': '/', 'secure': False, 'value': 'GA1.2.2096958532.1530680157'}, {'domain': '.readthedocs.io', 'expiry': 1530680217, 'httpOnly': False, 'name': '_gat_rtfd', 'path': '/', 'secure': False, 'value': '1'}] <class 'selenium.webdriver.chrome.webdriver.WebDriver'>
获取页面截图:
from selenium import webdriver driver=webdriver.Chrome() driver.get('http://www.python.org') driver.save_screenshot('screenshot.png') #保持页面截图到当前路径 driver.quit()
将页面滚动到底部:
from selenium import webdriver driver=webdriver.Chrome() driver.get('http://www.python.org') #通过DOM中的window对象的scrollTo方法,将窗口位置滚动到指定位置,document.body.scrollHeight返回整个body的高度,所以页面将滚动到页面底部 driver.execute_script("window.scrollTo(0,document.body.scrollHeight);")
cookies操作:
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/7/5 16:19 # @Author : Py.qi # @File : test7.py # @Software: PyCharm from selenium import webdriver driver=webdriver.Chrome() driver.get('https://www.baidu.com') print(driver.get_cookies()) #获取所有cookies driver.add_cookie({'name':'name' ,'domain':'www.baidu.com','value':'germey'}) #添加cookie print(driver.get_cookies()) driver.delete_all_cookies() print(driver.get_cookies())
class selenium.webdriver.common.by.By
有各种策略来定位页面中的元素。你可以使用最适合你的情况。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
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/7/4 13:03 # @Author : Py.qi # @File : test2.py # @Software: PyCharm from selenium import webdriver from selenium.webdriver.common.by import By driver=webdriver.Chrome() driver.get('http://selenium-python.readthedocs.io/locating-elements.html#locating-elements') data=driver.find_element(By.CLASS_NAME,'simple') #driver.find_element(By.ID,'IDname') #获取ID标签定位元素 #driver.find_element(By.CSS_SELECTOR,'cssname')#CSS选择器定位元素 #driver.find_element(By.LINK_TEXT,'linktext') #链接文本定位元素 #driver.find_element(By.PARTIAL_LINK_TEXT,'linktext') #部分链接文件定位元素 #driver.find_element(By.NAME,'name') #属性名定位元素 #driver.find_element(By.TAG_NAME,'tagname') #标签名定位元素 print(data.text) #打印元素文本内容 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
#如获取多个,可是使用: data=driver.find_elements(By.CLASS_NAME,'simple')
除了使用上面的方法外,还可以使用更细致的方法定位元素:
通过Id定位:
当您知道元素的id属性时使用此选项。使用此策略,将返回id属性值与该位置匹配的第一个元素,如使用find_elements_by_id将返回多个匹配的元素。如果没有元素具有匹配的id 属性,NoSuchElementException则会引发
driver.find_element_by_id('idname') driver.find_elements_by_id('idname')
按名称定位:
当您知道元素的name属性时,请使用此选项。使用此策略,将返回名称属性值与位置匹配的第一个元素,如使用find_elements_by_name将返回多个匹配的元素。如果没有元素具有匹配的name 属性,NoSuchElementException则将引发
driver.find_element_by_name('name') driver.find_elements_by_name('name')
通过XPath定位:
XPath是用于在XML文档中定位节点的语言。由于HTML可以是XML(XHTML)的实现,因此Selenium用户可以利用这种强大的语言来定位其Web应用程序中的元素。XPath扩展了通过id或name属性定位的简单方法,并打开了各种新的可能性,例如在页面上查找第三个复选框。
使用XPath的主要原因之一是当您没有适合您要查找的元素的id或name属性时。您可以使用XPath以绝对术语或相对于具有id或name属性的元素来定位元素。XPath定位器也可以用来通过id和name之外的属性指定元素。
XPaths包含根(html)中所有元素的位置,因此可能会失败,只需对应用程序进行最轻微的调整。通过查找具有id或name属性的附近元素(理想情况下是父元素),可以根据关系找到目标元素。这不太可能改变,可以使您的测试更加健壮
driver.find_element_by_xpath("//from[1]") #查看第一个表单元素 friver.dind_element_by_xpath("//from[@id='loginform']") #查找id为loinform的表单元素
通过链接文本查找超链接:
当您知道锚标记中使用的链接文本时,请使用此选项。使用此策略,将返回链接文本值与位置匹配的第一个元素。如果没有元素具有匹配的链接文本属性,NoSuchElementException则将引发
按标签名称定位元素:
如果要按标签名称查找元素,请使用此选项。使用此策略,将返回具有给定标记名称的第一个元素。如果没有元素具有匹配的标记名称,NoSuchElementException 则将引发
driver.find_element_by_tag_name('h1')
按类名定位元素:
如果要按类属性名称定位元素,请使用此选项。使用此策略,将返回具有匹配类属性名称的第一个元素。如果没有元素具有匹配的类属性名称,NoSuchElementException则将引发
driver.find_element_by_class_name('content')
通过CSS选择器定位元素:
当你想通过CSS选择器语法找到一个元素时使用它。使用此策略,将返回具有匹配的CSS选择器的第一个元素。如果没有元素具有匹配的CSS选择器,NoSuchElementException则会引发
driver.find_element_by_css_selector('p.content')
当我们通过上面 的方法定位到元素后返回的对象称为web元素对象,我们可以对元素对象再进行交互或继续查找等操作
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/7/4 13:55 # @Author : Py.qi # @File : test3.py # @Software: PyCharm from selenium import webdriver from selenium.webdriver.chrome.options import Options opt=Options() opt.add_argument('headless') driver=webdriver.Chrome(chrome_options=opt) driver.get('http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.remote.webelement') element=driver.find_element_by_id('module-selenium.webdriver.remote.webelement') print(element) print(type(element)) #返回一个webelement对象 <selenium.webdriver.remote.webelement.WebElement (session="dfaee65201abdf5a931306df6e7fe421", element="0.95256057244967-1")> <class 'selenium.webdriver.remote.webelement.WebElement'>
与页面交互,实现输出文本搜索功能,并打印搜索结果源码:
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/7/4 13:55 # @Author : Py.qi # @File : test3.py # @Software: PyCharm from selenium import webdriver driver=webdriver.Chrome() driver.get('http://www.cnblogs.com/zhangxinqi/') element=driver.find_element_by_id('q') #获取输入框元素 element.send_keys('python3之requests') #发送元素 button=driver.find_element_by_id('btnZzk') #获取搜索按钮 button.click() #发送搜索动作 data=driver.page_source print(driver.current_url) #打印URL print(data) print(type(element)) driver.close() http://zzk-s.cnblogs.com/s?w=blog%3Azhangxinqi%20python3%E4%B9%8Brequests <!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head> <meta charset="utf-8" /> <title> blog:zhangxinqi python3之requests - 博客园找找看</title>......
class selenium.webdriver.common.action_chains.ActionChains(driver)
在上面的实例中我们针对的是某个节点元素的操作,如果要对没有特定元素的对象操作如鼠标拖拽、键盘按键等,这些动作就称为动作链,selenium使用ActionChains()类来实现鼠标移动,鼠标按钮操作,按键操作和上下文菜单交互,悬停和拖放等
将元素拖拽到目标位置:
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()
执行鼠标操作的流程:
menu = driver.find_element_by_css_selector(".nav") #获取element对象 hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1") #获取点击对象 #创建鼠标对象 actions = ActionChains(driver) #移动鼠标到对象 actions.move_to_element(menu) #点击对象 actions.click(hidden_submenu) #执行操作 actions.perform()
class selenium.webdriver.common.alert.Alert(driver)
Alert内置支持处理弹窗对话框,方法:
import time from selenium import webdriver from selenium.webdriver.common.alert import Alert driver=webdriver.Chrome() driver.get('https://www.baidu.com') driver.execute_script("alert('确定');") #弹出窗口 time.sleep(2) print(driver.switch_to.alert.text) #获取alert文本 alert=Alert(driver).accept() #自动点击确定窗口
class selenium.webdriver.common.keys.Keys
selenium提供一个keys包来模拟所有的按键操作,下面我们介绍下一些常用的按键操作:
实现点击页面从python的pypi页面下载selenium源码包:
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/7/5 13:05 # @Author : Py.qi # @File : test5.py # @Software: PyCharm import requests from selenium import webdriver from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.action_chains import ActionChains driver=webdriver.Chrome() driver.get('https://pypi.org/') element=driver.find_element_by_id('search') #获取输入框 element.send_keys('selenium') #搜索selenium包 element.send_keys(Keys.ENTER) #按回车键 element_a=driver.find_element_by_link_text('selenium') #定位selenium包链接 ActionChains(driver).move_to_element(element_a).click(element_a).perform() #按左键点击链接执行 element_down=driver.find_element_by_link_text('Download files') #定位下载链接 ActionChains(driver).move_to_element(element_down).click(element_down).perform() #按左键点击链接 element_selenium=driver.find_element_by_link_text('selenium-3.13.0.tar.gz') #定位元素selenium下载包链接 data=element_selenium.get_attribute('href') #获取链接地址 with open('selenium-3.13.0.tar.gz','wb') as f: source=requests.get(data).content #请求下载链接地址获取二进制包数据 f.write(source) #写入数据 f.close() driver.quit()
目前,大多数Web应用程序都在使用AJAX技术。当浏览器加载页面时,该页面中的元素可能以不同的时间间隔加载。这使定位元素变得困难:如果DOM中尚未存在元素,则locate函数将引发ElementNotVisibleException异常。使用等待,我们可以解决这个问题。等待在执行的操作之间提供了一些松弛 - 主要是使用元素定位元素或任何其他操作。
Selenium Webdriver提供两种类型的等待 - 隐式和显式。 显式等待使WebDriver等待某个条件发生,然后再继续执行。 在尝试查找元素时,隐式等待会使WebDriver轮询DOM一段时间。
显示等待:
显示等待是根据定义的代码,用于在进一步执行代码之前等待某个条件发送,它提供了一些便捷方法,可以编写在仅需要等待的代码上,实现方法需要WebDriverWait与ExpectedCondition结合使用:
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/7/5 14:41 # @Author : Py.qi # @File : test6.py # @Software: PyCharm 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.Chrome() driver.get('https://www.taobao.com/') wait=WebDriverWait(driver,3) #设置监听driver等待时间3秒 input=wait.until(EC.presence_of_element_located((By.ID,'q'))) #设置等待条件为id为q的元素加载完成 button=wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'.btn-search'))) #设置等待条件为class名为btn-search的元素加载完成 print(input,button)
其他等待条件:
隐式等待:
当使用隐式等待执行测试的时候,如果Selenium没有在DOM中找到节点,将继续等待,超出设定时间后,则抛出找不到节点的异常。换句话说,当查找节点而节点并没有立即出现的时候,隐式等待将等待一段时间再查找DOM,默认的时间是0,调用driver的implicitly_wait()方法实现隐式等待:
from selenium import webdriver driver = webdriver.Firefox() driver.implicitly_wait(10) #隐式等待设置为10等待时间 driver.get("http://somedomain/url_that_delays_loading") myDynamicElement = driver.find_element_by_id("myDynamicElement")
所有webdriver代码中发生的异常:
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/7/5 16:19 # @Author : Py.qi # @File : test7.py # @Software: PyCharm from selenium import webdriver from selenium.common.exceptions import NoSuchElementException driver=webdriver.Chrome() driver.get('https://www.baidu.com') try: element=driver.find_element_by_id('test') print(element) except NoSuchElementException as e: print('元素不存在:',e) 元素不存在: Message: no such element: Unable to locate element: {"method":"id","selector":"test"} (Session info: chrome=67.0.3396.99) (Driver info: chromedriver=2.40.565498 (ea082db3280dd6843ebfb08a625e3eb905c4f5ab),platform=Windows NT 10.0.10240 x86_64)
# !/usr/bin/env python #coding:utf-8 import re import pymongo from selenium import webdriver from selenium.common.exceptions import TimeoutException from selenium.webdriver.common.by import By from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from urllib.parse import quote from selenium.common.exceptions import WebDriverException from pyquery import PyQuery as pq #链接mongodb数据库 client=pymongo.MongoClient(host='localhost',port=27017) db=client['taobao'] #定义无头chrome opt=webdriver.ChromeOptions() opt.add_argument('--headless') driver=webdriver.Chrome(chrome_options=opt) #定义页面等待时间 wait=WebDriverWait(driver,10) #定义搜索商品名 uname='iPad' #搜索商品 def search(): try: url = 'https://s.taobao.com/search?q=' + quote(uname) driver.get(url) total=wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#mainsrp-pager > div > div > div > div.total'))) except TimeoutException: return search() return total.text #实现翻页商品 def next_page(page): print('正在抓取第{}'.format(page)) try: if page >= 1: input=wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#mainsrp-pager > div > div > div > div.form > input'))) submit=wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'#mainsrp-pager > div > div > div > div.form > span.btn.J_Submit'))) input.clear() input.send_keys(page) submit.click() wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR,'#mainsrp-pager > div > div > div > ul > li.item.active > span'),str(page))) wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#mainsrp-itemlist .items .item'))) get_products() except TimeoutException: next_page(page) except WebDriverException as e: print('index_page:',e) #解析商品信息 def get_products(): #print('开始解析页面...') html = driver.page_source doc = pq(html, parser='html') items = doc('#mainsrp-itemlist .items .item').items() for i in items: product = { 'image': 'https:' + i.find('.pic .img').attr('data-src'), 'price': i.find('.price').text(), 'deal': i.find('.deal-cnt').text(), 'title': i.find('.title').text(), 'shop': i.find('.shop').text(), 'location': i.find('.location').text() #print(product) save_to_mongo(product) #保存到mongodb def save_to_mongo(result): try: if db['collection_taobao'].insert(result): print('保存到mongodb成功!',result) except Exception: print('保存到mongodb失败',result) #主函数调用 def main(): try: total=search() total=int(re.compile('(\d+)').search(total).group(1)) for i in range(1,total+1): next_page(i) finally: driver.quit() #执行函数入口 if __name__ == '__main__': main()
抓取头条图片:
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/7/6 11:16 # @Author : Py.qi # @File : toutiao.py # @Software: PyCharm import requests from selenium import webdriver from selenium.webdriver.common.by import By from selenium.common.exceptions import WebDriverException,TimeoutException from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.keys import Keys from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from pyquery import PyQuery as pq import time from PIL import Image from io import BytesIO from PIL import ImageFile ImageFile.LOAD_TRUNCATED_IMAGES = True opt=webdriver.ChromeOptions() opt.add_argument('--headless') driver=webdriver.Chrome(chrome_options=opt) wait=WebDriverWait(driver,10) def index_page(url,text): try: driver.get(url) insid=wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#rightModule > div.search-wrapper > div > div > div.tt-input.tt-input-group.tt-input-group--append > input'))) insid.clear() insid.send_keys(text) insid.send_keys(Keys.ENTER) driver.switch_to.window(driver.window_handles[1]) images=wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'body > div > div.y-box.container > div.y-left.index-middle > div.tabBar > ul > li:nth-child(3)'))) ActionChains(driver).move_to_element(images).click(images).perform() element=driver.find_element_by_id('footer') sum=0 while sum < 8: ActionChains(driver).move_to_element(element).send_keys(Keys.DOWN).perform() time.sleep(1) sum+=1 html=driver.page_source doc=pq(html,parser='html') items=doc('.index-middle .feedBox .sections .articleCard').items() for i in items: #print(i('.title-box a').attr('href')) img_url='https://www.toutiao.com/a' + str(i('.title-box a').attr('href')).split('/')[-2] driver.get(img_url) if driver.title == '404错误页': continue else: wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.bui-box'))) img_source=driver.page_source doc1=pq(img_source,parser='html') excent=doc1('.imageList .image-list .image-item').items() for item in excent: image_url=item('.image-item-inner a').attr('href') image_name='D:\images\\' + image_url.split('/')[-1] + '.jpg' content=requests.get(image_url).content im=Image.open(BytesIO(content)) im.save(image_name) im.close() print('保存图片成功',image_name) except TimeoutException: print('超时') except WebDriverException: print('driverError') except Exception as e: print(e) def main(): url='https://www.toutiao.com' context='街拍' index_page(url,context) if __name__ == '__main__': main()View Code
其他异常请查看官网文档: http://selenium-python.readthedocs.io/api.html#module-selenium.common.exceptions
其他详细使用方法参考官方文档: http://selenium-python.readthedocs.io