Selenium WebDriver

1. Browser navigation

a. 访问页面

进行页面访问使用的是get方法,传入参数为待访问页面的URL地址即可。

from selenium import webdriver
 
# 初始化浏览器为chrome浏览器
browser = webdriver.Chrome()
 
# 访问百度首页
browser.get(r'https://www.baidu.com/')
 
# 关闭浏览器
browser.close()

 

b. 前进后退

 

from selenium import webdriver
import time  
 
browser = webdriver.Chrome()
 
# 设置浏览器全屏
browser.maximize_window()   
browser.get(r'https://www.baidu.com')  
time.sleep(2)
 
# 打开淘宝页面
browser.get(r'https://www.taobao.com')  
time.sleep(2)
 
# 后退到百度页面
browser.back()  
time.sleep(2)
 
# 前进的淘宝页面
browser.forward() 
time.sleep(2)
 
# 关闭浏览器
browser.close()

 

c.刷新页面

refresh()方法可以用来进行浏览器页面刷新。

from selenium import webdriver
import time  
 
browser = webdriver.Chrome()
 
# 设置浏览器全屏
browser.maximize_window()   
browser.get(r'https://www.baidu.com')  
time.sleep(2)
 
try:
    # 刷新页面
    browser.refresh()  
    print('刷新页面')
except Exception as e:
    print('刷新失败')
   
# 关闭浏览器
browser.close()

 

d. 页面源码实时获取

WebDriver.page_source

 

f.滑动到底部

driver.execute_script(“window.scrollTo(0,document.body.scrollHeight);”)

 

2.selenium 的四种等待方式

a.强制等待

time模块 time.sleep(3) ——不建议使用,遇到网络不好的情况会超时

 

b. 隐式等待:

隐式等待是设置全局的查找页面元素的等待时间,在这个时间内没找到指定元素则抛出异常,只需设置一次。

如果是只需等待页面中的一个元素加载就用显示等待,等待整个网页加载就用隐式等待。

使用方法:implicitly_wait(delay),delay的单位为秒

缺点:这是全局等待,你想要的元素其实已经加载出来,但是有其他的js,css等加载时间比较久就会影响测试进度

from selenium import webdriver
from selenium.webdriver.common.by import By
wd = webdriver.Chrome()
wd.get('http://www.qq.com')
wd.implicitly_wait(10)
wd.find_element(By.CSS_SELECTOR,'[href="http://news.qq.com/"]').click()

 

c. 显式等待

当等待的条件满足后(一般用来判断需要等待的元素是否加载出来),就继续下一步操作。等不到就一直等,如果在规定的时间之内都没找到,那么就跳出Exception。

使用显示等待前需先导入显示等待所需模块和等待条件

WebDriverWait类是由webdriver提供的等待方法,配合该类提供的until()和until_not()方法一起使用,就可以根据判断条件而灵活进行等待
1.WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None)
2 driver:浏览器驱动
3 timeout:最长超时时间
4 poll_frequency:检测间隔时间,默认0.5s
5 ignored_exceptions:超时后的异常信息,默认情况抛出NoSuchElementException异常

6 WebDriverWait()一般由until()或until_not方法配合使用,下面是这两种方法的说明:
7 until(method,message=''):调用该方法提供的驱动程序作为一个参数,直到返回值为True;
8 until_not(method,message=''):调用该方法提供的驱动程序作为一个参数,直到返回值为Flase;
# coding = utf-8
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.Chrome()
driver.implicitly_wait(10)
driver.get('http://www.cnblogs.com/imyalost/')
locator = (By.LINK_TEXT, '老_张')
  
try:
    WebDriverWait(driver, 20, 0.5).until(EC.presence_of_element_located(locator))             finally:
    driver.close()

代码解析:

本例中,通过as关键字将expected_conditions重命名为EC,并调用presence_of_element_located()方法判断元素是否存在;

上面的例子中,同时使用了隐性等待和显性等待,但是需要注意的是:等待的最长时间取两者之中的最大值;

预期条件(Expected conditions),对 Python 接口来说,具体包含如下内容:

预期条件释义
alert_is_present 预期出现提示框
element_located_selection_state_to_be 预期节点元素选择状态
element_selection_state_to_be 预期节点元素选择状态
element_located_to_be_selected 预期节点元素为选择状态
element_to_be_clickable 预期元素可点击(可见+使能)
element_to_be_selected 预期元素处于选中状态
frame_to_be_available_and_switch_to_it 预期 frame 可用,同时切换到该 frame 中
visibility_of 预期节点可见(节点必须已经加载到当前 DOM 上)
visibility_of_element_located 预期节点可见
visibility_of_all_elements_located 预期指定的所有节点可见
visibility_of_any_elements_located 预期至少一个指定的节点可见
invisibility_of_element 预期节点元素不可见或不存在
invisibility_of_element_located 预期节点元素不可见或不存在
new_window_is_opened 预期新开窗口,同时窗口数量增加
number_of_windows_to_be 预期窗口数量
presence_of_all_elements_located 预期所有节点加载完成
presence_of_element_located 预期节点元素加载完成(无需为可见状态)
staleness_of 等待直到预期元素脱离 DOM
text_to_be_present_in_element 预期节点文本
text_to_be_present_in_element_value 预期节点元素 value 值
title_contains 预期标题包含相关子串(区分大小写)
title_is 预期标题(完全匹配)
url_changes 预期 URL 更改
url_contains 预期当前 URL 包含相关子串(区分大小写)
url_matches 预期当前 URL 匹配指定模式
url_to_be 预期当前 URL 内容(完全匹配)

 

from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException, TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait

driver = webdriver.Chrome()
driver.get('http://127.0.0.1:5500/index.html')

try:
    # 设置 WebDriverWait 的超时时间为 10 秒
    wait = WebDriverWait(driver, timeout=10)
    # 条件为 lambda 表达式
    el = wait.until(lambda d: d.find_element_by_tag_name("p"))
    print(f'locate tag p: {el.text}')
except TimeoutException:
    print('failed to locate p element!!')
finally:
    driver.quit()
可以不看
WebDriver.until(method, message='')会轮询method执行返回值,在规定时间内,method返回真就结束轮询,并把method返回值返回给WebDriver.until(method,message='')方法,所以上述代码中,我们直接让method定位我们需要的元素,成功找到时,until(..)方法就可以直接返回该元素。
如果超出规定时间,method仍返回false,那么until(..)方法会抛出TimeoutException异常。

作者:Whyn
链接:https://www.jianshu.com/p/0356a7bf833a
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
解释

 

d. FluentWait

 与显示等待的 WebDriverWait类似,区别是WebDriverWait已经设置好几个等待条件,而流畅等待 FluentWait可以自己设置等待条件。

##FluentWait instance defines the maximum amount of time to wait for a #condition, as well as the frequency with which to check the condition.

#Users may configure the wait to ignore specific types of exceptions whilst #waiting, such as NoSuchElementException when searching for an element on the #page.
driver = Firefox()
driver.get("http://somedomain/url_that_delays_loading")
wait = WebDriverWait(driver, timeout=10, poll_frequency=1, ignored_exceptions=[ElementNotVisibleException, ElementNotSelectableException])
element = wait.until(EC.element_to_be_clickable((By.XPATH, "//div")))
  
View Code
其实从上述代码中,可以看到,Python 中的 FluentWait显示等待 没有区别,这是因为不同语言的接口有些许不同,像FluentWait在 Python 接口中并没有提供,因为使用WebDriver就可以设置超时时间和轮询时间,而 Java 接口就提供了FluentWait类...
 
 

3.窗口大小操作

常用的窗口操作有设置窗口大小、最大化窗口、最小化窗口、全屏窗口

