zoukankan      html  css  js  c++  java
  • Selenium

    前言

    WebDriver中,关于鼠标相关操作的方法都封装在ActionChains类中。

    来看看ActionChains类都提供了哪些鼠标操作的方法:

    MethodDescription
    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) 鼠标移动到某个坐标
    move_to_element(to_element) 鼠标移动到某个元素
    move_to_element_with_offset(to_element, xoffset, yoffset) 鼠标移动到距离某个元素的某个距离
    pause(seconds) 暂停输入
    release(on_element=None) 在某个元素松开鼠标左键
    send_keys(*keys_to_send) 在当前元素中输入值
    send_keys_to_element(element, *keys_to_send) 给某个元素输入值
    perform() 相应存储的动作
    reset_actions() 清除所有已存储的动作

    左键:click

    之前已经在用鼠标左键单击了,那就是click。这里再来学习使用ActionChains类中调用click

    通过访问路飞学城的轻课页面,并点击播放。

    import time
    from selenium import webdriver
    from selenium.webdriver.common.action_chains import ActionChains
    
    # 获取webdriver实例
    browser = webdriver.Chrome()
    # 访问URL
    browser.get('https://www.luffycity.com/home')
    # 获取轻课标签并点击它
    time.sleep(1)
    span3 = browser.find_element_by_class_name('span3')  # 通过分析类名发现,span3只有一个
    ActionChains(browser).move_to_element(span3).click().perform()
    # 点击视频播放按钮
    time.sleep(4)
    button = browser.find_element_by_xpath('//*[@id="router-view"]/div/div[2]/button')
    ActionChains(browser).move_to_element(button).click().perform()
    # # 关闭浏览器
    time.sleep(20)   # 可以适当调整该值
    browser.quit()
    # 截止2019-6-5,代码无误

    效果如下:

    右键:content_click

    再来个鼠标右键的示例,这次打开的是多玩LOL天赋模拟器

    有以下几点需要注意:

    • 如果反复打开这个网页,并且上一次有操作天赋模拟器,这一次会自动记录之前添加的点数。
    • 第一次点击某个技能(巫术),第一次点击会加5点,然后右键一次减一点,这时你要左键想加回来就是加1点了。要注意第一次加5点的操作。

    示例代码如下:

    import time
    from selenium import webdriver
    from selenium.webdriver.common.action_chains import ActionChains
    # 获取webdriver实例
    browser = webdriver.Chrome()
    # 访问URL
    browser.get('http://lol.duowan.com/s/talent.html#duowan')
    # 反复打开页面,有时候天赋点数会被记录,所以要先重置
    time.sleep(2)
    browser.find_element_by_xpath('//*[@id="reset-tallent"]').click()
    # 获取巫术标签并点击它增加技能点
    time.sleep(1)
    wu = browser.find_element_by_xpath('//*[@id="calculator"]/div[2]/div[1]')  # 获取巫术标签的xpath
    wu.click()  # 点击巫术增加技能点
    # 右键减少技能点
    time.sleep(2)
    ActionChains(browser).move_to_element(wu).context_click().perform()
    time.sleep(1)
    ActionChains(browser).move_to_element(wu).context_click().perform()
    # 鼠标左键在加回来
    time.sleep(1)
    wu.click()
    # 点击重置天赋按钮
    time.sleep(2)
    reset = browser.find_element_by_xpath('//*[@id="reset-tallent"]')
    ActionChains(browser).move_to_element(reset).click().perform()
    # # 关闭浏览器
    time.sleep(3)
    browser.quit()
    # 截止2019-6-5,代码无误

    效果如下:

    拖动:drag_and_drag

    所谓的拖动,也就是鼠标左键点击标签不松开,直到拖动到指定标签后再松开。

    来个玩个游戏

    示例代码如下:

    import time
    from selenium import webdriver
    from selenium.webdriver.common.action_chains import ActionChains
    
    # 获取webdriver实例
    browser = webdriver.Chrome()
    # 访问URL
    browser.get('http://www.jq22.com/demo/pintu20151229/')
    
    # 点击开始按钮,开始游戏
    time.sleep(1)
    start = browser.find_element_by_id('start')
    ActionChains(browser).move_to_element(start).click().perform()
    
    # 准备拖动,首先要找到开始和结束的两个标签
    time.sleep(2)
    img1 = browser.find_element_by_xpath('//*[@id="container"]/div[18]')  # 选中开始标签
    img2 = browser.find_element_by_xpath('//*[@id="container"]/div[18]')  # 结束标签
    ActionChains(browser).move_to_element(img1).drag_and_drop(img1, img2).perform()
    
    # 关闭浏览器
    time.sleep(3)
    browser.quit()
    # 截止2019-6-5,代码无误
    效果如下:

    滑动验证

    # -*- coding: utf-8 -*-
    # __author__ = "maple"
    
    # import time
    # from selenium import webdriver
    # driver = webdriver.Chrome()
    # driver.implicitly_wait(10)
    
    import time
    import random
    import getpass
    from PIL import Image  # 处理图片
    from selenium import webdriver
    from selenium.webdriver.common.action_chains import ActionChains
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait  # 等待页面加载某些元素
    from selenium.webdriver.support import expected_conditions as EC
    
    
    
    full_snap = 'full_snap.png'
    portion_snap = 'portion_snap.png'
    
    
    def get_img(xpath, img_path):
        """ 处理图片 """
        # 拿到带缺口的图片(整个网页),使用wait等照片加载完毕才能获取
        _canvas = wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
        # 拍个快照,这个是整个网页的快照,没有这个快照,往下就无从谈起
        driver.save_screenshot(img_path)
        # 从带缺口的图片中获取像素点
        left = _canvas.location.get('x')
        top = _canvas.location.get('y')
        right = left + _canvas.size['width']
        bottom = top + _canvas.size['height']
        # 从网页快照中截取出我们想要的带缺口的照片
        img_file_obj = Image.open(img_path)
        # 从完整的图片中,截取带缺口的部分照片并保存
        img_file = img_file_obj.crop((left, top, right, bottom))  # 裁剪,别忘了是元组类型
        # img_file.show()  # 展示裁剪后的图片
        img_file.save(img_path)  # 保存裁剪后的图片
        return img_file
    
    
    # def get_distance(portion_img, full_img):
    #     """ 对比上一步中获取的两张图片,获取位移并返回 """
    #     for x in range(60, full_img.size[0]):  # 循环x轴,理解为行
    #         for y in range(20, full_img.size[1] - 20):  # 循环y轴,理解为列
    #             # print(x, y)
    #             rgb_portion = portion_img.getpixel((x, y))
    #             rgb_full = full_img.getpixel((x, y))
    #             if not (abs(rgb_portion[0] - rgb_full[0] < 60) and abs(rgb_portion[1] - rgb_full[1] < 60) and abs(
    #                 rgb_portion[2] - rgb_full[2] < 60)):
    #                 return x - 8  # 这个不一样的像素点,就是我们想要的,在尝试多次后,该像素点减7后准确率会提高
    
    
    def get_distance(image1, image2):
        p1 = image1.load()
        p2 = image2.load()
        x = 60
        for i in range(x, image1.size[0]):
            for j in range(20, image1.size[1] - 20):
                print(i, j)
                dot1 = p1[i, j]
                dot2 = p2[i, j]
                r = abs(dot1[0] - dot2[0])
                g = abs(dot1[1] - dot2[1])
                b = abs(dot1[2] - dot2[2])
                if not (r < 60 and g < 60 and b < 60):
                    return i - 7
                    # return i
        return i  # 当返回这个i的时候,意味着破解失败了,因为没有找到合适的位移点
    
    
    def get_tracks(distance):
        """ 根据distance值,模拟出一段段的滑动轨迹,位移公式: s=V0t+(at^2)/2 """
        track = []
        current = 0  # 当前速度 0
        mid = distance * 3 / 5  # 前3/5是匀加速运动,后2/5是匀减速
        # t = random.randint(1, 3) / 10  # 0.2 或者 0.3
        # t = 0.18456
        t = 0.3
        v = 0  # 初始速度
        while current < distance:
            if current < mid:  # 前半段,是匀加速
                a = random.randint(2, 3)
            else:
                a =  - random.randint(2, 3)
            v0 = v
            v = v0 + a * t
            move = v0 * t + 0.5 * a * (t ** 2)
            current += move
            track.append(round(move))  # 取整
        return track
    
    
    def crack_luffy_signin(user, pwd):
        """ 破解路飞学城登录的极验验证 """
    
        try:
            # 第1步:访问URL
            driver.get('https://account.cnblogs.com/signin?returnUrl=http%3a%2f%2fi.cnblogs.com%2f')
    
            # 第2步,获取用户名和密码标签并输入相应的值
            time.sleep(1)
            driver.find_element_by_id('LoginName').send_keys(user)
            driver.find_element_by_id('Password').send_keys(pwd)
            driver.find_element_by_class_name('ladda-label').click()
    
            # 第4步,拿到缺口和完整图片,用于后续做对比
            # 4.1 获取缺口图片
            time.sleep(1)
            portion_img = get_img('/html/body/div[2]/div[2]/div[6]/div/div[1]/div[1]/div/a/div[1]/div/canvas[1]',
                                  portion_snap)  # 传递缺口图片标签的xpath和图片名称
    
            # 4.2 获取完整的图片,但由于完整图片默认是隐藏的,我们无法截取,所以先让它显示出来
            # 4.2.1 通过js脚本将隐藏标签显示出来
            time.sleep(1)
            # 4.2.2 执行js脚本
            js = "document.getElementsByClassName('geetest_canvas_fullbg geetest_fade geetest_absolute')[0].style.display='block'"
            driver.execute_script(js)
    
            # 4.3 获取完整图片截图
            time.sleep(0.5)
            full_img = get_img('/html/body/div[2]/div[2]/div[6]/div/div[1]/div[1]/div/a/div[1]/canvas',
                               full_snap)  # 传递完整图片标签的xpath和图片名称
    
            # 第5步,对比两张图的像素RGB,得到不一样的像素点,取位移
            distance = get_distance(portion_img, full_img)
            # print(distance)  # 97就是我们想要的位移,并且这个值是不固定的
    
            # 第6步,获取移动轨迹
            tracks_list = get_tracks(distance)
    
            # 第7步, 按照轨迹列表开始匀加速再匀减速运动,水平移动
            # 7.1 获取滑动按钮
            geetest_slider_button = wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'geetest_slider_button')))
            # 7.2 按住不放
            ActionChains(driver).click_and_hold(geetest_slider_button).perform()
            print(1111, tracks_list)
            for track in tracks_list:
                print(22222222222,track)
                ActionChains(driver).move_by_offset(xoffset=track, yoffset=0).perform()  # 水平移动,所以x轴在变,y轴不变
            # else:  # 模拟人滑动到缺口位置之后再滑动一点再滑动回来
            ActionChains(driver).move_by_offset(xoffset=3, yoffset=0).perform()
            ActionChains(driver).move_by_offset(xoffset=-3, yoffset=0).perform()
            # 在滑到位置后,不是立即松开,而是在一段时间之后再松开
            ActionChains(driver).pause(random.randint(6, 15) / 10).release(geetest_slider_button).perform()
    
            # 第8步,获取确定按钮并点击
            # time.sleep(2)
            # driver.find_element_by_xpath('//*[@id="router-view"]/div/div/div[2]/div[2]/button').click()
    
    
        finally:
            # 关闭浏览器
            time.sleep(3)
            driver.quit()
    
    
    if __name__ == '__main__':
        user = input('输入你的用户名: ').strip() # 替换为你的用户名
    
        pwd = getpass.getpass('输入的密码: ').strip()  # 替换为你的密码
        # 获取webdriver实例
        driver = webdriver.Chrome()
        wait = WebDriverWait(driver, 10)
        crack_luffy_signin(user, pwd)
    
    # try:
    #     driver.get('https://account.cnblogs.com/signin?returnUrl=http%3a%2f%2fi.cnblogs.com%2f')
    #
    #     driver.find_element_by_id('LoginName').send_keys('11111')
    #     driver.find_element_by_id('Password').send_keys('22222')
    #     driver.find_element_by_class_name('ladda-label').click()
    #
    # except Exception as e:
    #     print(e)
    # finally:
    #     time.sleep(20)
    #     driver.quit()
    View Code

    效果:

    下拉菜单选择

    下拉菜单这里可以有三种方式选择:

    • select_by_index(id),通过id选择。
    • select_by_value(value值),通过value值选择。
    • select_by_text(“中国”),通过显示的文本内容选择。

    现在通过路飞学城的注册页面来演示下拉菜单的操作:

    import time
    from selenium import webdriver
    from selenium.webdriver.support.ui import Select
    
    # 获取webdriver实例
    browser = webdriver.Chrome()
    # 访问URL
    browser.get('https://www.luffycity.com/signup')
    # browser.maximize_window()  # 窗口最大化
    time.sleep(1)
    # 定位到select标签
    select = browser.find_element_by_class_name('phone_select')
    Select(select).select_by_value('355')  # 根据value值选择
    # 关闭浏览器
    time.sleep(3)
    browser.quit()
    # 截止2019-6-6,代码无误

    效果如下:

    模拟hover事件

    hover也就是鼠标悬浮,那么使用selenium怎么实现呢?

    通过一个悬浮事例来学习。

    事例以淘宝官网为例,要求:

    • 循环悬浮主题市场列表。
    • 然后悬浮【女装/男装/内衣】,并点击其内的【夏上新】。
    import time
    from selenium import webdriver
    from selenium.webdriver import ActionChains as AC
    
    driver = webdriver.Chrome()
    
    driver.get('https://www.taobao.com/')
    
    # 获取 主题市场 列表
    menu_list = driver.find_elements_by_class_name('J_Cat')
    print(menu_list.__len__())
    for i in menu_list:   # 循环模拟鼠标悬浮
        AC(driver).move_to_element(i).perform()
        time.sleep(0.5)
    
    # 悬浮到 女装/男装/内衣
    time.sleep(2)
    AC(driver).move_to_element(menu_list[0]).perform()
    # 点击其内的 夏上新 链接
    time.sleep(2)
    obj = driver.find_element_by_xpath('/html/body/div[4]/div[1]/div[1]/div[1]/div/div/div[1]/div[1]/div[1]/p/a[1]')
    print(obj.text)
    obj.click()
    
    time.sleep(6)
    driver.quit()
  • 相关阅读:
    JVM内存参数详解以及配置调优
    Sublime Text 3安装AngularJS插件
    GraphicsMagick安装&make命令使用
    清明节太原两日游
    Java异常处理机制 try-catch-finally
    成都一日游
    降低PNG图片存储大小方法、图片压缩方法
    Windows 10下mysql 64位 安装(mysql-5.7.11-winx64安装)
    解决-Dmaven.multiModuleProjectDirectory system property is not set. Check $M2_HOME environment variabl
    centos 7下Hadoop 2.7.2 伪分布式安装
  • 原文地址:https://www.cnblogs.com/sundawei7/p/11959006.html
Copyright © 2011-2022 走看看