继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

一发入魂 - Selenium使用

锐玩道
关注TA
已关注
手记 70
粉丝 154
获赞 1427

图片描述

前言

本文使用 python3.6.5.

Selenium 是一个用于 Web 应用程序测试的工具。

Selenium 测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括 IE(7, 8, 9, 10, 11),Firefox,Safari,Chrome,Opera 等。

使用 python 爬虫调用 selenium 来模拟正常用户访问浏览器.


Selenium 和 ChromeDriver 的安装与配置

安装

安装 selenium:

win: pip install selenium
liunx: pip3 install selenium

安装 ChromeDriver, 该工具供 selenium 使用 Chrome.

ChromeDriver: http://npm.taobao.org/mirrors/chromedriver/

这里只是对应版本中的一部分, 各位的 Chrome 版本可能超出了这里的版本范围.

但是通过版本对比, 可以发现每个 driver 版本对应的 chrome 版本范围为 3.

通过规律, 各位就能知道自己该下那个版本的 driver 了.

配置

  1. 将下载的 ChromeDriver 进行解压.
  2. 将解压后的文件放入合适的位置.
    1. win: 将解压后的文件放入配置了环境变量的文件夹, 如 python 的文件夹.
    2. linux: 将解压后的文件移动到/usr/loacl/bin目录中.
  3. 完成.

简单使用

如前面说的, 我们能使用 python 导入 selenium 来控制浏览器访问网站.

也就是说能使用 py 打开浏览器自动化访问.

Chrome 有界面运行

    #!/usr/bin/env python3
    from selenium import werdriver
    import time


    driver = webdriver.Chrome()     # 创建Chrome对象.
    # 操作这个对象.
    driver.get('https://www.baidu.com')     # get方式访问百度.
    time.sleep(2)
    driver.quit()   # 使用完, 记得关闭浏览器, 不然chromedriver.exe进程为一直在内存中.

Chrome 无界面运行

    #!/usr/bin/env python3
    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    import time

    chrome_opt = Options()      # 创建参数设置对象.
    chrome_opt.add_argument('--headless')   # 无界面化.
    chrome_opt.add_argument('--disable-gpu')    # 配合上面的无界面化.
    chrome_opt.add_argument('--window-size=1366,768')   # 设置窗口大小, 窗口大小会有影响.

    # 创建Chrome对象并传入设置信息.
    driver = webdriver.Chrome(chrome_options=chrome_opt)
    # 操作这个对象.
    driver.get('https://www.baidu.com')     # get方式访问百度.
    time.sleep(2)
    print(driver.page_source)       # 打印加载的page code, 证明(prove) program is right.
    driver.quit()   # 使用完, 记得关闭浏览器, 不然chromedriver.exe进程为一直在内存中.

Selenium 启动项(参数设置)与 Driver

Chrome WebDriver Options

#!/usr/bin/env python3
from selenium import webdriver
from selenium.webdriver.chrome.options import Options


chrome_opt = Options()      # 创建参数设置对象.
chrome_opt.add_argument('--windows-size=1366,768')  # 设置浏览器窗口大小.

# 创建chrome对象并传入设置信息.
driver = webdriver.Chrome(chrome_options=chrome_opt)
driver.quit()

常用的启动项

启动参数 作用
–user-agent=”“ 设置请求头的 User-Agent
–window-size=长,宽 设置浏览器分辨率
–headless 无界面运行
–start-maximized 最大化运行
–incognito 隐身模式
–disable-javascript 禁用 javascript
–disable-infobars 禁用浏览器正在被自动化程序控制的提示

禁用图片加载

Chrome 的禁用图片加载参数设置比较复杂,如下所示:

prefs = {
    'profile.default_content_setting_values' : {
        'images' : 2
    }
}
options.add_experimental_option('prefs',prefs)

禁用浏览器弹窗

使用浏览器时常常会有弹窗弹出,以下选项可以禁止弹窗:

prefs = {
    'profile.default_content_setting_values' :  {
        'notifications' : 2
     }
}
options.add_experimental_option('prefs',prefs)

Chrome WebDriver

