selenium

Posted woaixuexi9999

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了selenium相关的知识,希望对你有一定的参考价值。

一、什么是Selenium

selenium 是一套完整的web应用程序测试系统,包含了测试的录制(selenium IDE),编写及运行(Selenium Remote Control)和测试的并行处理(Selenium Grid)。Selenium的核心Selenium Core基于JsUnit,完全由javascript编写,因此可以用于任何支持JavaScript的浏览器上。

selenium可以模拟真实浏览器,自动化测试工具,支持多种浏览器,爬虫中主要用来解决JavaScript渲染问题。

二、selenium基本使用

用python写爬虫的时候,主要用的是selenium的Webdriver,我们可以通过下面的方式先看看Selenium.Webdriver支持哪些浏览器

技术分享图片

执行结果如下,从结果中我们也可以看出基本山支持了常见的所有浏览器:

技术分享图片

这里要说一下比较重要的PhantomJS,PhantomJS是一个而基于WebKit的服务端JavaScript API,支持Web而不需要浏览器支持,其快速、原生支持各种Web标准:Dom处理,CSS选择器,JSON等等。PhantomJS可以用用于页面自动化、网络监测、网页截屏,以及无界面测试

声明浏览器对象

上面我们知道了selenium支持很多的浏览器,但是如果想要声明并调用浏览器则需要:

from selenium import webdriver

browser = webdriver.Chrome()
browser = webdriver.Firefox()

这里只写了两个例子,当然了其他的支持的浏览器都可以通过这种方式调用

访问页面

from selenium import webdriver

browser = webdriver.Chrome()

browser.get("http://www.baidu.com") # 打开链接
browser.save_screenshot(screenshot.png) #屏幕截图
print(browser.page_source) #获取JS渲染后的源代码
browser.close() #关闭

查找元素

单个元素查找

from selenium import webdriver

browser = webdriver.Chrome()