① 设置窗口大小
driver.set_window_size(1920, 1080)

② 最大化窗口
driver.maximize_window()

③ 最小化窗口
driver.minimize_window()
最小化窗口是selenium4的新功能,selenium3不能使用此方法

④ 全屏窗口,相当于大多数浏览器中按下F11
driver.fullscreen_window()

from selenium import webdriver

driver = webdriver.Edge()
driver.get('https://www.baidu.com/')
driver.set_window_size(1920, 1080)   # 设置窗口大小 1920*1080
driver.minimize_window()  # 最小化窗口
driver.maximize_window()  # 最大化窗口
driver.fullscreen_window() # 全屏窗口

 

4.获取当前页面title

driver.title() 获取当前页面的title

from selenium import webdriver

driver = webdriver.Edge()
driver.get('https://www.baidu.com/')
title = driver.title  # 获取当前页面title
print(title)
from selenium import webdriver
driver = webdriver.Edge()
driver.get('https://www.baidu.com/')
url = driver.current_url    # 本行用于获取当前页面的url,即百度首页地址
print(url)

 

5.无界面的浏览器

from selenium import webdriver
 
# 无界面的浏览器
option = webdriver.ChromeOptions()
option.add_argument("headless")
browser = webdriver.Chrome(options=option)
 
# 访问百度首页
browser.get(r'https://www.baidu.com/')
# 截图预览
browser.get_screenshot_as_file('截图.png')
 
# 关闭浏览器
browser.close()

 

6.退出浏览器

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Edge()
driver.get('https://www.baidu.com/')
driver.find_element(By.ID, 'kw').send_keys('selenium')  #搜索框输入selenium
driver.find_element(By.ID, 'su').click()     # 点击百度一下
driver.quit()     # 退出浏览器

 driver.close()方法关闭当前标签页,driver.quit()方法关闭所有打开的标签页

 

7.元素操作

a. 元素定位

如何手动进行元素定位?

 打开浏览器---f12进入开发者模式---在Elements页面---使用选择工具去页面点击对应元素---HTML将自动展开并高亮显示选择到的元素标记

 

b.定位单个元素

使用方法find_element()和By,找到的是节点。

Selenium provides support for these 8 traditional location strategies in WebDriver:

LocatorDescription
class name Locates elements whose class name contains the search value (compound class names are not permitted)
css selector Locates elements matching a CSS selector
id Locates elements whose ID attribute matches the search value
name Locates elements whose NAME attribute matches the search value
link text Locates anchor elements whose visible text matches the search value
partial link text Locates anchor elements whose visible text contains the search value. If multiple elements are matching, only the first one will be selected.
tag name Locates elements whose tag name matches the search value,标签,去网页源码中找
xpath Locates elements matching an XPath expression

The attributes available for the By class are used to locate elements on a page. These are the attributes available for By class:

ID = "id"
NAME = "name"
XPATH = "xpath"
LINK_TEXT = "link text"
PARTIAL_LINK_TEXT = "partial link text"
TAG_NAME = "tag name"
CLASS_NAME = "class name"
CSS_SELECTOR = "css selector"

The ‘By’ class is used to specify which attribute is used to locate elements on a page. These are the various ways the attributes are used to locate elements on a page:

find_element(By.ID, "id")
find_element(By.NAME, "name")
find_element(By.XPATH, "xpath")
find_element(By.LINK_TEXT, "link text")
find_element(By.PARTIAL_LINK_TEXT, "partial link text")
find_element(By.TAG_NAME, "tag name")
find_element(By.CLASS_NAME, "class name")
find_element(By.CSS_SELECTOR, "css selector")

详细请参考:https://selenium-python.readthedocs.io/locating-elements.html

partial定位: 有时候一个超链接的文本很长,我们如果全部输入,既麻烦,又显得代码很不美观,这时候我们就可以只截取一部分字符串,用这种方法模糊匹配了。

dr = webdriver.Chrome()
dr.get('https://www.csdn.net/')
dr.find_element(By.CSS_SELECTOR, '#www-home-right > div.www-home-silde > div.ContentBlock > div:nth-child(2) > div > span').click()
CSS
dr = webdriver.Chrome()
dr.get('https://www.csdn.net/')
dr.find_element(By.XPATH, '//*[@id="www-home-right"]/div[1]/div[2]/div[1]/div/span').click()
XPATH
dr = webdriver.Chrome()
dr.get('https://www.csdn.net/')
#通过linetext点击‘Java'分类
dr.find_element(By.LINK_TEXT, 'Java').click()
time.sleep(3)
#通过部分linktext点击‘人工智能'分类
dr.find_element(By.PARTIAL_LINK_TEXT, '人工智').click()
LINK
from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get("https://www.example.com")

    # Get element with tag name 'div'
element = driver.find_element(By.TAG_NAME, 'div')

    # Get all the elements available with tag name 'p'
elements = element.find_elements(By.TAG_NAME, 'p')
for e in elements:
    print(e.text)
  
Find Elements From Element
#It is used to track (or) find DOM element which has the focus in the current browsing context.
  from selenium import webdriver
  from selenium.webdriver.common.by import By

  driver = webdriver.Chrome()
  driver.get("https://www.google.com")
  driver.find_element(By.CSS_SELECTOR, '[name="q"]').send_keys("webElement")

    # Get attribute of current active element
  attr = driver.switch_to.active_element.get_attribute("title")
  print(attr)
  
Get Active Element
Xpath解析
模糊查询

//ul/li[text()=“经验教程”] --全文字匹配
self.driver.find_element_by_link_text()
//a[contains(text(), “搜索”)] --模糊文字匹配
//li[contains,(.,‘单次预约’)]
常用解析