chromedriver.exe 一般可以放在环境文件中,但是有时候为了方便部署项目,或者为了容易打包,我们可以将 chromedriver.exe 放到我们的项目目录中,然后在初始化 Chrome Webdriver 对象时,传入 chromedriver.exe 的路径。

from selenium import webdriver

driver = webdriver.Chrome(executable_path='chromedriver.exe')
driver.quit()

Selenium Driver 操作

Driver 对象常见操作

  • get(url): 在当前浏览器会话中访问传入的 url 地址, driver.get('https://www.baidu.com').
  • close(): 关闭浏览器当前窗口。
  • quit(): 退出 webdriver 并关闭所有窗口。
  • refresh(): 刷新当前页面。
  • title: 获取当前页的标题。
  • page_source: 获取当前页渲染后的源代码。
  • current_url: 获取当前页面的 url。
  • window_handles: 获取当前会话中所有窗口的句柄。

Driver 查找单个元素

方法 作用
find_element_by_xpath() 通过Xpath查找
find_element_by_class_name() 通过class属性查找
find_element_by_css_selector() 通过css选择器查找
find_element_by_id() 通过id查找
find_element_by_link_text() 通过链接文本查找
find_element_by_name() 通过name属性进行查找
find_element_by_partial_link_text() 通过链接文本的部分匹配查找
find_element_by_tag_name() 通过标签名查找

查找后返回的是一个Webelement对象。
查找多个元素: 将其中的 element 加上一个 s,则是对应的多个查找方法

上面的方法都是将第一个找到的元素进行返回,而将所有匹配的元素进行返回使用的是find_elements_by_*方法。

Driver 操作 Cookie

  • add_cookie(cookie_dict) : 给当前会话添加一个 cookie。
  • cookie_dict: 一个字典对象,必须要有”name”和”value”两个键,可选的键有:“path”, “domain”, “secure”, “expiry” 。
  • 用法:
  driver.add_cookie({‘name’ : ‘foo’, ‘value’ : ‘bar’})
  driver.add_cookie({‘name’ : ‘foo’, ‘value’ : ‘bar’, ‘path’ : ‘/’})
  driver.add_cookie({‘name’ : ‘foo’, ‘value’ : ‘bar’, ‘path’ : ‘/’, ‘secure’:True})
  • get_cookie(name): 按 name 获取单个 Cookie,没有则返回 None。
  • get_cookies(): 获取所有 Cookie,返回的是一组字典。
  • delete_all_cookies(): 删除所有 Cookies。
  • delete_cookie(name): 按 name 删除指定 cookie。

Driver 获取截屏

  • get_screenshot_as_base64(): 获取当前窗口的截图保存为一个 base64 编码的字符串。
  • get_screenshot_as_file(filename): 获取当前窗口的截图保存为一个 png 格式的图片,filename 参数为图片的保存地址,最后应该以.png 结尾。如果出现 IO 错误,则返回 False。
    • 用法: driver.get_screenshot_as_file(‘/Screenshots/foo.png’)
  • get_screenshot_as_png(): 获取当前窗口的截图保存为一个 png 格式的二进制字符串。

Driver 获取窗口信息

  • get_window_position(windowHandle=’current’): 获取当前窗口的 x,y 坐标。
  • get_window_rect(): 获取当前窗口的 x,y 坐标和当前窗口的高度和宽度。
  • get_window_size(windowHandle=’current’): 获取当前窗口的高度和宽度。

Driver 切换操作

  • switch_to_frame(frame_reference): 将焦点切换到指定的子框架中
  • switch_to_window(window_name): 切换窗口

Driver 执行 JS 代码

  • execute_async_script(script, *args) : 在当前的 window/frame 中异步执行 JS 代码。
    • script:是你要执行的 JS 代码。
    • *args:是你的 JS 代码执行要传入的参数。
    • 用法:
      script = “var callback = arguments[arguments.length - 1]; ”
          script2 = “window.setTimeout(function(){ callback(‘timeout’) }, 3000);”
          driver.execute_async_script(script + script2)
      
  • execute_script(script, *args): 在当前的 window/frame 中同步执行 JS 代码。
    • script:是你要执行的 JS 代码。
    • *args:是你的 JS 代码执行要传入的参数。

