美文网首页
10 selenium的基本使用

10 selenium的基本使用

作者: yungege | 来源:发表于2019-08-06 22:28 被阅读0次

    10 selenium的基本使用

    一、selenium简介

    Selenium是一个用于web自动化测试的工具,Selenium测试直接运行在浏览器中,就好像一个真正的用户在操作一样, 支持大部分主流的浏览器,包括IE(7,8,9,10,11),Firefox,Safari,Chrome,Opera等。

    ​我们可以利用它来模拟用户点击访问网站,绕过一些复杂的认证场景

    通过selnium+驱动浏览器这种组合可以直接渲染解析js,绕过大部分的参数构造和反爬。

    注意事项:

    新版本的Selenium已经不在支持phantomjs,原作者也已经放弃维护该项目了。

    还有在做爬虫的时候尽量不要用这种方法,Selenium+浏览器的组合速度慢,应付不了数据量比较大的爬取以及并发爬取。并且很吃电脑资源。

    二、selenium配置

    Selenium安装非常简单,直接pip就可以搞定: pip install selenium

    使用selenium驱动chrome浏览器需要下载chromedriver,而且chromedriver版本需要与chrome的版本对应,版本错误的话则会运行报错。

    Chromedriver下载地址:https://chromedriver.storage.googleapis.com/index.html

    Windows: 下载对应版本的chromedriver解压后,将文件移动到一个配置了环境变量的文件夹中,例如Python安装文件夹

    Linux/Mac: 解压后,将文件移动至/usr/local/bin目录中

    Selenium驱动其他浏览器的也是需要下载对应的驱动

    三、基本使用

    1、启动/关闭

    获取页面内容:page_source

    from selenium import webdriver
    import time
    
    driver = webdriver.Chrome()
    
    driver.get('https://www.baidu.com')
    
    # 获取页面内容
    resp = driver.page_source
    print(resp)
    
    time.sleep(5)
    
    driver.close()
    

    2、元素选取

    在一个页面中有很多不同的策略可以定位一个元素。我们可以选择最合适的方法去查找元素。Selenium提供了下列的方法:

    注: 其中的element加上一个s,则是对应的多个元素的查找方法

    单个元素查找方法 作用
    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() 通过标签名查找
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    
    driver = webdriver.Chrome()
    
    driver.get('https://www.baidu.com')
    
    # 通过Xpath查找
    a1 = driver.find_element_by_xpath('//input[@value="百度一下"]')
    print('find_element_by_xpath',a1)
    # 通过id查找
    a2 = driver.find_element_by_id('su')
    print('find_element_by_id',a2)
    # 通过class属性查找
    a3 = driver.find_element_by_class_name('fm')
    print('find_element_by_class_name',a3)
    # 通过css选择器查找
    a4 = driver.find_element_by_css_selector('#su')
    print('find_element_by_class_name',a4)
    # 通过链接文本查找
    a5 = driver.find_element_by_link_text('新闻')
    print('find_element_by_link_text',a5)
    # 通过name属性查找
    a6 = driver.find_element_by_name('rn')
    print('find_element_by_name',a6)
    # 通过链接文本的部分匹配查找
    a7 = driver.find_element_by_partial_link_text('新')
    print('find_element_by_partial_link_text',a7)
    # 通过标签名查找
    a8 = driver.find_element_by_tag_name('input')
    print('find_element_by_tag_name',a8)
    # 查找多个
    a9 = driver.find_elements_by_tag_name('div')
    print('find_elements_by_tag_name',a9)
    

    除了以上的多种查找方式,还有两种私有方法集成了上面的所有的查找方法,让我们更方便的使用

    方法 作用
    find_element(By.XPATH, ‘//button/span’) 通过Xpath查找一个
    find_elements(By.XPATH, ‘//button/span’) 通过Xpath查找多个

    其中的第一个参数可以选择使用查找的方法,By.xxx 使用xxx方式解析,解析方法如下:

    注:By对象导入: from selenium.webdriver.common.by import By

    ID = "id" 
    XPATH = "xpath" 
    LINK_TEXT = "link text" 
    PARTIAL_LINK_TEXT = "partial link text" 
    NAME = "name" 
    TAG_NAME = "tag name" 
    CLASS_NAME = "class name" 
    CSS_SELECTOR = "css selector" 
    
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    
    driver = webdriver.Chrome()
    
    driver.get('https://www.baidu.com')
    # by_id
    a1 = driver.find_element(by=By.ID, value='su')
    print('By.ID',a1)
    # by_xpath
    a2 = driver.find_element(by=By.XPATH, value='//input[@value="百度一下"]')
    print('By.XPATH',a2)
    # by_link_text
    a3 = driver.find_element(by=By.LINK_TEXT, value='新闻')
    print('By.LINK_TEXT',a3)
    # by_partial_link_text
    a4 = driver.find_element(by=By.PARTIAL_LINK_TEXT, value='新')
    print('By.PARTIAL_LINK_TEXT',a4)
    # by_name
    a5 = driver.find_element(by=By.NAME, value='rn')
    print('By.NAME',a5)
    # by_tag_name
    a6 = driver.find_element(by=By.TAG_NAME, value='input')
    print('By.NAME',a6)
    # by_class_name
    a7 = driver.find_element(by=By.CLASS_NAME, value='fm')
    print('By.CLASS_NAME',a7)
    # by_css_selector
    a8 = driver.find_element(by=By.CSS_SELECTOR, value='#su')
    print('By.CSS_SELECTOR',a8)
    # 查找多个
    a9 = driver.find_elements(by=By.TAG_NAME, value='div')
    print('find_elements', a9)
    

    三、窗口/页面/弹窗切换

    1、窗口切换

    用selenium操作浏览器如果需要在打开新的页面,这个时候会有问题,因为我们用selenium操作的是第一个打开的窗口,所以新打开的页面我们是无法去操作的,所以我们要用到切换窗口:既handle切换的方法

    方法 作用
    window_handles 获取所有页面窗口的句柄
    current_window_handle 获取当前页面窗口的句柄
    switch_to.window(window_name) 定位页面转到指定的window_name页面
    from selenium import webdriver
    import time
    driver = webdriver.Chrome()
    
    driver.get('https://www.baidu.com')
    
    time.sleep(10)
    
    # 获取所有窗口的句柄
    handles = driver.window_handles
    # 获取当前窗口的句柄
    current = driver.current_window_handle
    # 定位页面转到指定的window_name页面
    driver.switch_to.window(handles[1])
    print(handles)
    print(current)
    time.sleep(2)
    # 获取当前窗口的句柄
    current = driver.current_window_handle
    print(current)
    

    2、页面(frame)切换

    在实际的爬虫中,有时候我们会遇到找不到元素的问题,明明定位的路径没问题,这个时候我们可以考虑一下是否是该页面存在frame的问题导致的定位不到元素。

    方法 作用
    switch_to.frame(frame_reference) 切到指定frame,可用id或name(str)、index(int)、元素(WebElement)定位
    switch_to.parent_frame() 切到父级frame,如果已是主文档,则无效果, 相当于后退回去
    switch_to_default_content() 切换到主页面,DOM树最开始的frame

    3、页面弹窗

    有的时候还会遇到弹窗的问题, 主要有两种一种是浏览器弹窗(alert/prompt),一种是自定义弹窗

    自定义弹窗,就是一个自定义的div层,是隐藏页面中的,当触发了这个弹窗后,他就显示出来,这种方式我们通过正常的定位方式是可以定位到的。

    alert弹窗,就要用下面的方法处理:

    方法 作用
    switch_to_alert 定位到alert弹窗,返回一个弹窗的对象
    dismiss() 对弹窗对象的取消操作(相当于点击弹窗上的取消按钮)
    accept() 对弹窗对象的确定操作(相当于点击弹窗上的确定按钮)
    send_keys(key) 对弹窗对象内的输入框输入数据(针对于prompt弹窗)
    text 获取弹窗内的文本

    四、等待/动作链

    1、等待

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

    但是,由于ajax和各种JS代码的异步加载问题,当一个页面被加载到浏览器时,该页面内的元素可以在不同的时间点被加载,这就使得元素的定位变得十分困难,当元素不再页面中时,使用selenium去查找的时候会抛出ElementNotVisibleException异常。

    为了解决这个问题,selenium提供了两种等待页面加载的方式,显示等待和隐式等待,让我们可以等待元素加载完成后在进行操作。

    1)显示等待

    显示等待: 显式等待指定某个条件,然后设置最长等待时间,程序每隔XX时间看一眼,如果条件成立,则执行下一步,否则继续等待,直到超过设置的最长时间,然后抛出超时异常(TimeoutException)。

    显示等待主要使用了WebDriverWait类与expected_conditions模块。

    一般写法:

    WebDriverWait(driver, timeout, poll_frequency, igonred_exceptions).until(method, message)
    

    Driver:传入WebDriver实例。
    timeout: 超时时间,等待的最长时间(同时要考虑隐性等待时间)
    poll_frequency: 调用until中的方法的间隔时间,默认是0.5秒
    ignored_exceptions: 忽略的异常,如果在调用until的过程中抛出这个元组中的异常,则不中断代码,继续等待.
    Method:可执行方法
    Message: 超时时返回的信息
    WebDriverWait包:from selenium.webdriver.support.wait import WebDriverWait
    expected_conditions包:from selenium.webdriver.support import expected_conditions as EC

    expected_conditions条件

    expected_conditions是selenium的一个子模块,其中包含一系列可用于判断的条件,配合该类的方法,就能够根据条件而进行灵活地等待了

    ActionChains提供的方法 作用
    title_is title_contains 这两个条件类验证title,验证传入的参数title是否等于或包含于driver
    presence_of_element_located presence_of_all_elements_located 这两个条件验证元素是否出现,传入的参数都是元组类型的locator,如(By.ID, 'kw') 顾名思义,一个只要一个符合条件的元素加载出来就通过;另一个必须所有符合条件的元素都加载出来才行
    visibility_of_element_located invisibility_of_element_located visibility_of 这三个条件验证元素是否可见,前两个传入参数是元组类型的locator,第三个传入WebElement
    text_to_be_present_in_element text_to_be_present_in_element_value 判断某段文本是否出现在某元素中,一个判断元素的text,一个判断元素的value
    frame_to_be_available_and_switch_to_it 判断frame是否可切入,可传入locator元组或者直接传入定位方式:id、name、index或WebElement
    alert_is_present 判断是否有alert出现
    element_to_be_clickable 判断元素是否可点击,传入locator
    # 显示等待
    from selenium import webdriver
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.common.by import By
    
    driver = webdriver.Chrome()
    
    driver.get('https://www.baidu.com')
    
    locator = (By.LINK_TEXT, '贴吧')
    
    try:
        # 等待链接text'贴吧'出现,然后点击、打印其href属性
        WebDriverWait(driver,20,0.5).until(EC.presence_of_element_located(locator))
        element = driver.find_element(*locator)
        print(element.get_attribute('href'))
        element.click()
    except:
        print('发生错误')
    finally:
        driver.close()
    

    2)隐式等待

    隐性等待implicitly_wait(xx) :设置了一个最长等待时间,如果在规定时间内网页加载完成,则执行下一步,否则一直等到时间截止,然后执行下一步。

    弊端就是程序会一直等待整个页面加载完成,就算你需要的元素加载出来了还是需要等待。,也就是一般情况下你看到浏览器标签栏那个小圈不再转,才会执行下一步,

    隐性等待对整个driver的周期都起作用,所以只要设置一次即可

    隐性等待和显性等待可以同时用,但要注意:等待的最长时间取两者之中的大者

    默认等待时间为0,可以通过下面的方式设置:

    # 隐式等待
    from selenium import webdriver
    
    driver = webdriver.Chrome()
    
    driver.implicitly_wait(10)        #隐式等待,最长10s
    
    driver.get('https://www.baidu.com')
    

    2、动作链(ActionChains)

    在selenium当中除了简单的点击动作外,还有一些稍微复杂的动作,就需要用到ActionChains(动作链)这个子模块来满足我们的需求。

    ActionChains可以完成复杂一点的页面交互行为,例如元素的拖拽,鼠标移动,悬停行为,内容菜单交互。

    它的执行原理就是当调用ActionChains方法的时候不会立即执行,而是将所有的操作暂时储存在一个队列中,当调用perform()方法的时候,会按照队列中放入的先后顺序执行前面的操作。

    ActionChains包:from selenium.webdriver.common.action_chains import ActionChains

    ActionChains提供的方法 作用
    click(on_element=None) 鼠标左键单击传入的元素
    double_click(on_element=None) 双击鼠标左键
    context_click(on_element=None) 点击鼠标右键
    click_and_hold(on_element=None) 点击鼠标左键,按住不放
    release(on_element=None) 在某个元素位置松开鼠标左键
    drag_and_drop(source, target) 拖拽到某个元素然后松开
    drag_and_drop_by_offset(source, xoffset, yoffset) 拖拽到某个坐标然后松开
    move_to_element(to_element) 鼠标移动到某个元素
    move_by_offset(xoffset, yoffset) 移动鼠标到指定的x,y位置
    move_to_element_with_offset(to_element, xoffset, yoffset) 将鼠标移动到距某个元素多少距离的位置
    perform() 执行链中的所有动作
    from selenium import webdriver
    from selenium.webdriver.common.action_chains import ActionChains
    import time
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.common.by import By
    
    driver = webdriver.Chrome()
    try:
        driver.get('http://www.treejs.cn/v3/demo/cn/exedit/drag.html')
        locator1 = (By.ID,'treeDemo_2_span')
        locator2 = (By.ID,'treeDemo_3_span')
        locator3 = (By.ID,'treeDemo_11_span')
        element = WebDriverWait(driver, 20, 0.5).until(EC.presence_of_element_located(locator1))
        target1 = WebDriverWait(driver, 20, 0.5).until(EC.presence_of_element_located(locator2))
        target2 = WebDriverWait(driver, 20, 0.5).until(EC.presence_of_element_located(locator3))
    
        ActionChains(driver).drag_and_drop(element,target1).perform()
        time.sleep(5)
        ActionChains(driver).drag_and_drop(element,target2).perform()
        time.sleep(5)
        ActionChains(driver).move_to_element(target2)
        time.sleep(5)
    finally:
        driver.quit()
    

    3、微博登录

    from selenium import webdriver
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.common.by import By
    
    driver = webdriver.Chrome()
    
    url = 'https://weibo.com/'
    driver.get(url)
    
    locator1 = (By.ID, 'loginname')
    locator2 = (By.XPATH, '//div[@class="input_wrap"]/input[@name="password"]')
    locator3 = (By.XPATH,'//a[@class="W_btn_a btn_32px"]')
    
    username = WebDriverWait(driver,20,0.5).until(EC.presence_of_element_located(locator1))
    password = WebDriverWait(driver,20,0.5).until(EC.presence_of_element_located(locator2))
    login = WebDriverWait(driver,20,0.5).until(EC.presence_of_element_located(locator3))
    username.send_keys('username')
    password.send_keys('password')
    login.click()
    

    相关文章

      网友评论

          本文标题:10 selenium的基本使用

          本文链接:https://www.haomeiwen.com/subject/iqxbdctx.html