解析文字:post_time = selector.xpath(’//div[@class=“video-data”]/span/text()’)

解析结果:[‘295播放\xa0·\xa0’, ‘0弹幕’, ‘2020-12-05 09:00:01’]

普通解析

extract() 返回一个包含有字符串的列表,配合[0]使用

extract_first() 返回列表中的第一个字符串,列表为空没有返回None

get() 提取列表中第1个文本内容(等同于extract_first())

Xpath难点
元素无法点击(报错:该元素不是可点击元素)【客户端渲染,需要研究分析js代码实现同等效果的操作;或者通过火狐浏览器对js代码点击事件进行研究】
例子:头条号微头条上传图片的点击按钮
Message: element not interactable【1、等待元素完全加载。2、换xpath方式进行解析实现(chrome复制的xpath)】
例子:头条号写回答无法定位元素进行send_key
跳转的链接是通过客户端异步加载完成的,当你鼠标放在跳转元素上,无法看到跳转的链接【无法复制链接地址、无法生成新的链接标签页面】,唯有你点击之后才会跳转覆盖当前页面
元素无法交互【下拉框】
先点击下拉图标让数据显示出来再通过xpath直接定位
Xpath解析及难点
1.只查找一个元素的时候:可以使用find_element(),find_elements()
  find_element()会返回一个WebElement节点对象,但是没找到会报错,而find_elements()不会,之后返回一个空列表
2.查找多个元素的时候:只能用find_elements(),返回一个列表,列表里的元素全是WebElement节点对象
3.找到都是节点(标签)
4.如果想要获取相关内容(只对find_element()有效,列表对象没有这个属性)  使用  .text;
5.如果想要获取相关属性的值(如href对应的链接等,只对find_element()有效,列表对象没有这个属性):使用   .get_attribute("href")                                        
find_element()和find_elements()区别

也可以在元素中再查找元素。

相对定位请参考:https://www.cnblogs.com/yunlong-study/p/16587452.html

 

绝对路径:login_form = driver.find_element_by_xpath("/html/body/form[1]")
HTML中的第一个表单元素: login_form = driver.find_element_by_xpath("//form[1]")
属性id=loginForm的元素:login_form = driver.find_element_by_xpath("//form[@id='loginForm']")
 
//div/*                 div下面的所有的元素
//div//p                查找div中的p节点,等于 css_selector里的('div p')
//div/p                查找div的子节点p; 等价于 css_selector里的('div > p')   
//*[@style]        查找所有包含style的所有元素,所有的属性要加@,等于('*[style]'):       
//p[@spec='len']     必须要加引号;等价于 css_selector里的("p[spec='len']")
//p[@id='kw']        xpath中对于id,class与其他元素一视同仁,没有其他的方法
 
//div/p[2]                   选择div下的第二个p节点 ;等价于css_selector里的div>p:nth-of-type(2)  符合p类型的第二个节点
//div/*[2]                   选择div下第二个元素
//div/p[position()=2]        position()=2   指定第二个位置;  等价于上面的 //div/p[2] 
          position()>=2      位置大于等于2
          position()<2       位置小于2
          position()!=2     位置不等于2
//div/p[last()]              选择div下的倒数第一个p节点; last()倒数第一个
//div/p[last()-1]            选择div下的倒数第二个p节点;
//div/p[position()=last()]   倒数第一个
//div/p[position()=last()-1] 倒数第二个
//div/p[position()>=last()-2]倒数第一个,第二个,第三个
//p | //button                       选择所有的p和button,等价于css_selector里的 p, button
//input[@id='kw' and @class='su']    选择id=kw 并且 class=su的input元素
//p[@spec='len']/..      选择p节点的上层节点       此方法在css_selector中没有
//p[@spec='len']/../..   上层节点的上层节点
find_element(By.xpath, "")用法

 

8. Interacting with web elements元素交互

There are only 5 basic commands that can be executed on an element:

click (applies to any element)
send keys (only applies to text fields and content editable elements)
clear (only applies to text fields and content editable elements)
submit (only applies to form elements)
select (see Select List Elements)
from selenium import webdriver
import time  
 
browser = webdriver.Chrome()
browser.get(r'https://www.baidu.com')  
time.sleep(2)
#find需要改一下
# 定位搜索框
input = browser.find_element_by_class_name('s_ipt')
# 输入python
input.send_keys('python')
time.sleep(2)


# 选中新闻按钮
click = browser.find_element_by_link_text('新闻')
# 点击之
click.click()
time.sleep(2)


# 定位搜索框
input = browser.find_element_by_class_name('s_ipt')
# 输入python
input.send_keys('python')
time.sleep(2)
# 清除python
input.clear()

 
# 回车查询
input.submit()
time.sleep(5)

# 关闭浏览器
browser.close()

单选

单选比较好操作,先定位需要单选的某个元素,然后点击一下即可

多选

多选好像也比较容易,依次定位需要选择的元素,点击即可。

操作 checkbox

checkbox 是多选框。

操作 radio

radio 是单选框。

from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from time import sleep

driver = webdriver.Chrome(executable_path="D:\Driver\chromedriver.exe")
driver.get("https://www.baidu.com")

# 定位“设置”
above = driver.find_element_by_xpath('//*[@id="u1"]/a[8]')

# 鼠标悬停出现“搜索设置”
ActionChains(driver).move_to_element(above).perform()
sleep(1)

# 定位“搜索设置”
driver.find_element_by_xpath('//*[@id="wrapper"]/div[6]/a[1]').click()
sleep(1)

# 定位radio按钮
radio_1 = driver.find_element_by_xpath('//*[@id="s1_1"]')
radio_2 = driver.find_element_by_xpath('//*[@id="s1_2"]')
print(radio_1.is_selected())
print(radio_2.is_selected())
example
# coding=utf-8

 

from selenium import webdriver

from time import sleep

 

driver = webdriver.Chrome()

driver.maximize_window()

 

driver.get("http://wenku.baidu.com")

driver.implicitly_wait(8)

 

for i in driver.find_element_by_xpath("//*/input[@type='radio']"): # 实现遍历点击所有的radio 

 print(i)

 sleep(3)

 i.click()

  

sleep(3)
————————————————
版权声明:本文为CSDN博主「空山老师」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_41334453/article/details/102837775
遍历点击所有文档类型的单选框
# coding=utf-8

 

from selenium import webdriver

from time import sleep

 

driver = webdriver.Chrome()

driver.maximize_window()

 

driver.get("http://wenku.baidu.com")

driver.implicitly_wait(8)

 

driver.find_element_by_xpath("//*[@id='t_ppt']").click() # 实现点击PPT文档类型 

sleep(3)
————————————————
版权声明:本文为CSDN博主「空山老师」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_41334453/article/details/102837775
点击其中一种文档类型

下拉框

下拉框的操作相对复杂一些,需要用到Select模块。

先导入该类

from selenium.webdriver.support.select import Select

select模块中有以下定位方法

'''1、三种选择某一选项项的方法'''
 
select_by_index()           # 通过索引定位;注意:index索引是从“0”开始。
select_by_value()           # 通过value值定位,value标签的属性值。
select_by_visible_text()    # 通过文本值定位,即显示在下拉框的值。
 
'''2、三种返回options信息的方法'''
 
options                     # 返回select元素所有的options
all_selected_options        # 返回select元素中所有已选中的选项
first_selected_options      # 返回select元素中选中的第一个选项                  
 
 
'''3、四种取消选中项的方法'''
 
deselect_all                # 取消全部的已选择项
deselect_by_index           # 取消已选中的索引项
deselect_by_value           # 取消已选中的value值
deselect_by_visible_text    # 取消已选中的文本值
from selenium import webdriver
from selenium.webdriver.support.select import Select
import time
 
url = 'file:///C:/Users/Gdc/Desktop/帅哥.html'
 
browser = webdriver.Chrome()
 
browser.get(url)
time.sleep(2)
 
# 根据索引选择
Select(browser.find_element_by_name("帅哥")).select_by_index("2")
time.sleep(2)
# 根据value值选择
Select(browser.find_element_by_name("帅哥")).select_by_value("草儿")
time.sleep(2)
# 根据文本值选择
Select(browser.find_element_by_name("帅哥")).select_by_visible_text("才哥")
time.sleep(2)

#取消所选中的select
# Deselect all selected <option> elements
select_element = driver.find_element(By.ID,'selectElementID')
select_object = Select(select_element)
select_object.deselect_all()

#一些 <select> 元素允许您选择多个选项。您可以使用以下方法确定您的 <select> 元素是否是其中之一
does_this_allow_multiple_selections = select_object.is_multiple
  
 
# 关闭浏览器
browser.close()

 

9. Actions API

a. 鼠标

在 WebDriver 中, 将这些关于鼠标操作的方法封装在 ActionChains 类提供。

click(on_element=None)                    #单击鼠标左键

click_and_hold(on_element=None)               #点击鼠标左键,按住不放

context_click(on_element=None)               #点击鼠标右键

double_click(on_element=None)               #双击鼠标左键

drag_and_drop(source, target)               #拖拽到某个元素然后松开

drag_and_drop_by_offset(source, xoffset, yoffset)     #拖拽到某个坐标然后松开

move_by_offset(xoffset, yoffset)              #鼠标移动到距离当前位置(x,y)

move_to_element(to_element)                #鼠标移动到某个元素

move_to_element_with_offset(to_element, xoffset, yoffset) #将鼠标移动到距某个元素多少距离的位置

release(on_element=None)                  #在某个元素位置松开鼠标左键

perform()                         #执行链中的所有动作

ActionChains的两种写法:

#首先导入模块
from selenium.webdriver.common.action_chains import ActionChains


#链条式方法 
searchElement = driver.find_element_by_id('sb_form_q').send_keys('selenium')
searchButtonElement = driver.find_elemen(By.ID,'sb_form_go')
ActionChains(driver).click(searchButtonElement).perform()


#分布式方法
searchElement = driver.find_element_by_id('sb_form_q').send_keys('selenium')
searchButtonElement = driver.find_element(By.ID,'sb_form_go') 
ActionChainsDriver
= ActionChains(driver).click(searchButtonElement) #这步还能分
ActionChainsDriver.perform()
element_d = self.driver.find_element(By.LINK_TEXT, 'abc')

element_e = self.driver.find_element(By.LINK_TEXT, 'def')
action = ActionChains(self.driver)
'''
action.drag_and_drop(element_d, element_e).perform()    #方法一拖拽
action.click_and_hold(element_d).release(element_e).perform()   #方法二拖拽
      action.click_and_hold(element_d).move_to_element(element_e).release().perform() #方法三拖拽
'''
拖拽
time.sleep(3)
    button = driver.find_element_by_xpath('//*[@id="login-slider"]/div[1]/div[2]/div')
    action = ActionChains(driver)  # 实例化一个action对象
    action.click_and_hold(button).perform()  # 鼠标左键按下不放
    action.move_by_offset(400, 0).perform()  # 平行移动鼠标
    action.reset_actions()
滑动解锁
    inputTag = driver.find_element_by_xpath('//*[@id="loginPage"]/ul/li[1]/div/input')
    inputTag.send_keys('13547584541')
 
    inputTag2 = driver.find_element_by_xpath('//*[@id="loginPage"]/ul/li[2]/div/input')
    inputTag2.send_keys('734888')
 
    driver.find_element_by_xpath('//*[@id="loginPage"]/div/button').click()
登录输入
import pyautogui
 
# 用0.5 秒的时间把光标移动到x,y(437, 151) 位置,y竖向向下增加
pyautogui.moveTo(437, 151, duration=0.5)
pyautogui.click()
 
pyautogui.click(350, 190, button ='left')# 左击
pyautogui.click(350, 190, button ='right')# 右击
Python控制鼠标点击
import pythoncom
import PyHook3 as pyHook
 
 
# 监听到鼠标事件调用
def onMouseEvent(event):
    if (event.MessageName == "mouse left down") and (event.MessageName != "mouse move"):
        # 因为鼠标一动就会有很多mouse move,所以把这个过滤下
        x,y = pag.position() #返回鼠标的坐标
        print(x,y)
 
    return True # 为True才会正常调用,如果为False的话,此次事件被拦截
 
 
    # 创建管理器
    hm = pyHook.HookManager()
    # 监听鼠标
    hm.MouseAll = onMouseEvent
    hm.HookMouse()
    # 循环监听
    pythoncom.PumpMessages()
pyHook监听鼠标并打印位置
def isElementPresent(driver, path):
    #从selenium.common.exceptions 模块导入 NoSuchElementException类
    from selenium.common.exceptions import NoSuchElementException
    try:
        element = driver.find_element_by_xpath(path)
    #原文是except NoSuchElementException, e:
    except NoSuchElementException as e:
        #打印异常信息
        # print(e)
        #发生了NoSuchElementException异常,说明页面中未找到该元素,返回False
        return False
    else:
        #没有发生异常,表示在页面中找到了该元素,返回True
        return True
 
res = isElementPresent(driver, "/html/div")
if res is True:
    # -----
判断节点是否存在

https://blog.csdn.net/qq_44695727/article/details/107334574

 

 b. 键盘

 Selenium WebDriver 中模拟键盘操作提供的接口主要为send_keyskey_downkey_up

  • send_keys:表示发送按键字符。

    对应不同的场景,send_keys来源不同,比如:

    send_keys的参数为输入的键盘字符串,对于特殊按键,比如回车,删除键等,其键盘字符封装到类Keys中。

    下面列举一些常见的键盘操作:

    键盘操作释义
    send_keys('Selenium 你好') 按键发送字符串Selenium 你好
    sned_keys(Keys.ENTER) 回车键(Enter)
    sned_keys(Keys.BACK_SPACE) 删除键(BackSpace)
    sned_keys(Keys.SPACE) 空格键(Space)
    sned_keys(Keys.TAB) 制表键(Tab)
    sned_keys(Keys.ALT) ALT 键
    sned_keys(Keys.CONTROL) Ctrl 键
    sned_keys(Keys.SHIFT) Shift 键
    sned_keys(Keys.ARROW_DOWN) 方向下键(类似的还有Keys.ARROW_UP/Keys.ARROW_LEFT/Keys.ARROW_RIGHT
    sned_keys(Keys.F1) F1 键(类似的还有F2~F12

    除了特殊字符外,send_keys还支持组合按键,只需将组合按键键值传递给该函数即可,比如:

    组合按键释义
    send_keys(Keys.CONTROL,'a') 全选(<Ctrl+a>)
    send_keys(Keys.CONTROL,'c') 复制(<Ctrl+c>)
    send_keys(Keys.CONTROL,'v') 粘贴(<Ctrl+v>)

    示例:如下所示,打开网页后按下<Ctrl+a>全选:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys

driver = webdriver.Chrome()
driver.get('https://www.jianshu.com')

html = driver.find_element(By.CSS_SELECTOR, 'html')
html.send_keys(Keys.CONTROL, 'a')
  • key_down:表示按下给定键,并保持按下状态(不释放)。
    该方法应当只用于 Ctrl 键、Alt 键 和 Shift 键的按键操作。

  • key_up:表示释放指定按键。

key_downkey_up只存在于ActionChains中,因此构建按键动作链时,才可以进行使用。

示例:如下所示,打开网页后按下<Ctrl+a>全选:driver = webdriver.Chrome()

driver.get('https://www.jianshu.com')

# 动作链:按下<Ctrl>,按下 a,松开<Ctrl>
ActionChains(driver).key_down(Keys.CONTROL).send_keys('a').key_up(Keys.CONTROL).perform()

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) 键盘 F1
……
send_keys(Keys.F12) 键盘 F12
键盘常用键操作
    text_input = driver.find_element(By.ID, "textInput")
    ActionChains(driver)\
        .send_keys_to_element(text_input, "abc")\
        .perform()
指定元素
class Keys(object):
    """
    Set of special keys codes.
    """

    NULL = '\ue000'
    CANCEL = '\ue001'  # ^break
    HELP = '\ue002'
    BACKSPACE = '\ue003'
    BACK_SPACE = BACKSPACE
    TAB = '\ue004'
    CLEAR = '\ue005'
    RETURN = '\ue006'
    ENTER = '\ue007'
    SHIFT = '\ue008'
    LEFT_SHIFT = SHIFT
    CONTROL = '\ue009'
    LEFT_CONTROL = CONTROL
    ALT = '\ue00a'
    LEFT_ALT = ALT
    PAUSE = '\ue00b'
    ESCAPE = '\ue00c'
    SPACE = '\ue00d'
    PAGE_UP = '\ue00e'
    PAGE_DOWN = '\ue00f'
    END = '\ue010'
    HOME = '\ue011'
    LEFT = '\ue012'
    ARROW_LEFT = LEFT
    UP = '\ue013'
    ARROW_UP = UP
    RIGHT = '\ue014'
    ARROW_RIGHT = RIGHT
    DOWN = '\ue015'
    ARROW_DOWN = DOWN
    INSERT = '\ue016'
    DELETE = '\ue017'
    SEMICOLON = '\ue018'
    EQUALS = '\ue019'

    NUMPAD0 = '\ue01a'  # number pad keys
    NUMPAD1 = '\ue01b'
    NUMPAD2 = '\ue01c'
    NUMPAD3 = '\ue01d'
    NUMPAD4 = '\ue01e'
    NUMPAD5 = '\ue01f'
    NUMPAD6 = '\ue020'
    NUMPAD7 = '\ue021'
    NUMPAD8 = '\ue022'
    NUMPAD9 = '\ue023'
    MULTIPLY = '\ue024'
    ADD = '\ue025'
    SEPARATOR = '\ue026'
    SUBTRACT = '\ue027'
    DECIMAL = '\ue028'
    DIVIDE = '\ue029'

    F1 = '\ue031'  # function  keys
    F2 = '\ue032'
    F3 = '\ue033'
    F4 = '\ue034'
    F5 = '\ue035'
    F6 = '\ue036'
    F7 = '\ue037'
    F8 = '\ue038'
    F9 = '\ue039'
    F10 = '\ue03a'
    F11 = '\ue03b'
    F12 = '\ue03c'

    META = '\ue03d'
    COMMAND = '\ue03d'
键盘ue编码

pywin32库,有机会了解下。

 

9.属性获取

定位到元素之后,就可以对元素的属性进行获取。

获取元素标签的内容(文本信息):会获取标签之间的文本内容,也可以看节点中class,src等。
get_attribute(‘textContent’)
获取元素内的全部HTML:会获取标签之间的完整 html get_attribute(
'innerHTML')
获取包含选中元素的HTML:获取当前标签的完整 html get_attribute(
'outerHTML')
WebElement.text:获取元素文本内容
WebElement.tag_name:获取元素标签名
WebElement.size:获取元素大小
WebElement.location:获取元素位置
from selenium import webdriver
import time  
 
browser = webdriver.Chrome()
 
browser.get(r'https://www.baidu.com')  
 
logo = browser.find_element_by_class_name('index-logo-src')
print(logo.text)
print(logo.id)
print(logo.location)
print(logo.tag_name)
print(logo.size)
 
# 关闭浏览器
browser.close()
example

 

 10.Information about web elements

 a. Is Displayed

# Navigate to the url
driver.get("https://www.google.com")

# Get boolean value for is element display
is_button_visible = driver.find_element(By.CSS_SELECTOR, "[name='login']").is_displayed()

b. Is Enabled

    # Navigate to url
driver.get("http://www.google.com")

    # Returns true if element is enabled else returns false
value = driver.find_element(By.NAME, 'btnK').is_enabled()
  

c. Is Selected

    # Navigate to url
driver.get("https://the-internet.herokuapp.com/checkboxes")

    # Returns true if element is checked else returns false
value = driver.find_element(By.CSS_SELECTOR, "input[type='checkbox']:first-of-type").is_selected()
  

d. Tag Name

    # Navigate to url
driver.get("https://www.example.com")

    # Returns TagName of the element
attr = driver.find_element(By.CSS_SELECTOR, "h1").tag_name
  

e. Size and Position

    # Navigate to url
driver.get("https://www.example.com")

    # Returns height, width, x and y coordinates referenced element
res = driver.find_element(By.CSS_SELECTOR, "h1").rect
  

f. Get CSS Value

    # Navigate to Url
driver.get('https://www.example.com')

    # Retrieves the computed style property 'color' of linktext
cssValue = driver.findElement(By.LINK_TEXT, "More information...").value_of_css_property('color')

  

g. Text Content

    # Navigate to url
driver.get("https://www.example.com")

    # Retrieves the text of the element
text = driver.find_element(By.CSS_SELECTOR, "h1").text
  

 

11.多窗口切换,多浏览器

比如同一个页面的不同子页面的节点元素获取操作,不同选项卡之间的切换以及不同浏览器窗口之间的切换操作等等。

a. Frame切换

Selenium打开一个页面之后,默认是在父页面进行操作,此时如果这个页面还有子页面,想要获取子页面的节点元素信息则需要切换到子页面进行擦走,这时候switch_to.frame()就来了。如果想回到父页面,用switch_to.parent_frame()即可。 详见https://www.cnblogs.com/yunlong-study/p/16594116.html

 

b. 选项卡切换(窗口)

我们在访问网页的时候会打开很多个页面,在Selenium中提供了一些方法方便我们对这些页面进行操作。

current_window_handle:获取当前窗口的句柄。

window_handles:返回当前浏览器的所有窗口的句柄。

switch_to_window():用于切换到对应的窗口。
from selenium import webdriver
import time
 
browser = webdriver.Chrome()
 
# 打开百度
browser.get('http://www.baidu.com')
# 新建一个选项卡
browser.execute_script('window.open()')
print(browser.window_handles)
# 跳转到第二个选项卡并打开知乎
browser.switch_to.window(browser.window_handles[1])
browser.get('http://www.zhihu.com')
# 回到第一个选项卡并打开淘宝(原来的百度页面改为了淘宝)
time.sleep(2)
browser.switch_to.window(browser.window_handles[0])
browser.get('http://www.taobao.com')

 

c.多浏览器处理 

#导入依赖
import os
from selenium import webdriver
 
 
def test_browser():
    #使用os模块的getenv方法来获取声明环境变量browser
    browser = os.getenv("browser").lower()
    #判断browser的值
    if browser == "headless":
        driver = webdriver.PhantomJS()
    elif browser == "firefox":
        driver = webdriver.Firefox()
    else:
        driver = webdriver.Chrome()
    driver.get("https://ceshiren.com/")
 

 

 12.表单的操作

https://www.cnblogs.com/yunlong-study/p/16594441.html

 

13.设置代理

有认证代理

# -*- coding: utf-8 -*-
# @Time    : 2017/11/15 9:50
# @Author  : 哎哟卧槽
# @Site    : 
# @File    : pubilc.py
# @Software: PyCharm

import string
import zipfile

def create_proxyauth_extension(proxy_host, proxy_port,
                               proxy_username, proxy_password,
                               scheme='http', plugin_path=None):
    """代理认证插件

    args:
        proxy_host (str): 你的代理地址或者域名(str类型)
        proxy_port (int): 代理端口号(int类型)
        proxy_username (str):用户名(字符串)
        proxy_password (str): 密码 (字符串)
    kwargs:
        scheme (str): 代理方式 默认http
        plugin_path (str): 扩展的绝对路径

    return str -> plugin_path
    """
    

    if plugin_path is None:
        plugin_path = 'vimm_chrome_proxyauth_plugin.zip'

    manifest_json = """
    {
        "version": "1.0.0",
        "manifest_version": 2,
        "name": "Chrome Proxy",
        "permissions": [
            "proxy",
            "tabs",
            "unlimitedStorage",
            "storage",
            "<all_urls>",
            "webRequest",
            "webRequestBlocking"
        ],
        "background": {
            "scripts": ["background.js"]
        },
        "minimum_chrome_version":"22.0.0"
    }
    """

    background_js = string.Template(
    """
    var config = {
            mode: "fixed_servers",
            rules: {
              singleProxy: {
                scheme: "${scheme}",
                host: "${host}",
                port: parseInt(${port})
              },
              bypassList: ["foobar.com"]
            }
          };

    chrome.proxy.settings.set({value: config, scope: "regular"}, function() {});

    function callbackFn(details) {
        return {
            authCredentials: {
                username: "${username}",
                password: "${password}"
            }
        };
    }

    chrome.webRequest.onAuthRequired.addListener(
                callbackFn,
                {urls: ["<all_urls>"]},
                ['blocking']
    );
    """
    ).substitute(
        host=proxy_host,
        port=proxy_port,
        username=proxy_username,
        password=proxy_password,
        scheme=scheme,
    )
    with zipfile.ZipFile(plugin_path, 'w') as zp:
        zp.writestr("manifest.json", manifest_json)
        zp.writestr("background.js", background_js)

    return plugin_path
#使用
from
selenium import webdriver from common.pubilc import create_proxyauth_extension proxyauth_plugin_path = create_proxyauth_extension( proxy_host="XXXXX.com", proxy_port=9020, proxy_username="XXXXXXX", proxy_password="XXXXXXX" ) co = webdriver.ChromeOptions() # co.add_argument("--start-maximized") co.add_extension(proxyauth_plugin_path) driver = webdriver.Chrome(executable_path="C:\chromedriver.exe", chrome_options=co) driver.get("http://ip138.com/") print(driver.page_source)

无认证代理

options = webdriver.ChromeOptions()
options.add_argument('--proxy-server=http://ip:port')  
driver = webdriver.Chrome(executable_path="C:\chromedriver.exe", chrome_options=0ptions)
driver.get("http://ip138.com/")
print(driver.page_source)

 example:

# 注意端口号
PROXY = '127.0.0.1:3582'
# 设置代理
webdriver.DesiredCapabilities.CHROME['proxy'] = {
    'httpProxy': PROXY,
    'sslProxy': PROXY,
    "proxyType": "MANUAL",
}

driver = webdriver.Chrome()
driver.get('https://httpbin.org/headers')
print(driver.page_source)

 

14. Options和ChromeOptions

https://www.cnblogs.com/yunlong-study/p/16595505.html

 

14.js执行

 https://www.cnblogs.com/yunlong-study/p/16597987.html

 

15.弹框处理机制

  • 在页面操作中有时会遇到JavaScript所生成的alert、confirm以及prompt弹框,可以使用switch_to.alert()方法定位到。然后使用 text/ accept / dismiss / send_keys等方法进行操作。
  • 操作alert常用的方法:
    • switch_to.alert:获取当前页面上的警告框。
    • text:返回alert / confirm / prompt中的文字信息。
    • accept():接受现有警告框。
    • dismiss():解散现有警告框。
    • send_keys(keysToSend):发送文本至警告框。keysToSend:将文本发送至警告框。

模拟弹框

  • 在Console里输入window.alert("这是一个弹框")

alert窗口处理案例

 

 

from time import sleep
from selenium import webdriver
from selenium.webdriver import ActionChains

class TestAlert:
    def setup(self):
        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.implicitly_wait(5)

    def teardown(self):
        self.driver.quit()

    def test_alert(self):
        self.driver.get("https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable")
        self.driver.switch_to.frame("iframeResult") # 切换到iframe中
        drag = self.driver.find_element_by_id("draggable")
        drop = self.driver.find_element_by_id("droppable")
        action = ActionChains(self.driver)
        action.drag_and_drop(drag, drop).perform() # 将元素1拖拽到元素2
        sleep(2)
        alert = self.driver.switch_to.alert
        print(alert.text)   # 打印弹窗信息
        alert.accept()    # 点击弹框的确定
        self.driver.switch_to.default_content() # 切换到默认frame中
        self.driver.find_element_by_id("submitBTN").click()

 也可参考:https://blog.csdn.net/weixin_42056525/article/details/109135016

 

 16.文件上传

input标签可以直接使用send_key(文件地址)上传文件
用法:
el = driver.find_element(By.ID, '上传按钮id')
el.send_keys("文件路径+文件名")
案例
打开百度图片首页:https://image.baidu.com/
点击摄像机按钮
点击选择文件按钮
选择本地文件上传
from time import sleep
from selenium import webdriver

class TestFile:
    def setup(self):
        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.implicitly_wait(5)

    def teardown(self):
        self.driver.quit()

    def test_file_upload(self):
        self.driver.get("https://image.baidu.com/")
        self.driver.find_element(By.ID, "sttb").click()
        self.driver.find_element(By.ID, "uploadImg").send_keys("1.png") 
     sleep(
2)

 

17.截屏

https://www.cnblogs.com/yunlong-study/p/16594153.html

 

18. cookie操作

Selenium WebDriver 中对 Cookie 的操作,主要有如下几种:

Cookie 操作释义
get_cookies() 获取所有 Cookie 信息
get_cookie(name) 获取名称为 name 的 Cookie 信息
add_cookie(cookie_dict) 添加 Cookie
delete_cookie(name) 删除名称为 name 的 Cookie
delete_all_cookies() 清空 Cookie
from selenium import webdriver

with webdriver.Chrome() as driver:
    driver.get('https://baidu.com')

    print('------- Cookie Info (Original) -------------')
    # 打印 Cookie 信息
    print(driver.get_cookies())

    cookie_dict = {
        'name': 'Whyn_cookie_id',
        'value': 'Whyn_cookie_value',
        # 'path': r'/',
        # 'secure':False
        # 'expiry': 162721599
    }
    # 添加 Cookie
    driver.add_cookie(cookie_dict)
    print('------- Cookie Info (Add) -------------')
    for cookie in driver.get_cookies():
        print('''
        {{
            "domain": "{domain}",
            "{name}": {value},
            "path": {path},
            "secure": {secure},
            "expiry": {expiry}
        }}'''.format(
            domain=cookie.get('domain', None),
            name=cookie['name'],
            value=cookie['value'],
            path=cookie.get('path', '/'),
            secure=cookie.get('secure', False),
            expiry=cookie.get('expiry', None)
        ))

    # 删除 Cookie
    driver.delete_cookie('Whyn_cookie_id')
    print('------- Cookie Info (Delete) -------------')
    for cookie in driver.get_cookies():
        print('{"%s":"%s"}' %(cookie['name'],cookie['value']))
    
    # 清空 Cookie
    print('------- Cookie Info (Clear) -------------')
    driver.delete_all_cookies()
    for cookie in driver.get_cookies():
        print('{"%s":"%s"}' %(cookie['name'],cookie['value']))

 

巧用 Cookie (纯记录)

 

 19.请求拦截

请求拦截

 

 20.反爬措施

检测异常行为:如反复访问,地址栏跳转到网站深处,频繁访问等。可通过构建代理ip池以及优化爬取逻辑等规避

加密网站信息:一种加密方法是,将一些字符串转为图片,这些图片在html中会变为乱码。碰到这些,需要具体问题具体分析

检测selenium:禁止selenium等自动控制软件访问,可通过设置以及js调整

验证码:可通过设置程序自动解验证码或人工守在爬虫旁解决

检测请求头:header中的Cookie、Referer、User-Agent都是检查点,在requests中需要专门设置,selenium一般不会遇到这个问题

selenium反爬

由于使用 Selenium 可以很方便对网页进行自动化操作,这同时也表示说 Selenium 是一个非常好用的爬虫处理器。

也因此,有一些网站就增加了对 Selenium 的检测,以禁止 Selenium 进行爬虫操作。

目前使用最多的检测 Selenium 爬取的方式为:通过检测浏览器当前页面的window.navigator,如果其包含有webdriver这个属性,那就表示使用了 Selenium 进行爬取,反之,如果检测到webdriverundefined,则表示正常操作。

比如对于网站:https://antispider1.scrape.cuiqingcai.com/

如果我们直接使用 Selenium 进行爬取,如下所示:

driver = webdriver.Chrome()
driver.get('https://antispider1.scrape.cuiqingcai.com/')
print(driver.page_source)

运行上述代码后,可以看到如下结果:

 

 

 而如果想解决这个问题,依据先前我们介绍的原理可知,只要我们能将window.navigator.webdriver设置为undefined即可,
但是我们不能简单地调用如下代码进行设置:

driver.execute_script('Object.defineProperty(navigator, "webdriver", {get: () => undefined})')

因为WebDriver.execute_script(..)是在页面加载完成后才执行,在时序上慢于网页检测。

因此,我们的变量修改必须尽早地在页面加载完成时进行设置。

而 Selenium 中提供的相应机制为:CDP(即 Chrome Devtools-Protocol,Chrome 开发工具协议)
对应的接口为:WebDriver.execute_cdp_cmd(cmd, cmd_args)

对应于上述示例,如果我们想要尽早在页面加载完成时执行我们的 JavaScript 脚本,需要使用的 CDP 命令为:Page.addScriptToEvaluateOnNewDocument,具体的代码如下所示:

options = ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-automation'])
options.add_experimental_option('useAutomationExtension', False)

browser=webdriver.Chrome(options=options)
browser.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'
})
browser.get('https://antispider1.scrape.cuiqingcai.com/')

 