Selenium Webelement 操作

Webelement 操作

前面有讲到使用find等方法来查找单个或多个元素对象, 其结果返回一个Webelement对象.

现在我们操作这个对象.

Webelement 常用方法

  • clear(): 清空对象中的内容.
  • click(): 单击对象.
  • get_attribute(name): 优先返回完全匹配属性名的值,如果不存在,则返回属性名中包含 name 的值。
  • screenshot(filename): 获取当前元素的截图,保存为 png,最好用绝对路径.
  • send_keys(value): 给对象元素输入数据, 如在百度中搜索’哔哩哔哩’.
  • submit(): 提交表单.

Webelement 常用属性

  • text: 获取当前元素的文本内容.
  • tag_name: 获取当前元素的标签名.
  • size: 获取当前元素的大小.
  • screenshot_as_png: 将当前元素截屏并保存为 png 格式的二进制数据.
  • screenshot_as_base64: 将当前元素截屏并保存为 base64 编码的字符串.
  • rect: 获取一个包含当前元素大小和位置的字典.
  • parent: 获取当前元素的父节点.
  • location: 当前元素的位置.
  • id: 当前元素的 id 值,主要用来 selenium 内部使用,可以用来判断两个元素是否是同一个元素.

Webelement 中的 keys

们经常需要模拟键盘的输入,当输入普通的值时,在send_keys()方法中传入要输入的字符串就好了。

但是我们有时候会用到一些特殊的按键,这时候就需要用到我们的 Keys 类。

    # 要使用按键值, 需要导入下面keys.
    from selenium.webdriver.common.keys import Keys


    elem.send_keys(Keys.CONTROL, 'c')
更多的模拟键

对应的属性

ADD = u’\\ue025’

ALT = u’\\ue00a’

ARROW_DOWN = u’\\ue015’

ARROW_LEFT = u’\\ue012’

ARROW_RIGHT = u’\\ue014’

ARROW_UP = u’\\ue013’

BACKSPACE = u’\\ue003’

BACK_SPACE = u’\\ue003’

CANCEL = u’\\ue001’

CLEAR = u’\\ue005’

COMMAND = u’\\ue03d’

CONTROL = u’\\ue009’

DECIMAL = u’\\ue028’

DELETE = u’\\ue017’

DIVIDE = u’\\ue029’

DOWN = u’\\ue015’

END = u’\\ue010’

ENTER = u’\\ue007’

EQUALS = u’\\ue019’

ESCAPE = u’\\ue00c’

F1 = u’\\ue031’

F2 = u’\\ue032’

F3 = u’\\ue033’

F4 = u’\\ue034’

F5 = u’\\ue035’

F6 = u’\\ue036’

F7 = u’\\ue037’

F8 = u’\\ue038’

F9 = u’\\ue039’

F10 = u’\\ue03a’

F11 = u’\\ue03b’

F12 = u’\\ue03c’

HELP = u’\\ue002’

HOME = u’\\ue011’

INSERT = u’\\ue016’

LEFT = u’\\ue012’

LEFT_ALT = u’\\ue00a’

LEFT_CONTROL = u’\\ue009’

LEFT_SHIFT = u’\\ue008’

META = u’\\ue03d’

MULTIPLY = u’\\ue024’

NULL = u’\\ue000’

NUMPAD0 = u’\\ue01a’

NUMPAD1 = u’\\ue01b’

NUMPAD2 = u’\\ue01c’

NUMPAD3 = u’\\ue01d’

NUMPAD4 = u’\\ue01e’

NUMPAD5 = u’\\ue01f’

NUMPAD6 = u’\\ue020’

NUMPAD7 = u’\\ue021’

NUMPAD8 = u’\\ue022’

NUMPAD9 = u’\\ue023’

PAGE_DOWN = u’\\ue00f’

PAGE_UP = u’\\ue00e’

PAUSE = u’\\ue00b’

RETURN = u’\\ue006’

RIGHT = u’\\ue014’

SEMICOLON = u’\\ue018’

SEPARATOR = u’\\ue026’

SHIFT = u’\\ue008’

