Selenium模块

Selenium模块

1 Selenium 介绍

1.1 Selenium简介

Selenium(浏览器自动化测试框架) 是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7, 8, 9, 10, 11),Firefox,Safari,Google Chrome,Opera等。这个工具的主要功能包括:测试浏览器的兼容性——测试你的应用程序看是否能够很好得工作在不同浏览器和操作系统之上。测试系统功能——创建回归测试检验软件功能和用户需求。支持自动录制动作和自动生成 .Net、Java、Perl等不同语言的测试脚本。

  • 框架底层使用JavaScript模拟真实用户对浏览器进行操作。测试脚本执行时,浏览器自动按照脚本代码做出点击,输入,打开,验证等操作,就像真实用户所做的一样,从终端用户的角度测试应用程序。
  • 使浏览器兼容性测试自动化成为可能,尽管在不同的浏览器上依然有细微的差别。
  • 使用简单,可使用Java,Python等多种语言编写用例脚本。

1.2 Selenium 安装

2 Selenium 基础使用

2.1 Selenium 调用

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from time import sleep

# 以Chrome为例
chrome_options = webdriver.ChromeOptions()
chrome_options.binary_location = r'C:\Program Files\Google\Chrome Dev\Application\chrome.exe'
ser = Service(r'chromedriver.exe')
driver = webdriver.Chrome(service=ser, options=chrome_options)
driver.get('https://www.ruiwen.com/wenxue/baijiyi/301471.html')
# 3s延迟观察结果
sleep(3)
driver.quit()

2.2 Selenium 定位

from selenium.webdriver.common.by import By

# 查找页面的“新闻”选项,并进行点击
driver.find_element(by=By.LINK_TEXT, value='新闻').click()
time.sleep(1)

# 定位到要悬停的元素
element = driver.find_element(by=By.XPATH, value='//*[@id="s-usersetting-top"]')

# 定位百度的输入框,并输入"京东"
driver.find_element(by=By.ID, value='kw').send_keys('京东')

# 其他的属性值如果太长,也可以采取模糊方法定位:例如
<a href="http://www.baidu.com?name=admin&passwd=pass&action=login" rel="external nofollow" >百度一下</a>
driver.find_element(by=By.XPATH, value="//a[contains(@href,'login')]")

2.3 Webdriver 浏览器操作

方法 说明
set_window_size() 设置浏览器的大小
back() 控制浏览器后退
forward() 控制浏览器前进
refresh() 刷新当前页面
clear() 清除文本
send_keys (value) 模拟按键输入
click() 单击元素
submit() 用于提交表单
get_attribute(name) 获取元素属性值
is_displayed() 设置该元素是否用户可见
size 返回元素的尺寸
text 获取元素的文本

2.4 动作链

from selenium.webdriver.common.action_chains import ActionChains
方法 说明
ActionChains(driver) 构造ActionChains对象
context_click() 执行鼠标悬停操作
move_to_element(above) 右击
double_click() 双击
drag_and_drop() 拖动
move_to_element(above) 执行鼠标悬停操作
context_click() 用于模拟鼠标右键操作, 在调用时需要指定元素定位
perform() 执行所有 ActionChains 中存储的行为,可以理解成是对整个操作的提交动作

2.5 键盘事件

