python+selenium 自动拖拽滑块

selenium 自动拖拽滑块以顺丰单号查询为例

  • 网址: https://www.sf-express.com/we/ow/chn/sc/waybill/waybill-detail/SFxxxx 后面是订单编号

    • 先看 滑块
      python+selenium 自动拖拽滑块_第1张图片
    • 这种滑块解决方案很多,本文是参照极验滑动验证码 ;获取滑动验证码完整背景和滑动时展现的背景,二者进行像素点比较,取最左侧不相同的像素点的位置left,即是我们要滑动的位置相对于图像最左侧的位置,届时再减去滑块按钮所在的x轴位置x_pos,就可以得到我们要滑动的长度。
    • 此方案的难点在于如何获取完整的背景图(当然方法也不止一种)
  • 这里我们很容易就找到了缺块的背景图
    python+selenium 自动拖拽滑块_第2张图片

    • 完整的背景图改如何获取呢,这时候笔者误打误撞发现了一个有意思的链接
      python+selenium 自动拖拽滑块_第3张图片
    • 这个 * 难道是一个分隔符 抱着试试的态度 访问了一下 * 前面的链接 果然
      python+selenium 自动拖拽滑块_第4张图片
    • 有了完整图片剩下的不就好弄了
      • 首先,把两张图片保存到本地(当然这里也可以参考极验 使用selenium带的截图功能,因为这里笔者没有找到限定的元素,没法使用js得到完整的背景,只能出此下策了)
      • 使用selenium获取元素 这里要注意 等待 iframe 加载
      • 关于拖动的时候注意 像素点;笔者这里就被坑了;你保存下来的图片大小和实际是有出入的,这里需要自己去计算
  • 最后附上代码(仅供参考)

# Author: Lovy
# File : 04_滑块
# Time : 2022-08-20 16:25

import requests
from selenium import webdriver
from time import sleep
from PIL import Image
from selenium.webdriver import ActionChains
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

headers = {
    'Referer': r'https://t.captcha.qq.com/cap_union_new_show?aid=2037219860&protocol=https&accver=1&showtype=popup&ua=TW96aWxsYS81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV09XNjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS85OS4wLjQ4NDQuNTEgU2FmYXJpLzUzNy4zNg%3D%3D&noheader=1&fb=1&aged=0&enableAged=0&enableDarkMode=0&grayscale=1&clientype=2&userLanguage=zh-cn&sess=s0UU0F8r06RUZ9PBVu2eNVsgV_g9hGQrupqfh3xEkQPybQOkMmGtit-awx8nE2_VV1zQAtQHDxcaNsr1zRC1y8j3p9vdCMegNL6x43id3TLhDtZXtbOy8yCBnmpmibs6cSucWri9CjhUpxhw82wPr21EHtsg3QAhSunNBe4T3zeRtWhMDmDG5KEKXgPArssRGIUAHtVvvpznlJcmL3mthvyagLJaoYtsnIQRZbRjm5ATqRv5vGe-Pav3NWPRuAJkBSM8sj0hr-niA*&fwidth=0&sid=6966721938633166848&wxLang=&tcScale=1&uid=&cap_cd=&rnd=414726&prehandleLoadTime=113&createIframeStart=1660995944597&global=0&subsid=2',
    'Host': 't.captcha.qq.com',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36',
}


class MyDriver():
    def __init__(self):
        self.x_pos = 0
        self.option = webdriver.ChromeOptions()
        self.driver = webdriver.Chrome(options=self.option)
        self.driver.maximize_window()
        self.driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
            "source": """Object.defineProperty(navigator, 'webdriver', {get: () => undefined})""",
        })

    def get_url(self, url):
        self.driver.get(url)
        sleep(5)  # 如何显式等待 iframe加载

    def switch_frame(self):
        frame_element = self.driver.find_element('id', 'tcaptcha_iframe')
        WebDriverWait(self.driver, 10, 0.5).until(
            EC.frame_to_be_available_and_switch_to_it(frame_element))

        element_locator = ('id', 'slideBg')
        WebDriverWait(self.driver, 10, 0.5).until(
            EC.visibility_of_element_located(element_locator))

    def get_gap(self, image1, image2):
        left = 60
        for i in range(left, image1.size[0]):
            for j in range(image1.size[1]):
                if not self.is_pixel_equal(image1, image2, i, j):
                    left = i
                    return left
        return left

    def is_pixel_equal(self, image1, image2, x, y):
        pixel1 = image1.load()[x, y]
        pixel2 = image2.load()[x, y]
        threshold = 60
        if abs(pixel1[0] - pixel2[0]) < threshold and abs(pixel1[1] - pixel2[1]) < threshold and abs(
                pixel1[2] - pixel2[2]) < threshold:
            return True
        else:
            return False

    def img_cv(self):
        img = self.driver.find_element('id', 'slideBg')
        src = img.get_attribute('src')
        img1 = requests.get(url=src, headers=headers)
        with open("temp_img1.png", 'wb') as f:
            f.write(img1.content)
        img2 = requests.get(url=src[:417], headers=headers)
        with open("temp_img2.png", 'wb') as f:
            f.write(img2.content)
        img1_ = Image.open('temp_img1.png')
        img2_ = Image.open('temp_img2.png')
        self.x_pos = self.get_gap(img1_, img2_)

    def move(self, url):
        self.get_url(url)
        self.switch_frame()
        self.img_cv()
        ele_huakuai = self.driver.find_element('id', 'tcaptcha_drag_button')
        ActionChains(self.driver, duration=1000).drag_and_drop_by_offset(ele_huakuai, self.x_pos // 2 - 35, 0).perform()
        sleep(0.5)
        self.driver.find_element('id', 'tcaptcha_drag_button').click()


if __name__ == '__main__':
    url = "https://www.sf-express.com/we/ow/chn/sc/waybill/waybill-detail/SFxxxx" # 单号填自己的
    mydriver = MyDriver()
    mydriver.move(url)

  • 最后在说一点利用Python+Selenium破解春秋航空网滑块验证码的实战过程这篇文章写的也不错;可以把所有的验证完整背景提前保存下来,对比背景图左上角顶点处的像素值,确定对应的背景,也是一种不错的思路

你可能感兴趣的:(UI自动化,python,selenium,开发语言)