SPACE = u’\\ue00d’

SUBTRACT = u’\\ue027’

TAB = u’\\ue004’

UP = u’\\ue013’

Selenium Action-Chains

What is the Action-Chains?

一般来说我们与页面的交互可以使用Webelement的方法来进行点击等操作。但是,有时候我们需要一些更复杂的动作,类似于拖动,双击,长按等等。

这时候就需要用到我们的Action Chains(动作链)了。

from selenium.webdriver import ActionChains
    from selenium import webdriver

    driver = webdriver.Chrome()     # 创建webdriver对象.

    element = driver.find_element_by_name("source")     # 查找单一元素对象.
    target = driver.find_element_by_name("target")      # 同上.

    actions = ActionChains(driver)      # 创建动作链对象.

    # 在element元素上点击抓起,移动到target元素上松开放下。 类似鼠标.
    actions.drag_and_drop(element, target)
    actions.perform()   # 执行动作.

在导入动作链模块以后,需要声明一个动作链对象,在声明时将 webdriver 对象当作参数传入,并将对象赋值给一个 actions 变量。

然后我们通过这个 actions 变量,调用其内部附带的各种动作方法进行操作。

注:在调用各种动作方法后,这些方法并不会马上执行,而是会按你代码的顺序存储在 ActionChains 对象的队列中。当你调用 perform()时,这些动作才会依次开始执行。

常用的 Action-Chains 方法

  • click(on_element=None) : 左键单击传入的元素,如果不传入的话,点击鼠标当前位置。
  • contextclick(_on_element=None): 右键单击。
  • doubleclick(_on_element=None) : 双击。
  • click_and_hold(on_element=None): 点击并抓起
  • drag_and_drop(source, target) : 在 source 元素上点击抓起,移动到 target 元素上松开放下。
  • drag_and_drop_by_offset(source, xoffset, yoffset):在 source 元素上点击抓起,移动到相对于 source 元素偏移 xoffset 和 yoffset 的坐标位置放下。
  • sendkeys(*keys_to_send_): 将键发送到当前聚焦的元素。
  • send_keys_toelement(_element, *keys_to_send): 将键发送到指定的元素。
  • reset_actions(): 清除已经存储的动作。

Selenium Wait

为什么需要等待?

在 selenium 操作浏览器的过程中,每一次请求urlselenium都会等待页面加载完毕以后,才会将操作权限再次交给我们的程序。

但是,由于ajax和各种JS代码异步加载问题,所以我们在使用selenium的时候常常会遇到操作的元素还没有加载出来,就会引发报错。为了解决这个问题,Selenium提供了几种等待的方法,让我们可以等待元素加载完毕后,再进行操作。

显式等待.

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


    driver = webdriver.Chrome()
    driver.get("http://somedomain/url_that_delays_loading")

    try:
        # 创建wait对象.
        element = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.ID, "myDynamicElement"))
        )

    finally:
        driver.quit()

在这个例子中,我们在查找一个元素的时候,不再使用find_element_by_*这样的方式来查找元素,而是使用了WebDriverWait

try 代码块中的代码的意思是:在抛出元素不存在异常之前,最多等待 10 秒。在这 10 秒中,WebDriverWait会默认每 500ms 运行一次 until 之中的内容,而 until 中的EC.presence_of_element_located则是检查元素是否已经被加载,检查的元素则通过By.ID这样的方式来进行查找。

就是说,在 10 秒内,默认每 0.5 秒检查一次元素是否存在,存在则将元素赋值给 element 这个变量。如果超过 10 秒这个元素仍不存在,则抛出超时异常。

隐式等待.

隐式等待指的是,在webdriver中进行find_element这一类查找操作时,如果找不到元素,则会默认的轮询等待一段时间。

这个值默认是 0,可以通过以下方式进行设置:

from selenium import webdriver

driver = webdriver.Chrome()
driver.implicitly_wait(10) # 单位是秒
driver.get("http://somedomain/url_that_delays_loading")
myDynamicElement = driver.find_element_by_id("myDynamicElement")

Expected Conditions 方法