通过调整浏览器选项,提供稳定运行环境并进行反爬。

一般来说,在声明浏览器前后,加上这堆东西,就不会被识别出来,此时还能威胁到我们的只剩异常访问和验证码。验证码的解决方案会在下一点中介绍,但异常访问只能靠优化爬取或者代理池来解决。

options = webdriver.ChromeOptions()
#稳定运行
options.add_argument('-enable-webgl')#解决 GL is disabled的问题
options.add_argument('--no-sandbox')  # 解决DevToolsActivePort文件不存在的报错
options.add_argument('--disable-dev-shm-usage') 
options.add_argument('--ignore-gpu-blacklist') 
options.add_argument('--allow-file-access-from-files') 

#反爬
options.add_experimental_option("excludeSwitches", ["enable-automation"])# 模拟真正浏览器
options.add_experimental_option('useAutomationExtension', False)

driver = webdriver.Chrome(options=options)#声明浏览器
#模拟真正浏览器
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
  "source": """
    Object.defineProperties(navigator,{webdriver:{get:() => false}});
  """
})

 

动态操作

滚动条到底有多长?

大家肯定见过这样的网站:它不会一次加载完所有信息,需要我们拖滚动条才能继续加载。然而,这个滚动条,到底拖多久才是个头?

我们以百度图片搜索"传承换心"为例,尝试将它的滚动条拖到底端,加载所有图片

