selenium作用:

  1. 自动化测试:通过它,我们可以写出⾃动化程序,模拟浏览器⾥操作web界⾯。 ⽐如点击界⾯按钮,在⽂本框中输⼊⽂字等操作。

  2. 获取信息:⽽且还能从web界⾯获取信息。 ⽐如招聘⽹站职位信息,财经⽹站股票价格信息 等等,然后⽤程序进⾏分析处理。

selenium环境:测试直接运⾏在浏览器中,就好像⼀个真正的⽤⼾在操作⼀样,⽀持⼤部分主流的浏览器,包括IE(7,8,9,10,11),Firefox,Safari,Chrome,Opera等。

selenium基本使用:
自动化程序selenium库→浏览器驱动,浏览器厂商提供→浏览器 Chrome,Firefox

  1. selenium安装:建议安装selenium4.0.0版本,因为我们在给图片定位的时候(0,0)坐标点是选在图片的左上角位置的,4.0.0版本后的版本是以图片中心定位。浏览器驱动可以自行到网上搜索对应的安装。

  2. 元素选取:

    1. ⽼版本selenium:

      在⼀个⻚⾯中有很多不同的策略可以定位⼀个元素。我们可以选择最合适的⽅法去查找元素。Selenium提供了下列的⽅法。

      单个元素查找⽅法

      作⽤

      find_element_by_xpath()

      通过Xpath查找

      find_element_by_class_name()

      通过class属性查找

      find_element_by_id()

      通过id属性查找

      find_element_by_name()

      通过name属性进⾏查找

    2. 新版本的⽤法:By对象查找,除了以上的多种查找⽅式,还有两种私有⽅法集成了上⾯的所有的查找⽅法,让我们更⽅便的使⽤。

      find_element(By.XPATH, ‘//button/span’)

      通过Xpath查找⼀个

      find_elements(By.XPATH, ‘//button/span’)

      通过Xpath查找多个

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

      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
      # wb = webdriver.Edge()
      # wb.get('https://movie.douban.com/top250')
      # wb.find_element(By.XPATH, '//span[@class="title"]')
    3. 文本输⼊和提交:

      # from selenium import webdriver
      # from selenium.webdriver.common.by import By
      # 
      # 
      # wb = webdriver.Edge()
      # wb.get("https://www.baidu.com")
      # wb.find_element(By.ID,"chat-textarea").send_keys("周杰伦")
      # wb.find_element(By.ID,"chat-submit-button").click()
  3. 动作切换:

    1. 窗⼝切换:⽤selenium操作浏览器如果需要在打开新的⻚⾯,这个时候会有问题,因为我们⽤selenium操作的是第⼀个打开的窗⼝,所以新打开的⻚⾯我们是⽆法去操作的,所以我们要⽤到切换窗⼝:即handle切换的⽅法。

      ⽅法

      作⽤

      js = 'window.open("https://www.baidu.com");'chrome.execute_script(js)

      打开新标签

      window_handles

      获取所有⻚⾯窗⼝的句柄

      current_window_handle

      获取当前⻚⾯窗⼝的句柄

      switch_to.window(window_name)

      定位⻚⾯转到指定的window_name

      ⻚⾯

      # from selenium import webdriver
      # from selenium.webdriver.common.by import By
      # 
      # 
      # wb = webdriver.Edge()
      # wb.execute_script('window.open("https://www.baidu.com")')
      # wb.execute_script('window.open("https://www.4399.com")')
      # wb.execute_script('window.open("https://www.vip.com")')
      # wb.execute_script('window.open("https://www.bing.com")')
      # 
      # wins = wb.window_handles
      # print(wb.current_window_handle)
      # print(wins)
      # wb.switch_to.window(wins[1])
      # print(wb.title)

      注意:Window_handles的顺序并不是浏览器上标签的顺序,尽量避免多标签操作。

    2. ⻚⾯切换:在实际的爬⾍中,明明定位的路径没问题,这个时候我们可以考虑⼀下是否是该⻚⾯存在frame的问题导有时候我们会遇到找不到元素的问题致的定位不到元素。

      ⽅法

      作⽤

      switch_to.frame(frame_reference)

      切到指定frame,可⽤id或name(str)、index(int)、元素(WebElement)定位

      switch_to.parent_frame()

      切到⽗级frame,如果已是主⽂档,则⽆效果, 相当于后退回去

      switch_to_default_content()

      切换到主⻚⾯,DOM树最开始的frame

      # # coding=utf-8
      # import time
      #
      # from selenium import webdriver
      # from selenium.webdriver.common.by import By
      #
      # wb = webdriver.Edge()
      # wb.maximize_window()
      #
      # wb.get('https://study.163.com/')
      #
      # time.sleep(1)
      # wb.find_element(by=By.XPATH, value='//span[@class="ux-btn th-bk-main ux-btn- ux-btn- ux-modal-btn um-modal-btn_ok th-bk-main"]').click()
      # wb.find_element(by=By.ID, value='j-nav-login').click()
      # time.sleep(1)
      # # 切换iframe标签的操作
      # fr = wb.find_element(by=By.XPATH, value='//iframe[@frameborder="0"]')
      # wb.switch_to.frame(fr)
      #
      # wb.find_element(by=By.ID, value='phoneipt').send_keys('18300000000')
      # wb.find_element(by=By.XPATH, value='//input[@placeholder="请输入密码"]').send_keys('qwe12345678')
      #
      # wb.switch_to.default_content()  # 切换到主页面
      # wb.find_element(by=By.XPATH,value='//a[@class="ux-modal_close"]').click()
    3. ⻚⾯弹窗:有的时候还会遇到弹窗的问题, 主要有两种⼀种是浏览器弹窗(alert/prompt),⼀种是⾃定义弹窗 ⾃定义弹窗,就是⼀个⾃定义的div层,是隐藏⻚⾯中的,当触发了这个弹窗后,他就显⽰出来,这种⽅式我们通过正 常的定位⽅式是可以定位到的。alert弹窗,就要⽤下⾯的⽅法处理:

      ⽅法

      作⽤

      switch_to

      定位到alert弹窗,返回⼀个弹窗的对象

      dismiss()

      对弹窗对象的取消操作(相当于点击弹窗上的取消按钮)

      accept()

      对弹窗对象的确定操作(相当于点击弹窗上的确定按钮)

      send_keys(key)

      对弹窗对象内的输⼊框输⼊数据(针对于prompt弹窗)

      text

      获取弹窗内的⽂本

  4. 等待:
    在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:超时时返回的信息

      # 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
      # 
      # wb = webdriver.Edge()
      # wb.maximize_window()
      # 
      # wb.get('https://study.163.com/')
      # 
      # wb.find_element(by=By.XPATH, value='//span[@class="ux-btn th-bk-main ux-btn- ux-btn- ux-modal-btn um-modal-btn_ok th-bk-main"]').click()
      # wb.find_element(by=By.ID, value='j-nav-login').click()
      # 
      # data = (By.XPATH, '//iframe[@frameborder="0"]')
      # WebDriverWait(driver=wb, timeout=5, poll_frequency=0.3).until(EC.presence_of_element_located(data), message='Not Found')
      # 
      # # 切换iframe标签的操作
      # fr = wb.find_element(by=By.XPATH, value='//iframe[@frameborder="0"]')
      # wb.switch_to.frame(fr)
      # 
      # wb.find_element(by=By.ID, value='phoneipt').send_keys('18300000000')
      # wb.find_element(by=By.XPATH, value='//input[@placeholder="请输入密码"]').send_keys('qwe12345678')
      # 
      # wb.switch_to.default_content()  # 切换到主页面
      # wb.find_element(by=By.XPATH,value='//a[@class="ux-modal_close"]').click()
    2. 隐性等待:隐性等待implicitly_wait(xx) :设置了⼀个最⻓等待时间,如果在规定时间内⽹⻚加载完成,则执⾏下⼀步,否则⼀直等到时间截⽌,然后执⾏下⼀步。
      弊端是程序会⼀直等待整个⻚⾯加载完成,就算你需要的元素加载出来了还是需要等待,也就是⼀般情况下你看到浏览器标签栏那个⼩圈不再转,才会执⾏下⼀步,隐性等待对整个driver的周期都起作⽤,所以只要设置⼀次即可。

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

      隐性等待和显性等待可以同时⽤,但要注意:等待的最⻓时间取两者之中的⼤者,默认等待时间为0。

    3. 强制等待:强制等待就是不论如何,在此处都需要阻塞等待⼀段时间,及time.sleep()
  5. 动作链:在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)
    移动⿏标到指定的xy位置
    move_to_element_with_offset(to_element, xoffset, yoffset)
    将⿏标移动到距某个元素多少距离的位置
    perform()
    执⾏链中的所有动作
    from selenium.webdriver import ActionChains
    from selenium.webdriver.common.by import By
    from selenium import webdriver
    
    wb = webdriver.Edge()
    wb.maximize_window()
    url = 'https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
    wb.get(url)
    # 需要选择iframe对象
    frame = wb.find_element(by = By.ID , value = "iframeResult")
    wb.switch_to.frame(frame)
    # 定位到小方块
    duixiang1 = wb.find_element(by = By.ID , value = "draggable")
    # 实例化动作链对象
    action1 = ActionChains(wb)
    # 把鼠标放到这个元素上,按鼠标左键,不松开
    action1.click_and_hold(duixiang1)
    # 往右移动一定的距离
    action1.move_by_offset(280 , 0)
    # 松开鼠标左键
    action1.release()
    # 执行动作链的操作
    action1.perform()

更多推荐