selenium自动化测试python

一。环境部署

1.selenium安装 

pip3 install selenium

1.安装浏览器驱动

WebDriver 需要通过浏览器驱动来与浏览器交互,以下列出几种常用的浏览器驱动下载地址:

Chrome:

http://chromedriver.storage.googleapis.com/index.html

Firefox:
https://github.com/mozilla/geckodriver/releases

Edge:
https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver

Safari:
https://webkit.org/blog/6900/webdriver-support-in-safari-10

使用不同的浏览器,需要下载对应版本驱动,并且确保驱动文件如chromedriver.exe放到你的系统环境PATH中,这里我将它放到python安装目录下。D:\Python36\chromedriver.exe

selenium思维导图详细使用介绍:

二。元素定位:

 1 <!DOCTYPE html>
 2 <html lang="zh-CN">
 3 <body>
 4     <h1 class="head_title">你好,<span id="world">世界!</span></h1>
 5     <a href="https://www.kancloud.cn/@guanfuchang" target="_blank">我的看云首页</a>
 6     <br/>
 7     <br/>
 8     <div id="login_form" class="login">
 9         用户名:<input name="username" class="ptqa user_name" placeholder="用户名" value="Milton" required/>
10         密码:<input type="text" name="password" class="ptqa pwd" placeholder="密码" value="ptqa" required/>
11         地区:
12         <select class="city">
13             <option value="gz">广州</option>
14             <option value="fs">佛山</option>
15             <option value="mm">茂名</option>
16             <option value="hb">襄樊</option>
17         </select>
18 
19         <br>
20         <br>
21         <button>提交</button>
22         <br>
23 
24     </div>
25 </body>
26 </html>
环境准备
 1 在同个目录下创建一个find_location.py文件,初始化工作
 2 from selenium import webdriver
 3 import os
 4 
 5 # 创建Chrome驱动实例
 6 driver = webdriver.Chrome()
 7 
 8 # 启动浏览器并且导航到指定URL
 9 # 这里为了覆盖更多的元素定位,我自己编写了一个本地的hello.html文件。
10 file_path = 'file:///' + os.path.abspath('hello.html')
11 driver.get(file_path)
初始化工作
find_element_by_class_name(self, name):
find_elements_by_class_name(self, name):
# 定位class名称为“head_title"的元素
head_title = driver.find_element_by_class_name("head_title")
print(head_title.text)
通过class定位
find_element_by_id(self, id_):
find_elements_by_id(self, id_):
# 定位id为“world”的元素
world = driver.find_element_by_id("world")
print(world.text)
通过id定位
find_element_by_name(self, name):
find_elements_by_name(self, name):
# 定位name为“username”的元素
username = driver.find_element_by_name("username")
print(username.get_attribute("value"))
通过name属性定位
1 find_element_by_tag_name(self, name):
2 find_elements_by_tag_name(self, name):
3 # 定位标签为<button>的元素
4 submit_btn = driver.find_element_by_tag_name("button")
5 print(submit_btn.text)
通过标签名定位
 1 find_element_by_link_text(self, link_text):
 2 find_element_by_partial_link_text(self, link_text):
 3 
 4 # 定位链接文本完全匹配“我的看云首页”的元素
 5 kancloud = driver.find_element_by_link_text("我的看云首页")
 6 print(kancloud.get_attribute("href"))
 7 
 8 # 定位链接文本部分匹配“看云首页”的元素
 9 kancloud = driver.find_element_by_partial_link_text("看云首页")
10 print(kancloud.get_attribute("href"))
通过链接文本定位
 1 find_element_by_xpath(self, xpath):
 2 find_elements_by_xpath(self, xpath):
 3 
 4 # xpath定位,相对路径定位用户名输入框
 5 username = driver.find_element_by_xpath("//body/div/input")
 6 print(username.get_attribute("value"))
 7 
 8 # xpath定位,相对路径与属性结合 定位密码输入框
 9 password = driver.find_element_by_xpath("//input[@name='password']")