from selenium import webdriver
import time
driver = webdriver.Chrome()#声明浏览器对象
try:
    driver.get("https://image.baidu.com")#相当于地址栏跳转
    box = driver.find_element_by_id('kw')#找到输入框
    box.click() 
    box.send_keys("传承换心")#先点一下,再输入内容
    button=driver.find_element_by_xpath("//input[@type='submit']")#找到按钮"百度一下"
    button.click - Domain Name For Sale | Dan.com()#按按钮
    
    js='window.scrollTo(0,document.body.scrollHeight)' #下滑到底部
    js2='return document.documentElement.scrollHeight' #检测当前滑动条位置

    #对于内嵌滚动条(不是网页边缘,而是网页里面可以拖动的东西),需要用getElements把这个元素找出来,再和刚才做一样的操作
    #js='document.getElementsByClassName("unifycontainer-two-wrapper")[0].scrollTop=1000000' 
    #js2='return document.getElementsByClassName("unifycontainer-two-wrapper")[0].scrollHeight'
    
    height=-1
    now=driver.execute_script(js2)
    #当滑动条位置不再被“下滑到底部”这一行为影响,说明滑动条真的到了底部
    while height!=now:
        height=now
        driver.execute_script(js)
        time.sleep(1)
        now=driver.execute_script(js2)
    
    time.sleep(5)#对于想要看结果的程序,在最后设置一下暂停
    driver.close()
    #当然,也可以直接删掉close语句,让浏览器一直开着……