模拟键盘按键 说明
send_keys(Keys.BACK_SPACE) 删除键(BackSpace)
send_keys(Keys.SPACE) 空格键(Space)
send_keys(Keys.TAB) 制表键(Tab)
send_keys(Keys.ESCAPE) 回退键(Esc)
send_keys(Keys.ENTER) 回车键(Enter)
send_keys(Keys.CONTROL,‘a') 全选(Ctrl+A)
send_keys(Keys.CONTROL,‘c') 复制(Ctrl+C)
send_keys(Keys.CONTROL,‘x') 剪切(Ctrl+X)
send_keys(Keys.CONTROL,‘v') 粘贴(Ctrl+V)
send_keys(Keys.F1…Fn) 键盘 F1…Fn

2.6 实战案例

  1. 使用Selenium 打开浏览器,进入百度搜索页面,打开新闻页面,后退出。
  2. 注释步骤1 撕开新闻页面代码,设置每页显示50条搜索结果,保存设置。处理弹出的警告页面,返回alert内容
  3. 找到百度的输入框,并输入"京东",点击搜索按钮,并在搜索结果中,打开京东官网
  4. 下拉京东官网页面后,退出。
import time
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import undetected_chromedriver as uc


# 如何规避 selenium 被检测
chrome_options = webdriver.ChromeOptions()
chrome_options.binary_location = r'C:\Program Files\Google\Chrome Dev\Application\chrome.exe'
chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])
chrome_options.add_argument('--disable-blink-features=AutomationControlled')

# 创建Chrome浏览器对象,这会在电脑上在打开一个浏览器窗口
# 后面是你的浏览器驱动位置
ser = Service(r"chromedriver.exe")
driver = webdriver.Chrome(service=ser, options=chrome_options)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
    "source": """
            Object.defineProperty(navigator, 'webdriver', {
              get: () => undefined
            })
            """
})

# 窗口最大化
driver.maximize_window()

# 创建一个等待对像,超时时间为10秒,调用的时间间隔为0.5
wait = WebDriverWait(driver, 10, 0.5)

# 用get打开百度页面
driver.get('https://www.baidu.com/')

# 查找页面的“新闻”选项,并进行点击
driver.find_element(by=By.LINK_TEXT, value='新闻').click()
time.sleep(1)

# 定位到要悬停的元素
element = driver.find_element(by=By.XPATH, value='//*[@id="s-usersetting-top"]')

# 对定位到的元素执行鼠标悬停操作
ActionChains(driver=driver).move_to_element(element).perform()
# 每隔0.5秒检查一次,直到页面元素出现link text为'搜索设置'的标签
wait.until(EC.presence_of_all_elements_located((By.LINK_TEXT, "搜索设置")))
# 打开设置后找到“搜索设置”选项
driver.find_element(by=By.LINK_TEXT, value='搜索设置').click()

# 设置为每页显示50条
wait.until(EC.presence_of_all_elements_located((By.XPATH, '//*[@id="se-setting-3"]/span[3]')))
driver.find_element(by=By.XPATH, value='//*[@id="se-setting-3"]/span[3]').click()

# 保存设置
wait.until(EC.presence_of_all_elements_located((By.LINK_TEXT, '保存设置')))
driver.find_element(by=By.LINK_TEXT, value='保存设置').click()

# 处理弹出的警告页面,返回alert内容
print(driver.switch_to.alert.text)
driver.switch_to.alert.accept()  # 取消允许
# driver.switch_to.alert.dismiss()  # 取消
# 另外一种实现形式
# alert = WebDriverWait(driver, 10, 0.5).until(EC.alert_is_present())
# print(alert.text)
# alert.accept()


# 找到百度的输入框,并输入"京东"
driver.find_element(by=By.ID, value='kw').send_keys('京东')
# 点击搜索按钮
driver.find_element(by=By.ID, value='su').click()
# 在搜索结果中,打开京东官网
wait.until(EC.presence_of_all_elements_located((By.XPATH, '//*[@id="1"]/div/div[1]/h3/a[1]')))
driver.find_element(by=By.XPATH, value='//*[@id="1"]/div/div[1]/h3/a[1]').click()

page_text = driver.page_source
print(page_text)
driver.switch_to.window(driver.window_handles[-1])  # 切换window handle,否则滑动的是第一个窗口

# 执行js
time.sleep(2)
# js = 'window.scrollTo(0,document.body.scrollHeight)'
driver.execute_script("document.documentElement.scrollTop=10000")  # 滚动到底部

time.sleep(10)
# 使用driver.quit()可以退出浏览器。不管打开的是几个窗口,全部退出。
driver.quit()
# 使用driver.close()可以关闭当前显示的窗口。如果打开多个窗口,也只会关闭当前的窗口,其他窗口正常显示。
# driver.close()