10 print(password.get_attribute("value"))
11 
12 # xpath定位,多个属性结合 定位密码输入框
13 password = driver.find_element_by_xpath("//input[@name='password'][@type='text']")
14 print(password.get_attribute("value"))
通过xpath定位
 1 find_element_by_css_selector(self, css_selector):
 2 find_elements_by_css_selector(self, css_selector):
 3 
 4 # css选择器,标签+属性 定位用户名输入框
 5 username = driver.find_element_by_css_selector("input[name='username']")
 6 print(username.get_attribute("value"))
 7 
 8 复制
 9 # css选择器,标签+class类名 定位用户名输入框
10 username = driver.find_element_by_css_selector("input.user_name")
11 print(username.get_attribute("value"))
12 
13 # css选择器,标签+多个class类名,定位密码输入框,注意不要空格,空格代表下一级子元素
14 password = driver.find_element_by_css_selector("input.ptqa.pwd")
15 print(password.get_attribute("value"))
16 
17 # css选择器,id+多个class类名,定位密码输入框
18 password = driver.find_element_by_css_selector("#login_form .ptqa.pwd")
19 print(password.get_attribute("value"))
20 
21 # css选择器,多级class类名,定位密码输入框
22 password = driver.find_element_by_css_selector(".login .ptqa.pwd")
23 print(password.get_attribute("value"))
24 
25 # css选择器,class类名+属性,定位密码输入框
26 password = driver.find_element_by_css_selector(".login .ptqa[name='password']")
27 print(password.get_attribute("value"))
28 
29 #css 选择器,根据父子关系,定位密码输入框
30 password = driver.find_element_by_css_selector("div[id='login_form']>input[name='password']")
31 print(password.get_attribute("value"))
32 
33 # css 选择器,根据兄弟关系,定位密码输入框
34 password = driver.find_element_by_css_selector("input[name='username']+input")
35 print(password.get_attribute("value"))
通过css选择器定位
 1 上面的所有元素定位 find_element_by_xxx和find_elements_by_xxx调用的结果,实际上都是在调用以下两种方法,我们也可以直接调用一下两种方法即可。
 2 
 3 find_element(self, by=By.ID, value=None):
 4 find_elements(self, by=By.ID, value=None):
 5 
 6 class By(object):
 7     """
 8     Set of supported locator strategies.
 9     """
10 
11     ID = "id"
12     XPATH = "xpath"
13     LINK_TEXT = "link text"
14     PARTIAL_LINK_TEXT = "partial link text"
15     NAME = "name"
16     TAG_NAME = "tag name"
17     CLASS_NAME = "class name"
18     CSS_SELECTOR = "css selector"
19 
20 
21 例如:
22 from selenium.webdriver.common.by import By
23 # 根据id,定位id为“world”的元素
24 world = driver.find_element(By.ID,"world")
25 print(world.text)
26 
27 # xpath定位,相对路径与属性结合 定位密码输入框
28 password = driver.find_element(By.XPATH,"//input[@name='password']")
29 print(password.get_attribute("value"))
30 
31 # css选择器,标签+属性 定位用户名输入框
32 username = driver.find_element(By.CSS_SELECTOR,"input[name='username']")
33 print(username.get_attribute("value"))
通用的终极定位语法

 

三。元素操作:

 1 清除文本输入框
 2 clear(self)
 3 
 4 点击元素
 5 click(self)
 6 
 7 提交表单
 8 submit(self)
 9 
10 发送信息
11 send_keys(self, *value)
12 
13 获取元素的文本
14 text
WebElement 中常见的元素操作
 1 获取元素属性
 2 get_attribute(self, name)
 3 
 4 判断元素可见
 5 is_displayed(self)
 6 
 7 判断元素可用
 8 is_enabled(self)
 9 