except Exception as e:
    print (e)

 

验证码

验证码,据我所知有三个对策

1.使用cookie避免输入验证码

参见链接:Selenium中遇到验证码问题的处理_嘉 诚的博客-CSDN博客_selenium验证码处理

2.自动识别验证码

验证码种类多样,难以一一列举,和网站加密一样,需要具体问题具体分析

3.最为暴力的人工法

前两种方法泛用性不强,自动识别需要自己设定程序,而有些网站无视cookie,每次登陆都需要验证码。

我使用的方法是在需要输入验证码的环节设置一个time.sleep()。在time.sleep期间,我们可以对selenium打开的浏览器进行操作,比如人工输入验证码,跳转几个页面等。只要在sleep结束后,你去到的网页能够接上后续程序,就不会有任何问题。

许多大型爬虫机构依然使用人工法,因为人工法对劳动力质量和数量要求都不高。

 

21.断言

1. selenium 提供了三种模式的断言:assert 、verify、waitfor
  Assert 失败时,该测试将终止。
  Verify 失败时,该测试将继续执行,并将错误记入日显示屏 。也就是说允许此单个 验证通过。确保应用程序在正确的页面上
  Waitfor 用于等待某些条件变为真。可用于 AJAX 应用程序的测试。如果该条件为真,他们将立即成功执行。如果该条件不为真,则将失败并暂停测试。直到超过当前所设定的超过时间。一般跟setTimeout时间一起使用。

 

