selenium使用总结

时间:2024-01-25 12:28:47

selenium

selenium是一个支持各大浏览器的自动化测试工具,包括 Chrome,Safari,Firefox ,ie等。再构造爬虫时,如果我们加入了User-Agent,那么变伪装成了浏览器,可以骗过一些技术水平不太高的网站。但如果使用selenium,则就不是伪装浏览器,而是真正的用浏览器去访问。有时我们可能会遇到这种情况,前端页面展示出来的东西,并不在后端源代码中,自然无法通过使用requests请求获得源码进行爬取。这时候就可以使用selenium进行爬取数据,因为他就是用真实的浏览器去访问页面的,所以出现的内容和我们在前端看到的是一模一样的。

0x01:selenium安装

python下使用pip安装

pip install selenium

此外,因为selenium是配合浏览器一起使用,所以需要下载浏览器的驱动(webdriver),以chrome为例
chrome的webdriver: http://chromedriver.storage.googleapis.com/index.html
不同的Chrome的版本对应的chromedriver.exe 版本也不一样,下载时不要搞错了。如果是最新的Chrome, 下载最新的chromedriver.exe 就可以了。把chromedriver的路径也加到环境变量里。

检测:运行这段代码,会自动打开百度

from selenium import webdriver      # 引入webdriver api
browser = webdriver.Chrome()        # 使用chrome浏览器声明一个webdriver对象
browser.get('http://www.baidu.com/')    # 表示使用chrome以get的方式请求百度的url
driver.find_element_by_id("kw").send_keys("selenium")   # 检索到百度的输入框,输入selenium
driver.find_element_by_id("su").click() # 检索到百度的搜索按钮并点击

0x02:元素选取
在上面的实例中,最重要的就是找到搜索框和搜索按钮对应的元素,然后再进行相应的操作(输入关键字、点击),强大的selenium提供了多种提取元素的方法。

单个元素提取

find_element_by_id      # 通过元素id
find_element_by_name    # 通过name属性
find_element_by_xpath   # 通过xpath
find_element_by_link_text   # 通过链接文本
find_element_by_partial_link_text
find_element_by_tag_name    # 通过标签名
find_element_by_class_name      # 通过class名称定位
find_element_by_css_selector    # 通过css选择器定位

多个元素提取,返回一个列表

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

0x03:操作元素方法

  • clear 清除元素的内容:clear(self)
  • send_keys 模拟按键输入:send_keys(self, *value)
  • click 点击元素:click(self)
  • submit 提交表单:submit(self)
  • 获取元素属性:get_attribute(self, name)
  • 获取元素文本:text

0x04:页面操作方法
from selenium import webdriver

  • 打开浏览器:driver = webdriver.Chrome()
  • 请求一个url:driver.get("www.baidu.com")
  • 返回当前页面的title:title = driver.title
  • 返回当前页面的url:url = driver.current_url
  • 返回当前页面的源码:source = driver.page_source
  • 关闭当前页面:driver.close()
  • 注销并关闭浏览器:driver.quit()
  • 浏览器前进:driver.forward()
  • 浏览器后退:driver.back()
  • 刷新当前页面:driver.refresh()
  • 获取当前session中的全部cookie:get_cookies(self)
  • 获取当前会中中的指定cookie:get_cookie(self, name)
  • 在当前会话中添加cookie:add_cookie(self, cookie_dict)
  • 添加浏览器User-Agent:
    options.add_argument('User-Agent=Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30')
  • 添加设置项Chrome Options:
    options = webdriver.ChromeOptions()
    options.add_argument('xxxx')
    driver = webdriver.Chrome(chrome_options=options)

0x05:页面等待
既然selenium是使用浏览器发送请求,那么势必会加载一些东西,而且现在的网页越来越多采用了ajax技术。如果代码运行到了提取元素的地方,而这个元素尚未被加载,那么就会报错。为了解决这个问题,selenium提供了两种等待方式,隐式等待显示等待。隐式等待是等待特定的时间,显式等待是指定某一条件直到这个条件成立时继续执行。

  • 隐式等待
    隐式等待比较简单,就是简单地设置一个等待时间,单位为秒。

      from selenium import webdriver
    
      driver = webdriver.Chrome()
      driver.implicitly_wait(10) # seconds
      driver.get("http://somedomain/url_that_delays_loading")
      myDynamicElement = driver.find_element_by_id("myDynamicElement")
  • 显式等待
    显式等待指定某个条件,然后设置最长等待时间。如果在这个时间还没有找到元素,那么便会抛出异常了。

      from selenium import webdriver
      from selenium.webdriver.support.ui import WebDriverWait
      driver = webdriver.Chrome()
      driver.get("http://somedomain/url_that_delays_loading")
      try:
          element = WebDriverWait(driver, 10).until(
              EC.presence_of_element_located((By.ID, "myDynamicElement"))
          )
      finally:
          driver.quit()

wait模块的WebDriverWait类是显性等待类,参数如下:

WebDriverWait(driver, 超时时长, 调用频率, 忽略异常).until(可执行方法, 超时时返回的信息)

这里需要特别注意的是until或until_not中的可执行方法method参数,很多人传入了WebElement对象,如下:

WebDriverWait(driver, 10).until(driver.find_element_by_id('kw'))  # 错误

这是错误的用法,这里的参数一定要是可以调用的,即这个对象一定有 call() 方法,否则会抛出异常:

TypeError: 'xxx' object is not callable

在这里,你可以用selenium提供的 expected_conditions 模块中的各种条件,也可以用WebElement的 is_displayed() 、is_enabled()、is_selected() 方法,或者用自己封装的方法都可以。那么接下来我们看一下selenium提供的条件有哪些:

expected_conditions:

```xpected_conditions是selenium的一个模块,其中包含一系列可用于判断的条件:

selenium.webdriver.support.expected_conditions(模块)

这两个条件类验证title,验证传入的参数title是否等于或包含于driver.title
title_is
title_contains

这两个人条件验证元素是否出现,传入的参数都是元组类型的locator,如(By.ID, 'kw')
顾名思义,一个只要一个符合条件的元素加载出来就通过;另一个必须所有符合条件的元素都加载出来才行
presence_of_element_located
presence_of_all_elements_located

这三个条件验证元素是否可见,前两个传入参数是元组类型的locator,第三个传入WebElement
第一个和第三个其实质是一样的
visibility_of_element_located
invisibility_of_element_located
visibility_of

这两个人条件判断某段文本是否出现在某元素中,一个判断元素的text,一个判断元素的value
text_to_be_present_in_element
text_to_be_present_in_element_value

这个条件判断frame是否可切入,可传入locator元组或者直接传入定位方式:id、name、index或WebElement
frame_to_be_available_and_switch_to_it

这个条件判断是否有alert出现
alert_is_present

这个条件判断元素是否可点击,传入locator
element_to_be_clickable

这四个条件判断元素是否被选中,第一个条件传入WebElement对象,第二个传入locator元组
第三个传入WebElement对象以及状态,相等返回True,否则返回False
第四个传入locator以及状态,相等返回True,否则返回False
element_to_be_selected
element_located_to_be_selected
element_selection_state_to_be
element_located_selection_state_to_be

最后一个条件判断一个元素是否仍在DOM中,传入WebElement对象,可以判断页面是否刷新了
staleness_of```

上面是所有17个condition,与until、until_not组合能够实现很多判断,如果能自己灵活封装,将会大大提高脚本的稳定性。

0x06:鼠标操作
在现实的自动化测试中关于鼠标的操作不仅仅是click()单击操作,还有很多包含在ActionChains类中的操作。如下:

  • context_click(elem) 右击鼠标点击元素elem,另存为等行为
  • double_click(elem) 双击鼠标点击元素elem,地图web可实现放大功能
  • drag_and_drop(source,target) 拖动鼠标,源元素按下左键移动至目标元素释放
  • move_to_element(elem) 鼠标移动到一个元素上
  • click_and_hold(elem) 按下鼠标左键在一个元素上
  • perform() 在通过调用该函数执行ActionChains中存储行为

举例如下图所示,获取通过鼠标右键另存为百度图片logo。代码:

import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
 
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
 
#鼠标移动至图片上 右键保存图片
elem_pic = driver.find_element_by_xpath("//div[@id='lg']/img")
print elem_pic.get_attribute("src")
action = ActionChains(driver).move_to_element(elem_pic)
action.context_click(elem_pic)
 
#重点:当右键鼠标点击键盘光标向下则移动至右键菜单第一个选项
action.send_keys(Keys.ARROW_DOWN)
time.sleep(3)
action.send_keys('v') #另存为
action.perform()
 
#获取另存为对话框(失败)
alert.switch_to_alert()
alert.accept()

0x07:键盘操作
在webdriver的Keys类中提供了键盘所有的按键操作,当然也包括一些常见的组合键操作如Ctrl+A(全选)、Ctrl+C(复制)、Ctrl+V(粘贴)。

  • send_keys(Keys.ENTER) 按下回车键
  • send_keys(Keys.TAB) 按下Tab制表键
  • send_keys(Keys.SPACE) 按下空格键space
  • send_keys(Kyes.ESCAPE) 按下回退键Esc
  • send_keys(Keys.BACK_SPACE) 按下删除键BackSpace
  • send_keys(Keys.SHIFT) 按下shift键
  • send_keys(Keys.CONTROL) 按下Ctrl键
  • send_keys(Keys.ARROW_DOWN) 按下鼠标光标向下按键
  • 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

这里使用的例子参考虫师的书籍《selenium2 python自动化测试》

import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
 
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
 
#输入框输入内容
elem = driver.find_element_by_id("kw")
elem.send_keys("Eastmount CSDN")
time.sleep(3)
 
#删除一个字符CSDN 回退键
elem.send_keys(Keys.BACK_SPACE)
elem.send_keys(Keys.BACK_SPACE)
elem.send_keys(Keys.BACK_SPACE)
elem.send_keys(Keys.BACK_SPACE)
time.sleep(3)
 
#输入空格+"博客"
elem.send_keys(Keys.SPACE)
elem.send_keys(u"博客")
time.sleep(3)
 
#ctrl+a 全选输入框内容
elem.send_keys(Keys.CONTROL,'a')
time.sleep(3)
 
#ctrl+x 剪切输入框内容
elem.send_keys(Keys.CONTROL,'x')
time.sleep(3)
 
#输入框重新输入搜索
elem.send_keys(Keys.CONTROL,'v')
time.sleep(3)
 
#通过回车键替代点击操作
driver.find_element_by_id("su").send_keys(Keys.ENTER)
time.sleep(3)
 
driver.quit()