zoukankan      html  css  js  c++  java
  • 十四、Selenium入门

    1、Selenium

      Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的,可以按指定的命令自动操作,不同是Selenium 可以直接运行在浏览器上,它支持所有主流的浏览器(包括PhantomJS这些无界面的浏览器)。

      Selenium 可以根据我们的指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏,或者判断网站上某些动作是否发生。

      Selenium 自己不带浏览器,不支持浏览器的功能,它需要与第三方浏览器结合在一起才能使用。但是有时候需要让它内嵌在代码中运行,可以用一个叫 PhantomJS 的工具代替真实的浏览器。

      安装:`pip install selenium`

      selenium官方文档:https://selenium-python.readthedocs.io/index.html

    2、PhantomJS

      PhantomJs是一个基于webkit的"无界面"(headless)浏览器,它会把网站加载到内存并执行页面上的javascript,因为不会展示图形界面,所以运行起来比完整的浏览器要高效。

      把Selenium和PhantomJS结合在一起,就可以运行一个非常强大的网络爬虫了,这个爬虫可以处理JavaScrip、Cookie、headers,以及任何我们真实用户需要做的事情。

      安装:`sudo apt-get install phantomjs`

      PhantomJS官方文档:https://phantomjs.org/documentation/

      不过现在最新版的selenium不再支持了,可以选择Chrome。

    3、快速入门

      selenium库里有个叫webdriver的API,webdriver类似于可以加载网站的浏览器,它类似BeautifulSoup或其他Selector对象,用来查找页面元素,与页面上的元素进行交互(发送文本,点击等),以及执行其他动作来运运行网络爬虫。

      (1)获取id标签的文本内容:driver.find_element_by_id("id_name").text

      (2)获取标题:driver.title

      (3)生成当前页面快照并保存:driver.save_screenshot("filename.png")

      (4)id="kw"用来定位输入框,输入字符串:driver.find_element_by_id("kw").send_keys("爬虫")

      (5)id="su"用来定位搜索按钮,click()是模拟点击:driver.find_element_by_id("su").click()

      (6)获取网页渲染后的源代码:driver.page_source

      (7)获取当前页面Cookie:driver.get_cookies()

      (8)ctrl+a全选定位部分内容:driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'a')

      (9)ctrl+x剪切定位部分内容:driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'x')

      (10)模拟enter回车键:driver.find_element_by_id("su").send_keys(Keys.RETURN)

      (11)清楚选定部分的内容:driver.find_element_by_id("kw").clear()

      (12)获取当前url:driver.current_url

      (13)关闭当前页面,如果只有一个页面,会关闭浏览器:driver.close()

      (14)关闭浏览器:driver.quit()

    # 导入webdriver
    from selenium import webdriver
    # 调用键盘按钮操作时需要引入的keys包
    from selenium.webdriver.common.keys import Keys
    
    import time
    
    # 调用环境变量指定的PhantomJS浏览器创建浏览器对象
    driver = webdriver.Chrome()
    
    # 如果没有在环境变量指定chromedriver位置,则需要引用可执行文件
    #driver = webdriver.Chrome(executable_path="/usr/bin/chromedriver")
    
    # get方法会一直等到页面被完全加载,然后才会继续程序,通常测试会选择time.sleep(2)
    driver.get("https://www.baidu.com")
    
    # 获取页面中 为head_wrapper的id标签的文本内容
    # data = driver.find_element_by_id("head_wrapper").text
    # 打印获取到的数据
    # print(data)
    """
    百度热榜
    �换一换
    1同一个世界同一个妈
    4直播:相信未来义演再开唱
    2奥巴马批评特朗普疫情应对
    5强基计划直播
    3吉林一女洗衣工确诊后再传11人
    6今天,最想对妈妈说的话
    """
    
    # 打印页面标题
    # print(driver.title)
    # 百度一下,你就知道
    
    # 生成当前页面快照并保存
    #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()
    
    # # 延时2s,保证获取到实际的内容
    # time.sleep(2)
    # # 获取新页面的快照
    # driver.save_screenshot("爬虫.png")
    
    
    # 打印网页渲染后的源代码
    # print(driver.page_source)
    
    
    # 获取当前页面cookie
    # print(driver.get_cookies())
    
    
    # # 输入框重新输入内容
    driver.find_element_by_id("kw").send_keys("python")
    # driver.find_element_by_id("su").click()
    
    # 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")
    
    # 模拟enter回车键
    driver.find_element_by_id("su").send_keys(Keys.RETURN)
    
    # 清空输入款内容
    # driver.find_element_by_id('kw').clear()
    
    # 获取当前url
    print(driver.current_url)
    """
    https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=python&fenlei=256&rsv_pq=f56af1be000010cf&rsv_t=682eH4uSAFnDdURF0mggnYJfY6t28dxq2Irnjwx%2F4vQhRZrNLQQ1UnwAVVo&rqlang=cn&rsv_enter=1&rsv_dl=tb&rsv_sug3=6&rsv_btype=i&inputT=132&rsv_sug4=132
    """
    
    # 关闭当前页面,如果只有一个页面,会关闭浏览器
    time.sleep(3)
    driver.close()
    
    # 关闭浏览器
    # driver.quit()

    4、页面操作

      selenium的webdriver提供了各种方法来寻找元素

      假设有一个表单输入框:

    <input type="text" name="user-name" id="passwd-id" />

      那么通过find_element_by_*等方法可以找到元素:

    # 获取id标签值
    element = driver.find_element_by_id("passwd-id")
    
    # 获取name标签值
    element = driver.find_element_by_name("user-name")
    
    # 获取标签名值
    element = driver.find_element_by_tag_name("input")
    
    # 通过XPath来匹配
    element = driver.find_element_by_xpath("//input[@id='passwd-id']")

    5、定位UI元素(WebElements)

      5.1 关于元素的选取,有如下的API单个元素选取:

        `find_elements_by_id`

        `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`

      5.2 selenium.webdriver.common.by下有一个By,可以结合find_element()一起使用

        导入By`from selenium.webdriver.common.by import By`

        (1)By ID

    <div id = "cool" > ... < /div >
    
    element = driver.find_element_by_id("cool")
    ------------------------ or -------------------------
    element = driver.find_element(by=By.ID,value="cool")

        (2)By Class Name

    <div class = "cheese" > <span > Cheddar < /span > </div >
    <div class = "cheese" > <span > Gouda < /span > </div >
    
    element = driver.find_elements_by_class_name("cool")
    ------------------------ or -------------------------
    element = driver.find_elements(by=By.CLASS_NAME,value="cheese")

        (3)By Link Text   

    <a href = "http://www.google.com/search?q=cheese" > cheese < /a >
    
    element = driver.find_elements_by_link_text("cool")
    ------------------------ or -------------------------
    element = driver.find_elements(by=By.LINK_TEXT,value="cheese")

        (4)By Partial Link Text

    <a href = "http://www.google.com/search?q=cheese" >search for  cheese < /a >
    
    element = driver.find_elements_by_partial_link_text("cool")
    ------------------------ or -------------------------
    element = driver.find_elements(by=By.PARTIAL_LINK_TEXT,value="cheese")

        (5)By CSS

    <div id = "food" > <span class = "dairy" > milk < /span > <span class = "dairy aged" > cheese < /span > </div >
    
    element = driver.find_elements_by_css_selector("#food span.dairy.aged")
    ------------------------ or -------------------------
    element = driver.find_elements(by=By.CSS_SELECTOR, "#food span.dairy.aged")

        (6)By XPath

    <input type = "text" name = "example" / >
    <INPUT type = "text" name = "other" / >
    
    element = driver.find_elements_by_xpath("//input")
    ------------------------ or -------------------------
    element = driver.find_elements(by=By.XPATH, "//input")      

        (7)By Tag Name

    <iframe src = "..." > </iframe >
    
    element = driver.find_elements_by_tag_name("iframe")
    ------------------------ or -------------------------
    element = driver.find_elements(by=By.TAG_NAME, "iframe")

        (8)By Name

    <input name = "cheese" type = "text"/>
    
    element = driver.find_elements_by_name("cheese")
    ------------------------ or -------------------------
    element = driver.find_elements(by=By.NAME, "cheese")

    6、鼠标动作链

      通过导入ActionChains类,来实现在页面上模拟一些鼠标操作,比如双击、右击、拖拽或者按住不动等。

    # 导入webdriver
    from selenium import webdriver
    # 调用键盘按钮操作时需要引入的keys包
    from selenium.webdriver.common.keys import Keys
    # 导入ActionChains类
    from selenium.webdriver import ActionChains
    import time
    
    driver = webdriver.Chrome()
    driver.get("https://www.baidu.com")
    
    # 鼠标移动到"新闻",`ac`定义了元素的位置
    ac = driver.find_element_by_xpath("//div[@id='s-top-left']/a[1]")
    ActionChains(driver).move_to_element(ac).perform()
    time.sleep(2)
    # 鼠标移动到”hao123“
    ac = driver.find_element_by_xpath("//div[@id='s-top-left']/a[2]")
    ActionChains(driver).move_to_element(ac).perform()
    
    
    # 在ac位置单击
    # ac = driver.find_element_by_xpath("//div[@id='s-top-left']/a[1]")
    # ActionChains(driver).move_to_element(ac).click(ac).perform()
    
    # 在ac位置双击
    # ac = driver.find_element_by_xpath("//div[@id='s-top-left']/a[1]")
    # ActionChains(driver).move_to_element(ac).double_click(ac).perform()
    # 因为同时在这个地方双击,所以会弹出两个相同的窗口
    
    # 在ac位置右击
    # ac = driver.find_element_by_xpath("//div[@id='s-top-left']/a[1]")
    # ActionChains(driver).move_to_element(ac).context_click(ac).perform()
    
    # 在ac位置左键单击hold住
    # ac = driver.find_element_by_xpath("//div[@id='s-top-left']/a[1]")
    # ActionChains(driver).move_to_element(ac).click_and_hold(ac).perform()
    
    # 将ac1拖拽到ac2位置
    ac1 = driver.find_element_by_xpath("//div[@id='s-top-left']/a[1]")
    ac2 = driver.find_element_by_xpath("//div[@id='s-top-left']/a[2]")
    ActionChains(driver).drag_and_drop(ac1,ac2).perform()

    7、SELECT表单

      碰到<select></select>标签的下拉框,直接点击下拉框中的选项不一定可行。

      Selenium专门提供了Select类来处理下拉框,

    # 导入webdriver
    from selenium import webdriver
    from selenium.webdriver.support.ui import Select
    import time
    
    driver = webdriver.Chrome()
    driver.get("http://course.hbpu.edu.cn/G2S/ShowSystem/Index.aspx")
    
    # 找到class的选项卡
    """
    <select class="left search" onchange="searchChange(this)" style="margin-top:2px;">
        <option value="OrganiseSearch.aspx">组织结构</option>
        <option value="SpecialtySearch.aspx">专业</option>
        <option value="TeacherSearch.aspx">教师</option>
        <option value="CourseSearch.aspx">课程</option>
        <option value="WebsiteSearch.aspx">课程网站</option>
    </select>
    """
    # 定位后构造选择器
    select_ = Select(driver.find_element_by_xpath("//select"))
    
    # 操作select_来选择,可以通过index,value,visible_text
    select_.select_by_index(2)
    time.sleep(2)
    select_.select_by_value("SpecialtySearch.aspx")
    time.sleep(2)
    select_.select_by_visible_text("课程")
    # 状态是”教师“>>>"专业>>>”课程“

      以上是三种选择下拉框的方式,它可以根据索引来选择,可以根据值来选择,可以根据文字来选择。

      说明:(1)index索引从0开始

         (2)value是option标签的一个属性值,并不是显示在下拉框中的值

         (3)visible_text是在option标签文本中的值,是显示在下拉框的值

      如果全部取消选择:`select.deselect_all()`

    8、弹窗处理

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

      `alert = driver.switch_to_alert()`

    9、页面切换

      切换浏览器个页面窗口的方法:`driver.switch_to.window("this is window name")`

      使用window_handles方法来获取每个窗口的操作对象:

      ```

      for    handle    in    driver.window_handles:

        driver.switch_to_window(handle)

      ```

    10、页面前进或后退

      操作页面的前进和后退功能:

      ```

      driver.forward()  #前进

      driver.back()  #后退

      ```

    11、Cookies

      获取页面每个Cookies值,用法如下:

      ```

      for    cookie    in    driver.get_cookies():

        print("{} -> {}".format(cookie['name'],cookie['value']))

      ```

      删除Cookies,用法如下:

      ```

      # 通过name

      driver.delete_cookie("CookieName")

      # 删除所有

      driver.delete_all_cookies()

      ```

    12、页面等待

      现在的网页越来越多采用了 Ajax 技术,这样程序便不能确定何时某个元素完全加载出来了。如果实际页面等待时间过长导致某个dom元素还没出来,但是你的代码直接使用了这个WebElement,那么就会抛出NullPointer的异常。

      为了避免这种元素定位困难而且会提高产生 ElementNotVisibleException 的概率。所以 Selenium 提供了两种等待方式,一种是隐式等待,一种是显式等待。

      隐式等待是等待特定的时间,显式等待是指定某一条件直到这个条件成立时继续执行

      12.1 显式等待

        显式等待指定某个条件,然后设置最长等待时间,如果在这个时间还没有找到元素,那么便会抛出异常。

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    # 导入WebDriverWait库,负责循环等待
    from selenium.webdriver.support.ui import WebDriverWait
    # 导入expected_conditions类,负责条件触发
    from selenium.webdriver.support import expected_conditions as EC
    
    driver = webdriver.Chrome()
    driver.get("http://www.baidu.com")
    try:
        # 页面一致循环,直到id="myDynamicElement"出现
        element=WebDriverWait(driver,10).until(
            EC.presence_of_element_located((By.ID,"myDynamicElement"))
        )
    finally:
        driver.quit()

        如果不写参数,程序默认会0.5s调用一次来查看元素是否已经生成,如果本来元素就是存在,那么会立即返回。

        expected_conditions中内置的等待条件,可以直接调用这些条件,而不用自己写某些等待条件:

        `title_is`

        `title_contains`

        `persence_of_element_located`

        `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`

        `invisibility_of_element_located`

        `element_to_be_clickable-it is Displayed and Enabled`

        `staleness_of`

        `element_to_be_selected`

        `element_located_to_be_selected`

        `element_selection_state_to_be`

        `element_location_selection_state_to_be`

        `alert_is_present`

      12.2 隐式等待

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

    from selenium import webdriver
    
    driver = webdriver.Chrome()
    driver.implicitly_wait(10) #等待10s
    driver.get('http://www.baidu.com')
    myDynamicElement = driver.find_element_by_id("myDynamicElement")

        如果不设置,则默认等待时间为0。    

  • 相关阅读:
    ABAP开发者上云的时候到了
    1074. 宇宙无敌加法器(20)
    1073. 多选题常见计分法(20)
    1072. 开学寄语(20)
    1071. 小赌怡情(15)
    1049. Counting Ones (30)
    1047. Student List for Course (25)
    1044. Shopping in Mars (25)
    1043. Is It a Binary Search Tree (25)
    1040. Longest Symmetric String (25)
  • 原文地址:https://www.cnblogs.com/nuochengze/p/12865227.html
Copyright © 2011-2022 走看看