browser.get("http://www.taobao.com")
input_first = browser.find_element_by_id("q") #通过id
input_second = browser.find_element_by_css_selector("#q") #通过css选择器
input_third = browser.find_element_by_xpath(//*[@id="q"]) #通过xpath
print(input_first)
print(input_second)
print(input_third)
browser.close()

这里我们通过三种不同的方式去获取响应的元素,第一种是通过id的方式,第二个中是CSS选择器,第三种是xpath选择器,结果都是相同的。
结果如下:

技术分享图片

这里列举一下常用的查找元素方法:

find_element_by_name
find_element_by_id
find_element_by_xpath
find_element_by_link_text
find_element_by_partial_link_text
find_element_by_tag_name
find_element_by_class_name
find_element_by_css_selector

下面这种方式是比较通用的一种方式:这里需要记住By模块所以需要导入
from selenium.webdriver.common.by import By

from selenium import webdriver

from selenium.webdriver.common.by import By

browser = webdriver.Chrome()

browser.get("http://www.taobao.com")
input_first = browser.find_element(By.ID,"q")
print(input_first)
browser.close()

多个元素查找

其实多个元素和单个元素的区别,举个例子:find_elements,单个元素是find_element,其他使用上没什么区别,通过其中的一个例子演示:

from selenium import webdriver


browser = webdriver.Chrome()
browser.get("http://www.taobao.com")
lis = browser.find_elements_by_css_selector(.service-bd li)
print(lis)
browser.close()

这样获得就是一个列表

技术分享图片

 

当然上面的方式也是可以通过导入from selenium.webdriver.common.by import By 这种方式实现

lis = browser.find_elements(By.CSS_SELECTOR,‘.service-bd li‘)

同样的在单个元素中查找的方法在多个元素查找中同样存在:
find_elements_by_name
find_elements_by_id
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

元素交互操作

对于获取的元素调用交互方法

from selenium import webdriver

import time

browser = webdriver.Chrome()
browser.get("http://www.taobao.com")
input_str = browser.find_element_by_id(q)
input_str.send_keys("ipad")
time.sleep(1)
input_str.clear()
input_str.send_keys("MakBook pro")
button = browser.find_element_by_class_name(btn-search)
button.click()

运行的结果可以看出程序会自动打开Chrome浏览器并打开淘宝输入ipad,然后删除,重新输入MakBook pro,并点击搜索

Selenium所有的api文档:http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.common.action_chains

交互动作

将动作附加到动作链中串行执行

from selenium import webdriver
from selenium.webdriver import ActionChains

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() #执行动作链
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()                                            #执行链中的所有动作

执行JavaScript

这是一个非常有用的方法,这里就可以直接调用js方法来实现一些操作,
下面的例子是通过登录知乎然后通过js翻到页面底部,并弹框提示

from selenium import webdriver
browser = webdriver.Chrome()
browser.get("http://www.zhihu.com/explore")
browser.execute_script(window.scrollTo(0, document.body.scrollHeight))
browser.execute_script(alert("To Bottom"))

获取元素属性
get_attribute(‘class‘)

from selenium import webdriver

browser = webdriver.Chrome()
url = https://www.zhihu.com/explore
browser.get(url)
logo = browser.find_element_by_id(zh-top-link-logo)
print(logo)
print(logo.get_attribute(class))

获取文本值
text

from selenium import webdriver

browser = webdriver.Chrome()
url = https://www.zhihu.com/explore
browser.get(url)
input = browser.find_element_by_class_name(zu-top-add-question)
print(input.text)

获取ID,位置,标签名
id
location
tag_name
size

from selenium import webdriver

browser = webdriver.Chrome()
url = https://www.zhihu.com/explore
browser.get(url)
input = browser.find_element_by_class_name(zu-top-add-question)
print(input.id)
print(input.location)
print(input.tag_name)
print(input.size)

Frame

frame相当于独立的网页,如果在父类网frame查找子类的,则必须切换到子类的frame,子类如果查找父类也需要先切换

这里常用的是switch_to.from()和switch_to.parent_frame()

实例:登录qq邮箱并发送邮件

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

driver = webdriver.Chrome()
driver.implicitly_wait(10)
try:
    driver.get(https://mail.qq.com/)
    driver.maximize_window() #最大化
    driver.switch_to_frame(login_frame) #切换到login_frame
    locator1 = (By.ID,login_button)
    WebDriverWait(driver,20).until(EC.presence_of_element_located(locator1))
    driver.find_element_by_id(u).clear()
    driver.find_element_by_id(u).send_keys(xxxx)#输入qq账号
    time.sleep(1)
    driver.find_element_by_id(p).send_keys(xxxx)# 输入密码
    time.sleep(1)
    driver.find_element_by_id(login_button).click()#点击登录
    time.sleep(2)
    locator2 = (By.ID,btlogin)
    WebDriverWait(driver,20).until(EC.presence_of_element_located(locator2))
    driver.find_element_by_id(pp).clear()
    driver.find_element_by_id(pp).send_keys(xxxx)#输入安全密码
    driver.find_element_by_id(btlogin).click()#点击确认
    time.sleep(3)
    locator3 = (By.ID,composebtn)
    WebDriverWait(driver,20).until(EC.presence_of_element_located(locator3))
    driver.find_element_by_xpath(//*[@id="composebtn"]).click()
    time.sleep(2)
    driver.switch_to_frame(mainFrame)#切到mainFrame
    locator4 = (By.ID,toAreaCtrl)
    WebDriverWait(driver,20).until(EC.presence_of_element_located(locator4))
    driver.find_element_by_xpath(//*[@id="toAreaCtrl"]/div[2]/input).send_keys(xxxxx)
    time.sleep(1)
    driver.find_element_by_id(subject).send_keys(test)
    time.sleep(1)
    driver.switch_to_frame(driver.find_element_by_tag_name(iframe))
    driver.find_element_by_xpath(/html/body).send_keys(12345)
    driver.switch_to.parent_frame()#切回父类
    driver.find_element_by_xpath(//*[@id="AttachFrame"]/span/input).click()
    driver.find_element_by_link_text(发送).click()
    locator5 = (By.ID,sendinfomsg)
    WebDriverWait(driver, 20).until(EC.presence_of_element_located(locator5))
    print(driver.find_element_by_id(sendinfomsg).text)
except Exception as e:
    print(e)

实例二:

import time
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException

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)
print(source)
try:
    logo = browser.find_element_by_class_name(logo)
except NoSuchElementException:
    print(NO LOGO)
browser.switch_to.parent_frame()
logo = browser.find_element_by_class_name(logo)
print(logo)
print(logo.text)

等待

当使用了隐式等待执行测试的时候,如果 WebDriver没有在 DOM中找到元素,将继续等待,超出设定时间后则抛出找不到元素的异常, 换句话说,当查找元素或元素并没有立即出现的时候,隐式等待将等待一段时间再查找 DOM,默认的时间是0

隐式等待
到了一定的时间发现元素还没有加载,则继续等待我们指定的时间,如果超过了我们指定的时间还没有加载就会抛出异常,如果没有需要等待的时候就已经加载完毕就会立即执行

from selenium import webdriver

browser = webdriver.Chrome()
browser.implicitly_wait(10)
browser.get(https://www.zhihu.com/explore)
input = browser.find_element_by_class_name(zu-top-add-question)
print(input)

显示等待

指定一个等待条件,并且指定一个最长等待时间,会在这个时间内进行判断是否满足等待条件,如果成立就会立即返回,如果不成立,就会一直等待,直到等待你指定的最长等待时间,如果还是不满足,就会抛出异常,如果满足了就会正常返回

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

browser = webdriver.Chrome()
browser.get(https://www.taobao.com/)
wait = WebDriverWait(browser, 10)
input = wait.until(EC.presence_of_element_located((By.ID, q)))#等待input标签出现
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, .btn-search)))
print(input, button)

上述的例子中的条件:EC.presence_of_element_located()是确认元素是否已经出现了
EC.element_to_be_clickable()是确认元素是否是可点击的

常用的判断条件:
title_is 标题是某内容
title_contains 标题包含某内容
presence_of_element_located 元素加载出,传入定位元组,如(By.ID, ‘p‘)
visibility_of_element_located 元素可见,传入定位元组
visibility_of 可见,传入元素对象
presence_of_all_elements_located 所有元素加载出
text_to_be_present_in_element 某个元素文本包含某文字
text_to_be_present_in_element_value 某个元素值包含某文字
frame_to_be_available_and_switch_to_it frame加载并切换
invisibility_of_element_located 元素不可见
element_to_be_clickable 元素可点击
staleness_of 判断一个元素是否仍在DOM,可判断页面是否已经刷新
element_to_be_selected 元素可选择,传元素对象
element_located_to_be_selected 元素可选择,传入定位元组
element_selection_state_to_be 传入元素对象以及状态,相等返回True,否则返回False
element_located_selection_state_to_be 传入定位元组以及状态,相等返回True,否则返回False
alert_is_present 是否出现Alert

更多操作参考:http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.support.expected_conditions

浏览器的前进和后退

back()
forward()

import time
from selenium import webdriver

browser = webdriver.Chrome()
browser.get(https://www.baidu.com/)
browser.get(https://www.taobao.com/)
browser.get(https://www.python.org/)
browser.back()
time.sleep(1)
browser.forward()
browser.close()

cookie操作

get_cookies()
delete_all_cookes()
add_cookie()

from selenium import webdriver

browser = webdriver.Chrome()
browser.get(https://www.zhihu.com/explore)
print(browser.get_cookies())#获取cookies
browser.add_cookie({name: name, domain: www.zhihu.com, value: zhaofan}) #添加cookies
print(browser.get_cookies())
browser.delete_all_cookies() #移除所有cookies
print(browser.get_cookies())

小结

导入webdriver
from selenium import webdriver
import time

#要想调用键盘按键操作需要引入keys包
from selenium.webdriver.common.keys import Keys

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

# 获取css=#u1 > a:nth-child(1)文本内容
data = driver.find_element_by_css_selector(#u1 > a:nth-child(1)).text

# 打印数据内容
print(data) # 新闻

# 生成页面快照并保存
driver.save_screenshot("baidu.png")

# 搜索
# # id="kw"是百度搜索输入框,输入字符串"长城"
driver.find_element_by_id(kw).send_keys(长城)

# id="su"是百度搜索按钮,click()是模拟点击
driver.find_element_by_id(su).click()
time.sleep(1)
# 获取新的页面快照
driver.save_screenshot("长城.png")

# 打印网页渲染后的源代码
print(driver.page_source)

# 获取当前页面Cookie
print(cookies: ,driver.get_cookies())
#
#ctrl+a全选输入框内容
driver.find_element_by_id(kw).send_keys(Keys.CONTROL, a)
#ctrl+x剪切输入框内容
driver.find_element_by_id(kw).send_keys(Keys.CONTROL, x)
#
#输入框重新输入内容
driver.find_element_by_id(kw).send_keys(python)
#
# 模拟Enter回车键
driver.find_element_by_id(su).send_keys(Keys.RETURN)
time.sleep(5)
# 清空输入框内容
driver.find_element_by_id(kw).clear()
#生成新的页面快照
driver.save_screenshot(python.png)
#获取当前url
print(driver.current_url)

driver.quit()

driver.close()

 

选项卡管理

通过执行js命令实现新开选项卡window.open()
不同的选项卡是存在列表里browser.window_handles
通过browser.window_handles[0]就可以操作第一个选项卡

import time
from selenium import webdriver

browser = webdriver.Chrome()
browser.get(https://www.baidu.com)
browser.execute_script(window.open())
print(browser.window_handles)#获取所有选项卡
browser.switch_to_window(browser.window_handles[1])
browser.get(https://www.taobao.com)
time.sleep(1)
browser.switch_to_window(browser.window_handles[0])
browser.get(https://python.org)

异常处理

这里的异常比较复杂,官网的参考地址:
http://selenium-python.readthedocs.io/api.html#module-selenium.common.exceptions
这里只进行简单的演示,查找一个不存在的元素

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

browser = webdriver.Chrome()
try:
    browser.get(https://www.baidu.com)
except TimeoutException:
    print(Time Out)
try:
    browser.find_element_by_id(hello)
except NoSuchElementException:
    print(No Element)
finally:
    browser.close()

弹窗处理

当你触发了某个事件之后,页面出现了弹窗提示,处理这个提示或者获取提示信息方法如下

alert = driver.switch_to_alert()
alert.accept()
print(alert)

phantomjs介绍

PhantomJS是一个无界面的,可脚本编程的WebKit浏览器引擎。它原生支持多种web标准:DOM 操作,CSS选择器,JSON,Canvas 以及SVG。

phantomjs常用配置

# 引入配置对象DesiredCapabilities

fromselenium.webdriver.common.desired_capabilities import DesiredCapabilities

dcap =dict(DesiredCapabilities.PHANTOMJS)

#从USER_AGENTS列表中随机选一个浏览器头,伪装浏览器

dcap["phantomjs.page.settings.userAgent"]= (random.choice(USER_AGENTS))

# 不载入图片,爬页面速度会快很多

dcap["phantomjs.page.settings.loadImages"]= False

# 设置代理

service_args =[--proxy=127.0.0.1:9999,--proxy-type=socks5]

#打开带配置信息的phantomJS浏览器

driver =webdriver.PhantomJS(phantomjs_driver_path,desired_capabilities=dcap,service_args=service_args)

填充表单

我们已经知道了怎样向文本框中输入文字,但是其它的表单元素呢?例如下拉选项卡的的处理可以如下

首先获取了第一个 select 元素,也就是下拉选项卡。然后轮流设置了 select 选项卡中的每一个 option 选项。你可以看到,这并不是一个非常有效的方法。

其实 WebDriver 中提供了一个叫 Select 的方法,可以帮助我们完成这些事情。

如你所见,它可以根据索引来选择,可以根据值来选择,可以根据文字来选择。是十分方便的。

全部取消选择怎么办呢?很简单

这样便可以取消所有的选择。

另外我们还可以通过下面的方法获取所有的已选选项。

这样就相当于模拟点击了 submit 按钮,做到表单提交。

当然你也可以单独提交某个元素

方法,WebDriver 会在表单中寻找它所在的表单,如果发现这个元素并没有被表单所包围,那么程序会抛出 NoSuchElementException 的异常。




















































以上是关于selenium的主要内容,如果未能解决你的问题,请参考以下文章

Selenium JavascriptExecutor 详解

Selenium JavascriptExecutor 详解

有没有办法关闭代码片段中的命名建议?

selenium之调用Javascript

selenium+Python(处理html5的视频播放)

使用 Java 的 Selenium WebDriver (Selenium 2) 中 selenium.refresh() 的等效代码