10 判断元素是否被选中
11 is_selected(self)
WebElement 中常见的元素属性
1 获取元素位置
2 location
3 
4 获取元素大小
5 size
6 
7 获取元素的文本
8 text
WebElement 中常见的属性方法
1 ActionChains中提供一些复杂操作,如鼠标移动,鼠标按钮操作,按键操作和上下文菜单交互等,这些操作在实际运用中其实复杂操作并不常用,这里只简单介绍一个元素拖拽的例子,其他方法,请自行查看源码。
2 
3 element = driver.find_element_by_name("source")
4 target = driver.find_element_by_name("target")
5 
6 from selenium.webdriver import ActionChains
7 action_chains = ActionChains(driver)
8 # 拖拽(在元素A上按住鼠标左键不放,拖动到元素B上,然后松开鼠标)
9 action_chains.drag_and_drop(element, target).perform()
ActionChains 中的复杂操作

 

四。浏览器当行操作:

 

五。元素等待;

 

六。 示例演示

获取页面源码数据:
通过page_source属性可以获取网页的源代码,接着就可以使用解析库(如正则表达式、Beautiful Soup、pyquery等)来提取信息了。

 动作链:它们没有特定的执行对象,比如鼠标拖曳、键盘按键等,这些动作用另一种方式来执行,那就是动作链。

 

from selenium import webdriver
from selenium.webdriver import ActionChains
import time
browser = webdriver.Chrome()
url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)
browser.switch_to.frame('iframeResult')
source = browser.find_element_by_css_selector('#draggable')
target = browser.find_element_by_css_selector('#droppable')
actions = ActionChains(browser)
# actions.drag_and_drop(source, target)
# actions.perform() #执行动作链
actions.click_and_hold(source)
time.sleep(3)
for i in range(5):
    actions.move_by_offset(xoffset=17,yoffset=0).perform()
    time.sleep(0.5)

actions.release()
示例:实现一个节点的拖曳操作,将某个节点从一处拖曳到另外一处

 

浏览器前进后退演示:

import time
from selenium import webdriver
 
browser=webdriver.Chrome()
browser.get('https://www.baidu.com')
browser.get('https://www.taobao.com')
browser.get('http://www.sina.com.cn/')
 
browser.back()
time.sleep(10)
browser.forward()
browser.close()
需要:模拟浏览器的前进后退

Cookie处理:

  使用Selenium,还可以方便地对Cookies进行操作,例如获取、添加、删除Cookies等。示例如下:

from selenium import webdriver
 
browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
print(browser.get_cookies())
browser.add_cookie({'name': 'name', 'domain': 'www.zhihu.com', 'value': 'germey'})
print(browser.get_cookies())
browser.delete_all_cookies()
print(browser.get_cookies())
cookie操作演示

异常处理:

from selenium import webdriver
from selenium.common.exceptions import TimeoutException,NoSuchElementException,NoSuchFrameException

try:
    browser=webdriver.Chrome()
    browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
    browser.switch_to.frame('iframssseResult')

except TimeoutException as e:
    print(e)
except NoSuchFrameException as e:
    print(e)
finally:
    browser.close()
异常处理演示

selenium实现模拟百度搜索功能

from selenium import webdriver
from time import sleep

#实例化一个浏览器对象
bro = webdriver.Chrome(executable_path='./chromedriver.exe')
#基于url发起请求
sleep(2)
bro.get('https://www.baidu.com/')
#实现页面标签的定位
sleep(2)
input_tag = bro.find_element_by_id('kw')
input_tag.send_keys('周杰伦')
sleep(2)
btn = bro.find_element_by_id('su')
btn.click()
sleep(3)
#获取当前浏览器打开的页面对应的源码数据
page_text = bro.page_source
print(page_text)
sleep(2)
bro.quit()
需求:使用selenium在百度上进行数据搜索

 selenium实现无可视化展示

from selenium.webdriver.chrome.options import Options
from selenium import webdriver
from time import sleep
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')

#实例化一个浏览器对象
bro = webdriver.Chrome(executable_path='./chromedriver.exe',chrome_options=chrome_options)
#基于url发起请求
sleep(2)
bro.get('https://www.baidu.com/')
#实现页面标签的定位
sleep(2)
input_tag = bro.find_element_by_id('kw')
input_tag.send_keys('周杰伦')
sleep(2)
btn = bro.find_element_by_id('su')
btn.click()
sleep(3)
bro.save_screenshot('./1.jpg') # 进行截图保存
#获取当前浏览器打开的页面对应的源码数据
page_text = bro.page_source  # 爬取页面源码
print(page_text)
sleep(2)
bro.quit()
使用无可视化界面搜索并截图和爬取页面源码

 加载js文件实现动态加载浏览器数据