3 窗口切换注意事项

引用:selenium中的window handle - 菜鸟学院 (noobyard.com)

import time
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
def demo():
    driver = webdriver.Chrome()
    driver.implicitly_wait(10)
    driver.get('[http://baidu.com](http://baidu.com)')
    print(driver.window_handles) #打开百度后第一次打印窗口句柄
    bd_kw = driver.find_element_by_css_selector('#kw')
    bd_sb = driver.find_element_by_css_selector('#su')
    ac = ActionChains(driver)
    ac.send_keys_to_element(bd_kw, 'python').click(bd_sb).perform()
    py = driver.find_element_by_xpath('//*[@id="2"]/h3/a')
    py.click() #在百度中搜索python后打开一个新的窗口
    print(driver.window_handles) #第二次打印窗口句柄
    time.sleep(5)
    driver.close() #关闭driver的当前句柄,可以用current_handle查看
    print(driver.window_handles) #第三次打印窗口句柄
    driver.switch_to.window(driver.window_handles[-1]) #切换window handle
    print(driver.current_window_handle) #打印current_window_handle,不切换会报异常,因为之前的window已经被我们关闭了
    time.sleep(5)
    driver.quit()
if __name__ == '__main__':
    demo()
----------------------
>>>['CDwindow-3711170FE14EB6A64A8D9A51249D8EF6'] #只打开了百度首页,所以只有一个
>>>['CDwindow-3711170FE14EB6A64A8D9A51249D8EF6', 'CDwindow-1FDDE8A60F9569D82F5A477DCBF6B8E1'] #打开了百度首页和某一个搜索出来的页面,新的页面在新的窗口中,所以有两个
>>>['CDwindow-1FDDE8A60F9569D82F5A477DCBF6B8E1'] #没切换handle,关闭了第一个window,所以看到,原列表中的第一个元素被删除了,只有新的窗口handle保留下来了
>>>CDwindow-1FDDE8A60F9569D82F5A477DCBF6B8E1 #切换了handle,并打印出current_window_handle` 

4 使用动作链实现拖拽

from selenium.webdriver.common.action_chains import ActionChains
from time import sleep
# import undetected_chromedriver as uc
from selenium import webdriver
from selenium.webdriver.chrome.service import Service

chrome_options = webdriver.ChromeOptions()
chrome_options.binary_location = r'C:\Program Files\Google\Chrome Dev\Application\chrome.exe'
ser = Service(r'chromedriver.exe')
driver = webdriver.Chrome(service=ser, options=chrome_options)

