验证码处理思路流程

  1. 获取图片链接
  2. 下载图片
  3. 将图片上传到打码平台获取参数
  4. 设计滑块距离算法
  5. 自动化拟人滑动滑块

打码平台采用图鉴打码 : http://www.ttshitu.com/

1. 获取图片链接 保存图片

try:
    image_src = driver.find_element(By.XPATH, '//*[@class="vcode-spin-faceboder"]/img')
    image = image_src.get_attribute("src")
    resp = requests.get(image)
    with open('img.png', 'wb') as f:
        f.write(resp.content)
except Exception as error:
    print(error)
    browser.refresh()
    time.sleep(4)

2. 滑块距离算法设计

a. 滑块像素

  • 横轴距离50

image.png

image.png

b.滑动条长度

  • 横轴距离260

image.png

  • 根据多次计算实际的滑条距离220-235根据实际情况调整

image.png

3. 比例设计

  • 打码平台返回的是旋转度数
  • 负值代表逆时针 加上360就是顺时针角度
  • 角度 / 360 * 滑条长度 = 需要拖动的距离

    代码如下:

    if '百度安全验证' in str(driver.page_source):
        while True:
            time.sleep(random.uniform(3, 5))
            # 保存图片
            try:
                image_src = driver.find_element_by_xpath('//img[@class="vcode-spin-img"]').get_attribute('src')
                image = requests.get(rotation_image_src).content
                with open('./image.png', 'wb')as f:
                    f.write(image)
            except Exception as error:
                print(error)
                driver.refresh()
                time.sleep(4)
                continue
            try:
                # 对接打码平台
                distance_api = int(base64_api('user','passwd','img_path','type'))
            except Exception as error:
                print(error)
                continue
            print('distance api:', distance_api)
            # 计算移动距离
            if distance_api > 0:
                distance = abs(220 * distance_api / 360)
            elif distance_api < 0:
                distance = abs(abs(220 * (360 + distance_api) / 360))
            else:
                continue
            print('current distance:', distance)
            partHead = math.ceil(distance * 0.8)
            partTail = distance - partHead
            # 定位滑块
            slider_element = driver.find_element_by_xpath('//div[@class="vcode-spin-button"]/p')
            # 开始拖拽滑块
            ActionChains(driver).click_and_hold(on_element=slider_element).perform()
            ActionChains(driver).move_by_offset(xoffset=partHead, yoffset=0).perform()
            tracks = get_tracks(partTail)
            for s in tracks:
                # 特别注意yoffset可以设置随机变动,否则会被识别为机器拖动
                # ActionChains(driver).move_by_offset(xoffset=s, yoffset=random.randint(0, 5) - 3).perform()
                ActionChains(driver).move_by_offset(xoffset=s, yoffset=0).perform()
            time.sleep(0.3)
            # 释放滑块
            ActionChains(driver).release().perform()
            time.sleep(random.uniform(3, 5))
            if str(driver.page_source).find("百度安全验证") >= 0:
                continue
            else:
                return True
    • 滑动的比例,假设需要滑动的距离为X
    • 那么就是【X:235】

4. 拟人滑动算法

def get_tracks(distance):
    # 初速度
    v = 0
    # 计算间隔
    t = 0.3
    # 移动轨迹
    tracks = []
    # 当前位移
    current = 0
    # 减速阀值
    mid = distance * 4 / 5
    while current < distance:
        if current < mid:
            # 加速度为正
            # a = random.randint(30, 40)
            a = 2
        else:
            # 加速度为负
            # a = -random.randint(40, 80)
            a = -3

        # 初速度v0
        v0 = v
        # 移动距离
        s = v0 * t + 0.5 * a * (t ** 2)
        #当前位移
        current += s
        # 加入轨迹
        tracks.append(round(s))
        v = v0 + a * t
    return tracks
最后修改:2022 年 01 月 12 日
如果觉得我的文章对你有用,请随意赞赏