滚轮向下滑动一屏的高度:window.scrollTo(0,document.body.scrollHeight)
from selenium import webdriver
from time import sleep

bro = webdriver.Chrome(executable_path='./chromedriver.exe')
# bro = webdriver.PhantomJS(executable_path = '')
bro.get(url='https://news.163.com/domestic/') # 线程阻塞代码,上一个未执行完,下一个是不会执行的
sleep(2)
#让滚轮向下滑动
js = 'window.scrollTo(0,document.body.scrollHeight)'
bro.execute_script(js) # 非阻塞代码异步实现,所以这块要给一个暂停时间防止网速不好或者一些因素引起的问题
sleep(2)
bro.execute_script(js)
sleep(2)
bro.execute_script(js)
sleep(2)

a_tag = bro.find_element_by_xpath('/html/body/div/div[3]/div[4]/div[1]/div/div/a')
a_tag.click()
sleep(2)

#源码数据就包含了所有的新闻数据
page_text = bro.page_source

with open('./wangyi.html','w',encoding='utf-8') as fp:
    fp.write(page_text)
需求:网易新闻,实现滚轮滑动加载更多数据

这里引出一个无界面浏览器:phantomjs实现了一个无界面的webkit浏览器。虽然没有界面,但dom渲染、js运行、网络访问、canvas/svg绘制等功能都很完备,在页面抓取、页面输出、自动化测试等方面有广泛的应用。

驱动包百度共享下载:链接:https://pan.baidu.com/s/15j5RpkVAryKRa_VFrjdqDw      提取码:zptn 

from selenium import webdriver
from time import sleep

# bro = webdriver.Chrome(executable_path='./chromedriver.exe')
bro = webdriver.PhantomJS(executable_path = './phantomjs.exe')  #这里输入的是phantomjs.exe驱动路径
bro.get(url='https://news.163.com/domestic/') # 线程阻塞代码,上一个未执行完,下一个是不会执行的
sleep(2)
#让滚轮向下滑动
js = 'window.scrollTo(0,document.body.scrollHeight)'
bro.execute_script(js) # 非阻塞代码异步实现,所以这块要给一个暂停时间防止网速不好或者一些因素引起的问题
sleep(2)
bro.execute_script(js)
sleep(2)
bro.execute_script(js)
sleep(2)

a_tag = bro.find_element_by_xpath('/html/body/div/div[3]/div[4]/div[1]/div/div/a')
a_tag.click()
sleep(2)

#源码数据就包含了所有的新闻数据
page_text = bro.page_source

with open('./wangyi.html','w',encoding='utf-8') as fp:
    fp.write(page_text)
需求:通过无界面浏览器爬取数据

PhantomJS为用户提供了一个截屏的功能,使用save_screenshot函数实现

from selenium import webdriver
import time

# phantomjs路径
path = r'PhantomJS驱动路径'
browser = webdriver.PhantomJS(path)

# 打开百度
url = 'http://www.baidu.com/'
browser.get(url)
time.sleep(3)
browser.save_screenshot(r'phantomjs\baidu.png')

# 查找input输入框
my_input = browser.find_element_by_id('kw')
# 往框里面写文字
my_input.send_keys('美女')
time.sleep(3)
#截屏
browser.save_screenshot(r'phantomjs\meinv.png')

# 查找搜索按钮
button = browser.find_elements_by_class_name('s_btn')[0]
button.click()
time.sleep(3)
browser.save_screenshot(r'phantomjs\show.png')
time.sleep(3)
browser.quit()
需求:PhantomJS截图演示

 

selenium实现切换iframe:

