目录
Selenium(WEB自动化工具)
-
准备工作
下载selenium包
pip install selenium
如遇网络问题可改源: pip install selenium -i 清华源
下载浏览器驱动
注意找对应浏览器版本的驱动,下载解压完成后将驱动文件(重命名去掉后面的数字)复制进python解释器所在文件夹下
Edge浏览器驱动网站:https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/#installation
-
基本操作
#导入包
from selenium.webdriver import Edge
#创建一个浏览器对象
browser = Edge()
#打开一个网址
browser.get("https://www.baidu.com")
#打印标签页名称
print(browser.title)
#打印页面源代码
print(browser.page_source())
#退出驱动,关闭所有窗口
browser.quit()
-
对象定位方法
webdriver 提供了一系列的对象定位方法,常用的有以下几种:
#xpath定位:find_element_by_xpath()
#id定位:find_element_by_id()
#name定位:find_element_by_name()
#class定位:find_element_by_class_name()
#link定位:find_element_by_link_text()
#partial link定位:find_element_by_partial_link_text()
#tag定位:find_element_by_tag_name()
#css定位:find_element_by_css_selector()
#(将element改为elements将匹配所有的对应元素,类似正则匹配里find和find_all的关系)
在实际进行元素定位时,经常发现class name是有多个class组合的复合类,中间以空格隔开。如果直接进行定位会出现报错,可以通过以下方式处理:
1.class属性唯一但是有空格,选择空格两边唯一的那一个
2.若空格隔开的class不唯一可以通过索引进行定位
self.browser.find_elements_by_class_name('table-dragColumn')[0].click()
3.通过css方法进行定位(空格以‘.’代替)
self.browser.find_element_by_css_selector('.dtb-style-1.table-dragColumns').click()
包含整个类self.browser.find_element_by_css_selector('class="dtb-style-1 table-dragColumns"').click()
-
三种等待方式
有时候为了保证脚本运行的稳定性,需要脚本中添加等待时间。
强制等待
第一种也是最简单粗暴的一种办法就是强制等待sleep(xx),需要引入“time”模块。time.sleep(3),不管你浏览器是否加载完了,程序都得等待3秒,3秒一到,继续执行下面的代码,作为调试很有用,有时候也可以在代码里这样等待,不过不建议总用这种等待方式,太死板,严重影响程序执行速度。
隐性等待
第二种办法叫隐性等待,通过添加 implicitly_wait() 方法就可以方便的实现智能等待。browser.implicitly_wait(30) 的用法应该比 time.sleep() 更智能,后者只能选择一个固定的时间的等待,前者可以 在一个时间范围内智能的等待。
隐形等待是设置了一个最长等待时间,如果在规定时间内网页加载完成,则执行下一步,否则一直等到时间截止,然后执行下一步。注意这里有一个弊端,那就是程序会一直等待整个页面加载完成,也就是一般情况下你看到浏览器标签栏那个小圈不再转,才会执行下一步,但有时候页面想要的元素早就在加载完成了,但是因为个别js之类的东西特别慢,我仍得等到页面全部完成才能执行下一步,我想等我要的元素出来之后就下一步怎么办?有办法,这就要看selenium提供的另一种等待方式——显性等待wait了。
需要特别说明的是:隐性等待对整个driver的周期都起作用,所以只要设置一次即可
显性等待
第三种办法就是显性等待,WebDriverWait类,配合该类的until()和until_not()方法,就能够根据判断条件而进行灵活地等待了。它主要的意思就是:程序每隔xx秒看一眼,如果条件成立了,则执行下一步,否则继续等待,直到超过设置的最长时间,然后抛出TimeoutException。
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
driver = webdriver.Edge()
driver.implicitly_wait(10) # 隐性等待和显性等待可以同时用,但要注意:等待的最长时间取两者之中的大者
driver.get('https://huilansame.github.io')
locator = (By.LINK_TEXT, 'CSDN')
try:
WebDriverWait(driver, 20, 0.5).until(EC.presence_of_element_located(locator))
finally:
driver.close()
如果想深入研究WebDriverWait类,可参考:https://www.jb51.net/article/92672.htm
-
浏览器操作
浏览器最大化、最小化
#将浏览器最大化显示
browser.maximize_window()
#将浏览器最小化显示
browser.minimize_window()
浏览器设置窗口大小
#设置浏览器宽480、高800显示
browser.set_window_size(480, 800)
浏览器前进后退、窗口选择
#前进
browser.forword()
#后退
browser.back()
#切换到最后一个标签页窗口
browser.switch_to_window(browser.window_handles[-1])
#关闭当前窗口
browser.close()
#退出驱动关闭所有窗口
browser.quit()
-
操作测试对象
一般来说,webdriver 中比较常用的操作对象的方法有下面几个:
click——点击对象
send_keys——在对象上模拟按键输入
clear——清除对象的内容,如果可以的话
submit——提交对象的内容,如果可以的话
text——用于获取元素的文本信息
-
键盘事件
#要想调用键盘按键操作需要引入 keys 包
from selenium.webdriver.common.keys import Keys
#通过 send_keys()调用按键
send_keys(Keys.TAB) # TAB
send_keys(Keys.ENTER) # 回车
-
鼠标事件
鼠标事件一般包括鼠标右键、双击、拖动、移动鼠标到某个元素上等等,需要引入ActionChains类。ActionChains 常用方法:
#perform() 执行所有ActionChains 中存储的行为
#context_click() 右击
#double_click() 双击
#drag_and_drop() 拖动
#move_to_element() 鼠标悬停
示例 :
#引入ActionChains类
from selenium.webdriver.common.action_chains import ActionChains
#创建动作链
action = ActionChains(browser)
#鼠标双击示例:
#定位到要双击的元素
qqq =browser.find_element_by_xpath("xxx")
#对定位到的元素执行鼠标双击操作
action.double_click(qqq).perform()
#鼠标拖放示例:
#定位元素的原位置
element = browser.find_element_by_name("source")
#定位元素要移动到的目标位置
target = browser.find_element_by_name("target")
#执行元素的移动操作
action.drag_and_drop(element, target).perform()
-
多层框架/层级定位
定位元素过程中经常会遇到找不到元素的问题,出现该问题一般都是以下因素导致:
1.元素定位方法不对
2.页面存在iframe或内嵌窗口
3.页面超时
webdriver 提供了一个 switch_to_frame 方法,可以很轻松的来解决这个问题。用法:
#先找到 ifrome1(id = f1)
browser.switch_to_frame("f1")
#同样的,如果是内嵌窗口
browser.switch_to_window("f1")
#想切回来
browser.switch_to.default_content()
-
下拉列表
#导入对应包
from selenium.webdriver.support.select import Select
#定位到下拉列表
list = browser.find_element_by_xpath("...")
#对元素进行包装,包装成下拉列表
sel = Select(list)
#所有选项sel.options()
#根据索引切换sel.select_by_index()
#根据value的值切换sel.select_by_value()
#根据文本显示内容切换sel.select_by_visible_text()
-
执行JavaScript代码
browser.execute.script()
-
无头浏览器
#需要导入包
from selenium.webdriver.Edge.options import Options
#创建一个参数对象,用来控制edge以无界面模式打开
edge_options = Options()
#无头浏览器参数配置
edge_options.add_argument("--headless")
edge_options.add_argument("--disable-gpu")
#把参数配置放入浏览器中,创建浏览器对象
browser = Edge(options = edge_options)
-
Expected Conditions解析
使用场景
1.直接在断言中使用
2.与WebDriverWait配合使用,动态等待页面上元素出现或者消失
相关方法
title_is: 判断当前页面的title是否精确等于预期
title_contains: 判断当前页面的title是否包含预期字符串
presence_of_element_located:判断某个元素是否被加到了dom树里,并不代表该元素一定可见
visibility_of_element_located:判断某个元素是否可见.可见代表元素非隐藏,并且元素的宽和高都不等于0
visibility_of:跟上面的方法做一样的事情,只是上面的方法要传入locator,这个方法直接传定位到的element就好了
presence_of_all_elements_located:判断是否至少有1个元素存在于dom树中。举个例子,如果页面上有n个元素的class都是'column-md-3',那么只要有1个元素存在,这个方法就返回True
text_to_be_present_in_element:判断某个元素中的text是否包含了预期的字符串
text_to_be_present_in_element_value:判断某个元素中的value属性是否包含了预期的字符串
frame_to_be_available_and_switch_to_it:判断该frame是否可以switch进去,如果可以的话,返回True并且switch进去,否则返回False
invisibility_of_element_located:判断某个元素中是否不存在于dom树或不可见
element_to_be_clickable:判断某个元素中是否可见并且是enable的,这样的话才叫clickable
staleness_of:等某个元素从dom树中移除,注意,这个方法也是返回True或False
element_to_be_selected:判断某个元素是否被选中了,一般用在下拉列表
element_selection_state_to_be:判断某个元素的选中状态是否符合预期
element_located_selection_state_to_be:跟上面的方法作用一样,只是上面的方法传入定位到的element,而这个方法传入locator
alert_is_present:判断页面上是否存在alert
示例
"""
思路:
1.判断title:title_is()、title_contains()
2.导入expected_conditions模块。由于这个模块名称比较长,所以为了后续的调用方便,重新命名为EC了(有点像数据库里面多表查询时候重命名)
3.打开博客首页后判断title,返回结果是True或False
"""
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Firefox()driver.get("URL")
# 判断title完全等于
title = EC.title_is(u'冰封')
print title(driver)
# 判断title包含
title1 = EC.title_contains(u'冰封')
print title1(driver)
# 另外一种写法
r1 = EC.title_is(u'冰封')(driver)
r2 = EC.title_contains(u'冰封')(driver)
print r1
print r2
-
selenium规避检测--------浏览器托管
验证码
破解方法:
1.图像识别
2.互联网上比较成熟的验证码破解工具,如:超级鹰 http://www.chaojiying.com/about.html