2. 自动化测试中,结果判断有三种方式:截图对比、控件对比、日志分析。其中控件对比就是断言,当执行完一定的自动化测试逻辑后,

可以将 获取控件上的信息与预期的信息进行对比,判断测试结果是否通过。

简单例子:新增数据,保存,给出提示:保存成功。对这个事件进行结果判断,即断言

 

3.三种方法

if ...else ...判断进行断言

from time import *
from selenium import webdriver
def login(user="admin",pwd="123456"):
  driver = webdriver.Chrome()
  driver.implicitly_wait(10)
  driver.get("http://192.168.1.110:8080/cms")
  driver.maximize_window()
  sleep(1)
  driver.find_element_by_id("userAccount").send_keys(user)
  sleep(1)
  driver.find_element_by_id("loginPwd").send_keys(pwd)
  sleep(1)
  driver.find_element_by_id("loginBtn").click()  #登录
  sleep(1)
  users = driver.find_element_by_class_name("c-white").text  #获取用户名
  sleep(1)
  driver.quit()
  if users[6:] == user:
    pass
  else:
    raise AssertionError

if __name__ == '__main__':
  login()
View Code
from time import *
from selenium import webdriver
def login(user="admin",pwd="123456"):
  driver = webdriver.Chrome()
  driver.implicitly_wait(10)
  driver.get("http://192.168.1.110:8080/cms")
  driver.maximize_window()
  sleep(1)
  driver.find_element_by_id("userAccount").send_keys(user)
  sleep(1)
  driver.find_element_by_id("loginPwd").send_keys(pwd)
  sleep(1)
  driver.find_element_by_id("loginBtn").click()  #登录
  sleep(1)
  users = driver.find_element_by_class_name("c-white").text  #获取用户名
  sleep(1)
  driver.quit()
  if users[6:7] == user:
    pass
  else:
    assert False

if __name__ == '__main__':
  login()
View Code

 

try ... except ...断言

from time import *
from selenium import webdriver
def fatie(title,body):
  dr = login()
  sleep(2)
  dr.find_element_by_partial_link_text("版块").click()
  sleep(1)
  dr.find_element_by_id("subject").send_keys(title)
  sleep(1)
  dr.find_element_by_id("fastpostmessage").send_keys(body)
  sleep(2)
  dr.find_element_by_name("topicsubmit").click()
  sleep(2)
  try:
    dr.find_element_by_id("thread_subject")
  except:
    raise AssertionError
  else:
    pass
  sleep(3)
  dr.quit()
View Code

 

assert断言(基于unittest)

  • assertIn(arg1, arg2, msg=None)   验证 arg1 是 arg2 的子串,不是则 fail
  • assertNotIn(arg1, arg2, msg=None)   验证 arg1 不是 arg2 的子串,是则 fail
  • assertEqual(arg1, arg2, msg=None)   验证 arg1=arg2,不等则 fail
  • assertNotEqual(arg1, arg2, msg=None)   验证 arg1 != arg2, 相等则 fail