Expected Conditions这个类提供了很多种常见的检查条件可以供我们使用。

  • title_is: 判断 title,返回布尔值.
    • WebDriverWait(driver,10).until(EC.title_is(u"百度一下,你就知道"))
  • title_contains: 判断 title,返回布尔值.
    • WebDriverWait(driver,10).until(EC.title_contains(u"百度一下"))
  • presence_of_element_located: 判断元素对象是否被加载到 dom 树里; 并不代表该元素一定可见, 如果定位到就返回 Webelement.
    • WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,'some')))
  • visibility_of_element_located: 判断元素对象是否被加载到 dom 里并且可见, 一般在对象可能会被其他元素对象遮挡的情况下使用.
    • WebDriverWait(driver,10).until(EC.visibility_of_element_located((By.ID,'some')))
  • visibility_of: 判断元素是否可见,如果可见就返回这个元素.
    • WebDriverWait(driver,10).until(EC.visibility_of(driver.find_element(by=By.ID,value='some')))
  • presence_of_all_elements_located: 判断是否至少有 1 个元素存在 dom 树中,如果定位(找)到就返回列表.
    • WebDriverWait(driver,10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR,'some')))
  • visibility_of_any_elements_located: 判断是否至少有一个元素在页面中可见,如果定位到就返回列表.
    • WebDriverWait(driver,10).until(EC.visibility_of_any_elements_located((By.CSS_SELECTOR,'some')))
  • text_to_be_present_in_element: 判断指定的元素中是否包含了预期的字符串,返回布尔值.
    • WebDriverWait(driver,10).until(EC.text_to_be_present_in_element((By.XPATH,"some"),u'设置'))
  • text_to_be_present_in_element_value: 判断指定元素的属性值中是否包含了预期的字符串,返回布尔值.
    • WebDriverWait(driver,10).until(EC.text_to_be_present_in_element_value((By.CSS_SELECTOR,'some'),u'百度一下'))
  • frame_to_be_available_and_switch_to_it: 判断该 frame 是否可以 switch 进去,如果可以的话,返回 True 并且 switch 进去,否则返回 False.
    • WebDriverWait(driver,10).until(EC.frame_to_be_available_and_switch_to_it(some))
  • invisibility_of_element_located: 判断某个元素在是否存在于 dom 或不可见,如果可见返回 False,不可见返回这个元素.
    • WebDriverWait(driver,10).until(EC.invisibility_of_element_located((By.CSS_SELECTOR,'some')))
  • element_to_be_clickable: 判断某个元素中是否有可见并且是 enable(可点击)的.
    • WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,"some"))).click()
  • staleness_of: 等待某个元素从 dom 树中移除.
    • WebDriverWait(driver,10).until(EC.staleness_of(driver.find_element(By.ID,'some')))
  • element_to_be_selected: 判断某个元素是否被选中了,一般用在下拉列表.
    • WebDriverWait(driver,10).until(EC.element_to_be_selected(driver.find_element(By.XPATH,"some")))
  • element_located_to_be_selected: 判断元素是否被选中, 传入一个元组对象.
    • 暂没找到例子.
  • element_selection_state_to_be: 判断某个元素的选中状态是否符合预期.
    • WebDriverWait(driver,10).until(EC.element_selection_state_to_be(driver.find_element(By.XPATH,"some"),True))
  • element_located_selection_state_to_be: 判断某个元素的选中状态是否符合预期.
    • WebDriverWait(driver,10).until(EC.element_located_selection_state_to_be((By.XPATH,"some"),True))
  • alert_is_present: 判断页面上是否存在 alert(Js 弹窗),如果有就切换到 alert 并返回 alert 的内容.
    • WebDriverWait(driver,10).until(EC.alert_is_present())
    '''
        示意代码, 不完整.
    '''
    from selenium import webdriver
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.by import By


    driver = webdriver.Chrome()

    wait = WebDriverWait(driver, 10)
    # 等待直到元素可以被点击
    element = wait.until(EC.element_to_be_clickable((By.ID, 'someid')))

打开App,阅读手记
3人推荐
发表评论
随时随地看视频慕课网APP

热门评论

感谢大佬,学习了

查看全部评论