from selenium import webdriver
from time import sleep
bro = webdriver.Chrome(executable_path='./chromedriver.exe')
url = 'https://qzone.qq.com/'
bro.get(url=url)
#将当前页面切换到了指定的iframe中,后续才可以定位到iframe中存在的标签
bro.switch_to.frame('login_frame')
a_tag = bro.find_element_by_id('switcher_plogin')
a_tag.click()
sleep(3)

bro.quit()
需求:模拟QQ空间登录切换iframe
import requests
from selenium import webdriver
from lxml import etree
import time

driver = webdriver.Chrome(executable_path='/Users/bobo/Desktop/chromedriver')
driver.get('https://qzone.qq.com/')
#在web 应用中经常会遇到frame 嵌套页面的应用,使用WebDriver 每次只能在一个页面上识别元素,对于frame 嵌套内的页面上的元素,直接定位是定位是定位不到的。这个时候就需要通过switch_to_frame()方法将当前定位的主体切换了frame 里。
driver.switch_to.frame('login_frame')
driver.find_element_by_id('switcher_plogin').click()

#driver.find_element_by_id('u').clear()
driver.find_element_by_id('u').send_keys('328410948')  #这里填写你的QQ号
#driver.find_element_by_id('p').clear()
driver.find_element_by_id('p').send_keys('xxxxxx')  #这里填写你的QQ密码
    
driver.find_element_by_id('login_button').click()
time.sleep(2)
driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
time.sleep(2)
driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
time.sleep(2)
driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
time.sleep(2)
page_text = driver.page_source

tree = etree.HTML(page_text)
#执行解析操作
li_list = tree.xpath('//ul[@id="feed_friend_list"]/li')
for li in li_list:
    text_list = li.xpath('.//div[@class="f-info"]//text()|.//div[@class="f-info qz_info_cut"]//text()')
    text = ''.join(text_list)
    print(text+'\n\n\n')
    
driver.close()
需求:登录QQ空间,爬取数据代码

 

selenium规避被检测识别

现在不少大网站有对selenium采取了监测机制。比如正常情况下我们用浏览器访问淘宝等网站的 window.navigator.webdriver的值为 
undefined。而使用selenium访问则该值为true。那么如何解决这个问题呢?

只需要设置Chromedriver的启动参数即可解决问题。在启动Chromedriver之前,为Chrome开启实验性功能参数excludeSwitches,它的值为['enable-automation'],完整代码如下:
from selenium.webdriver import Chrome
from selenium.webdriver import ChromeOptions

option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
driver = Chrome(options=option)

 

from selenium import webdriver
from time import sleep
import time

if __name__ == '__main__':
    url = 'https://movie.douban.com/typerank?type_name=%E6%81%90%E6%80%96&type=20&interval_id=100:90&action='
    # 发起请求前,可以让url表示的页面动态加载出更多的数据
    path = r'C:\Users\Administrator\Desktop\爬虫授课\day05\ziliao\phantomjs-2.1.1-windows\bin\phantomjs.exe'
    # 创建无界面的浏览器对象
    bro = webdriver.PhantomJS(path)
    # 发起url请求
    bro.get(url)
    time.sleep(3)
    # 截图
    bro.save_screenshot('1.png')

    # 执行js代码(让滚动条向下偏移n个像素(作用:动态加载了更多的电影信息))
    js = 'window.scrollTo(0,document.body.scrollHeight)'
    bro.execute_script(js)  # 该函数可以执行一组字符串形式的js代码
    time.sleep(2)

    bro.execute_script(js)  # 该函数可以执行一组字符串形式的js代码
    time.sleep(2)
    bro.save_screenshot('2.png') 
    time.sleep(2) 
    # 使用爬虫程序爬去当前url中的内容 
    html_source = bro.page_source # 该属性可以获取当前浏览器的当前页的源码(html) 
    with open('./source.html', 'w', encoding='utf-8') as fp: 
        fp.write(html_source) 
    bro.quit()
需求:使用懒加载爬取豆瓣网中的电影信息演示代码

 

posted @ 2019-03-19 16:25  姜浩  阅读(451)  评论(0编辑  收藏  举报