import time
import unittest

class Test(unittest.TestCase):
  def test01(self):
    self.assertEqual(2,2,msg="test01 error!")

  def test02(self):
    self.assertNotEqual(1,2,msg="test02 error!")

  def test03(self):
    self.assertIn("fang","xinfangshuo",msg="test03 error!")

  def test04(self):
    self.assertNotIn("xing","xinfangshuo",msg="test04 error!")

  def tearDown(self):
    time.sleep(1)

if __name__ == '__main__':
  unittest.main()
View Code
可以根据自己的需要,修改判断条件,下面这些断言方法借鉴其他帖子,可以作为参考

断言常用的有:
assertLocation(判断当前是在正确的页面)、

assertTitle(检查当前页面的 title 是否正确)、
assertValue(检查 input 的值, checkbox 或 radio,有值为”on”无为”off”)、
assertSelected(检查 select 的下拉菜单中选中是否正确)、
assertSelectedOptions(检查下拉菜单中的选项的是否正确)、
assertText(检查指定元素的文本)、
assertTextPresent(检查在当前给用户显示的页面上是否有出现指定的文本)、
assertTextNotPresent(检查在当前给用户显示的页面上是否没有出现指定的文本)、
assertAttribute(检查当前指定元素的属性的值)、
assertTable(检查 table 里的某个 cell 中的值)、
assertEditable(检查指定的 input 是否可以编辑)、

assertNotEditable(检查指定的 input 是否不可以编辑)、
assertAlert(检查是否有产生带指定 message 的 alert 对话框)、
verifyTitle (检查预期的页面标题)
verifyTextPresent (验证预期的文本是否在页面上的某个位置)
verifyElementPresent(验证预期的UI元素,它的HTML标签的定义,是否在当前网页上)
verifyText(核实预期的文本和相应的HTML标签是否都存在于页面上)
verifyTable(验证表的预期内容)
waitForPageToLoad(暂停执行,直到预期的新的页面加载)
waitForElementPresent (等待检验某元素的存在。为真时,则执行。)

验证和断言的区别:验证失败后不影响脚本的继续执行,断言失败后将停止脚本的执行。

异常类型
AssertionError:assert语句失败

AttributeError:试图访问一个对象没有的属性

IOError:输入输出异常,基本是无法打开文件

ImportError:无法引入模块或者包,基本是路径问题

IndentationError:语法错误,代码没有正确的对齐

IndexError:下标索引超出序列边界

KeyError:试图访问字典里不存在的键

KeyboadrInterrupt:Ctrl+c被按下

NameError:使用一个还未赋值对象的变量

SyntaxError:python代码逻辑语法错误,不能执行

TypeError:传入的对象类型与要求不符

UnboundLocalError:试图访问一个还未设置的全局变量,基本上是由于另有一个同名的全局变量,导致你以为在访问

ValueError:传入一个不被期望的值,即使类型正确
常用的断言和异常类型

IDE 断言

 

22.BiDirectional API

23.Chrome DevTools

24.Selenium 监听器

25.使用selenium4监听网络请求

 

26.页面加载超时时间

1. 利用selenium请求网页的时候,有时因为某种原因使得页面一直处于加载状态,使得源代码一直不能返回。这种情况可以全局设置driver的加载时间,超时后停止加载然后强制返回源代码。

driver = webdriver.Chrome()

初始化driver对象后,设置一下两个超时时间

driver.set_page_load_timeout(10) #页面加载超时时间

driver.set_script_timeout(10) #页面js加载超时时间

由于超时后selenium会报错,所以要添加异常处理

try:

browser.get('http://www.amazon.com/dp/B001UPMC1Y')

except TimeoutException: # 报错后就强制停止加载 # 这里是js控制

browser.execute_script('window.stop()')

print(browser.page_source)

 

2. chromedriver更新后,总是timeout 然后driver断开

设置pageLoadStrategy为none。

driver.get(url)方法要根据desired_capabilities的pageLoadStrategy字段的值,确定执行结束的时机:
(1)NONE:html下载完成,不等待解析完成即返回;
(2)EAGER:要等待整个dom树加载完成,即DOMContentLoaded这个事件完成,仅对html的内容进行下载解析;
(3)NORMAL: 等待整个界面加载完成(指对html和子资源的下载与解析,如JS文件,图片等,不包括ajax).

def method1():
    desired_capabilities = DesiredCapabilities.CHROME
    desired_capabilities["pageLoadStrategy"] = "none"
    driver = webdriver.Chrome(executable_path = r'F:\webdriver\chromedriver.exe',  desired_capabilities = desired_capabilities)
    driver.get('https://www.baidu.com')
    driver.quit()

 

27. 页面加载策略设置

首选需要明白的一点是,如果什么都不设置,通常,以chrome浏览器为例,所有的元素定位是在页面被完全加载后(页面tab不再转圈)才开始。
有时候其实想要的元素已经加载出来了,只是页面还在加载其他东西,例如图片,此时若不想继续等待直接执行元素定位操作,则需要在创建driver的时候设置页面加载策略:
当调用driver.get("https://xxxx.xxx.xxx")来访问某页面时,get方法通常会阻塞浏览器直到页面完全加载后才执行后面的动作,若一个页面加载过慢,则会导致get方法一直阻塞。有时候希望页面在加载过程中就开始检测元素是否存在,而不是等到页面加载完了才开始检测,想要实现这个效果,可以用DesiredCapabilities类下的setPageLoadStrategy方法(Python,Chrome浏览器):

from selenium import webdriver

from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.support.ui import WebDriverWait

desired_capabilities = DesiredCapabilities.CHROME # 修改页面加载策略
desired_capabilities["pageLoadStrategy"] = "none" # 注释这两行会导致最后输出结果的延迟,即等待页面加载完成再输出
#注:2021/12/20 在谷歌浏览器96.0.4664.110上验证出效果。


driver = webdriver.Chrome('browsers/chromedriver.exe')
wait = WebDriverWait(driver, 10) #后面可以使用wait对特定元素进行等待

driver.get('http://qzone.qq.com/')
# some code to work.

print("Reach end.")

 

其中PageLoadStrategy有三种选择:

(1) none: 当html下载完成之后,不等待解析完成,selenium会直接返回

(2) eager: 要等待整个dom树加载完成,即DOMContentLoaded这个事件完成,仅对html的内容进行下载解析。注:在谷歌浏览器96.0.4664.110验证不支持eager。

(3) normal: 即正常情况下,selenium会等待整个界面加载完成(指对html和子资源的下载与解析,如JS文件,图片等,不包括ajax

以下这段来自https://blog.csdn.net/wkb342814892/article/details/81611737,感谢原作者

实际上,对于一个新加载的dom,页面啥时候开始接受命令由页面的加载策略决定,也就是说,我们通过修改页面加载策略,可以使页面即使处于加载中,也能接受我们的命令,从这点可以解决webdriver.get的阻塞问题。而每类webdriver都有一个对应的配置文件放在特定的类DesiredCapabilities里面,通过修改里面的pageLoadStrategy,可以使webdriver的页面加载策略发生改变。

上面的代码用了最后一种解析方式——none,不作等待,直接返回,然后在后面的代码中可以用explicit_wait或者implicit_wait等方式来对特定元素进行等待捕捉。

 

28. Page Object设计模式

链接 ,链接2

 

 

 29.实战

https://www.jianshu.com/nb/49874782

 

 更多内容请看:https://www.selenium.dev/documentation/webdriver/additional_features/fileupload/

 上面部分内容,我没实际敲过。有时间,要全部过一下,加官网的document。

 
posted @ 2022-08-22 14:20  云long  阅读(255)  评论(0编辑  收藏  举报