driver.get('https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
# 在实现标签定位时,如果发现定位的标签是存在于iframe标签之中的,则在定位时必须执行一个固定的操作switch_to.frame('[id|name]')
driver.switch_to.frame('iframeResult')
drag_tag = driver.find_element('id', 'draggable')
to_tag = driver.find_element('id', 'droppable')

# 创建一个动作链
action = ActionChains(driver=driver)

# 方式一:
action.drag_and_drop(drag_tag, to_tag).perform()
sleep(1)

# 方式二:
# perform() 让动作链立即执行
action.click_and_hold(drag_tag).move_to_element(to_tag).release().perform()
sleep(1)

# 方式三:
action = ActionChains(driver=driver).click_and_hold(drag_tag)
for i in range(5):
    action.move_by_offset(51, 1).perform()
    sleep(1)
action.release().perform()

print(driver.switch_to.alert.text)
driver.switch_to.alert.accept()
sleep(10)
driver.quit()

5 窗口界面截图

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from time import sleep
from PIL import Image

# 获取chrome参数对象
chrome_options = webdriver.ChromeOptions()
chrome_options.binary_location = r'C:\Program Files\Google\Chrome Dev\Application\chrome.exe'
# 添加无头参数r,一定要使用无头模式,不然截不了全页面,只能截到你电脑的高度
chrome_options.add_argument('headless')
# 为了解决一些莫名其妙的问题关闭 GPU 计算
chrome_options.add_argument('disable-gpu')
# 为了解决一些莫名其妙的问题浏览器不动
chrome_options.add_argument('no-sandbox')
# 添加驱动地址。 由于在函数内,设置参数chrome_options
ser = Service(r'chromedriver.exe')
driver = webdriver.Chrome(service=ser, options=chrome_options)
driver.get('https://www.ruiwen.com/wenxue/baijiyi/301471.html')
sleep(3)
img = driver.find_element('xpath', '/html/body/div[2]/div[2]/div/div[2]/p[3]/img')
img_location = img.location
img_size = img.size
driver.set_window_size(img.size['width'], img.size['height'])
img.screenshot('code.png')
driver.quit()
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from time import sleep
from PIL import Image

chrome_options = webdriver.ChromeOptions()
chrome_options.binary_location = r'C:\Program Files\Google\Chrome Dev\Application\chrome.exe'
ser = Service(r'chromedriver.exe')
driver = webdriver.Chrome(service=ser, options=chrome_options)
driver.get('https://www.ruiwen.com/wenxue/baijiyi/301471.html')
# 最大化窗口
driver.maximize_window()
sleep(1)
# 定位到图片所在位置
js = 'document.documentElement.scrollTop=500'
driver.execute_script(js)
sleep(1)
# 保存当前窗口截图
driver.save_screenshot('page.png')
sleep(1)
# 定位图片所在位置
img = driver.find_element('xpath', '/html/body/div[2]/div[2]/div/div[2]/p[3]/img')
img_location = img.location
# 获取图片长宽像素
img_size = img.size
img_range = (int(img_location['x'] + 50), int(img_location['y'] - 475), int(img_location['x'] + img_size['width']),
             int(img_location['y'] + img_size['height'] - 475))
# 对保存的窗口截图对像素进行截图、保存
target_img = Image.open('page.png')
fragment = target_img.crop(img_range)
fragment.save('code.png')
driver.quit()

6 特性

6.1 无窗口化启动

# 获取chrome参数对象
chrome_options = webdriver.ChromeOptions()
chrome_options.binary_location = r'C:\Program Files\Google\Chrome Dev\Application\chrome.exe'
# 添加无头参数r,一定要使用无头模式,不然截不了全页面,只能截到你电脑的高度
chrome_options.add_argument('headless')
# 为了解决一些莫名其妙的问题关闭 GPU 计算
chrome_options.add_argument('disable-gpu')
# 为了解决一些莫名其妙的问题浏览器不动
chrome_options.add_argument('no-sandbox')


6.2 规避网站检测

import time
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By

# 如何规避 selenium 被检测
chrome_options = webdriver.ChromeOptions()
chrome_options.binary_location = r'C:\Program Files\Google\Chrome Dev\Application\chrome.exe'
chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])
chrome_options.add_argument('--disable-blink-features=AutomationControlled')

# 创建Chrome浏览器对象,这会在电脑上在打开一个浏览器窗口
# 后面是你的浏览器驱动位置
ser = Service(r"chromedriver.exe")
driver = webdriver.Chrome(service=ser, options=chrome_options)
# driver = webdriver.Chrome(options=chrome_options)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
    "source": """
            Object.defineProperty(navigator, 'webdriver', {
              get: () => undefined
            })
            """
})

# 窗口最大化
driver.maximize_window()

# 用get打开百度页面
driver.get('https://www.baidu.com/')

# 查找页面的“新闻”选项,并进行点击
driver.find_element(by=By.LINK_TEXT, value='新闻').click()

time.sleep(30)
# 使用driver.quit()可以退出浏览器。不管打开的是几个窗口,全部退出。
driver.quit()
# 使用driver.close()可以关闭当前显示的窗口。如果打开多个窗口,也只会关闭当前的窗口,其他窗口正常显示。
# driver.close()

"""
window.navigator.webdriver
false
"""
posted @ 2022-12-05 11:58  f_carey  阅读(94)  评论(0编辑  收藏  举报