python实现自动登录某瓣,过拼图验证

一、环境介绍:

系统:window11 python:3.8 selenium:4.5
其他模块需要:requests、pillow

二、说明

总体思路:
1、利用selenium功能进行模拟鼠标、键盘自动化操作。
2、利用pillow功能进行图片的修改(主要是图片像素)
3、利用requests模块进行打码平台请求
4、利用第三方打码平台的API请求获取缺口的坐标x值,即缺口偏移量
注:此代码可以直接复制使用,代码仍有很大优化空间,本代码仅做技术研究使用,产生任何纠纷与本人无关。

本次只实现单次登录,并且即使拼图验证成功,账号本身有安全风险仍需要扫码登录。这个情况非本文探讨内容。

可以通过opencv和pillow模块实现本地识别缺口偏移量,但需要进行大量测试和准确率验证,节省时间本次采用第三方API进行识别,非广告,也可使用其他第三方API,效果一样。

未严格按照标准python工程代码格式,比如采用入口代码是:if __name__ == __main__或者创建类的方式。

三、代码使用

使用须知

1、应该知道windows系统是否开启了缩放功能,滑块起始偏移量应根据具体的缩放倍数调整,不然可能出现滑块移动位置错误的问题。
2、需要获取背景图url,通过url下载的图片往往偏大,所以使用pillow的函数调整为图片元素属性设置的大小后再计算偏移量。
3、代码中用户名和密码需要自己修改。
4、部分函数方法不接受浮点数据,出现浮点数需要转换成int
5、找不到元素,注意切换iframe,操作完还需要切换回去。
6、需要自己手动下载浏览器驱动。selenium 4.9版本后好像会自动下载驱动
7、代码使用的是chorme浏览器,绕过检测代码不一定所有版本都有效

代码

代码里面有详细解释

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support import expected_conditions as EC

import requests, json, base64, re, sys, time, os
from urllib.request import urlretrieve
from PIL import Image


def base64_api(img):
    # 图鉴官方提供的接口模板,这里稍微修改了下
    with open(img, 'rb') as f:
        b64 = base64.b64encode(f.read()).decode()

    data = {"username": "xxxx", "password": 'xxxxxx', "typeid": 33, "image": b64}

    result = json.loads(requests.post("http://api.ttshitu.com/predict", json=data).text)

    if result['success']:
        print(result)
        return result["data"]["result"]
    else:
        return result["message"]
    return ""

#获取验证图片,并调整像素
def get_bg_offset(url):
    src_png = r'.\download.png'
    resize_png = r'.\resize.png'

    #下载图片,和显示的图片大小不一样
    urlretrieve(url, src_png)

    # 打开原始图像
    image = Image.open(src_png)

    # 调整图像大小
    '''#经过元素属性查看,在页面显示的图片应该是278x198.571,resize方法不接受浮点数,
    Image.LANCZOS是改变图片大小的计算方式
    '''
    wide = 278
    high = 198.571
    resized_image = image.resize((int(wide), int(high)), Image.LANCZOS)
    # 保存修改后的图像
    resized_image.save(resize_png)
    return resize_png

#移动滑块
def move_slider(move_x,driver):
    '''
    计算滑块实际偏移量
    滑块每次起始大约离左边缘18.6个像素,这个是固定值,从元素属性中获知的。
    由于系统开启了缩放,扩大了1.5倍,故约为28个像素
    '''
    slider_x = move_x - 28
    print("鼠标移动量为:" + str(slider_x))

    #定位滑块元素
    slider_element = driver.find_element(By.XPATH,'//*[@id="tcOperation"]/div[6]')

    # 创建ActionChains对象
    actions = ActionChains(driver)

    #防止移动太快,被检测出来是自动化操作,移动多次。计算分两次移动的量
    temp = int(slider_x % 2)#取余,分两次移动可能还剩余1个像素
    slider_x /= 2

    # 按住并拖动元素,添加操作停顿时间,模拟人为操作,防止太快被判定为机器人操作
    actions.click_and_hold(slider_element).move_by_offset(int(slider_x), 0).perform()
    time.sleep(0.5)
    actions.click_and_hold(slider_element).move_by_offset(-55, 0).perform()#左移55个像素
    time.sleep(0.5)
    actions.click_and_hold(slider_element).move_by_offset(55, 0).perform()#右移55个像素
    time.sleep(0.5)
    actions.click_and_hold(slider_element).move_by_offset(int(slider_x)+temp, 0).perform()

    # 释放鼠标控制,这个是必须的,不然不进行最终验证
    actions.release().perform()

    # # 等待一段时间,可以根据需要调整等待时间
    # driver.implicitly_wait(2)
    return True


###--------------------------------------------------正式代码开始-----------------------------------------------------##
chrome_path = "./chromedriver.exe"
db_url = r"https://www.douban.com/"

driver = webdriver.Chrome(service=Service(chrome_path))

#绕过检测代码
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
    "source": """
      Object.defineProperty(navigator, 'webdriver', {
        get: () => undefined
      })
    """
})

#打开网址
driver.get(db_url)

# 将网页最大化
driver.maximize_window()

time.sleep(1)

# 先切换到 iframe
wait = WebDriverWait(driver, 10)
iframe = wait.until(EC.frame_to_be_available_and_switch_to_it((By.XPATH, '//*[@id="anony-reg-new"]/div/div[1]/iframe')))

# 定位并点击密码登录元素
password_login_element = wait.until(EC.element_to_be_clickable((By.CLASS_NAME, "account-tab-account")))
password_login_element.click()

time.sleep(0.5)
driver.find_element(By.XPATH,'//*[@id="username"]').send_keys("xxxxxx")
driver.find_element(By.XPATH,'//*[@id="password"]').send_keys("xxxxxxx")
time.sleep(1)
driver.find_element(By.XPATH,'/html/body/div[1]/div[2]/div[1]/div[5]/a').click()#点击后会弹出滑快验证窗口

#切换到验证的iframe
iframe = wait.until(EC.frame_to_be_available_and_switch_to_it((By.XPATH, '//*[@id="tcaptcha_iframe_dy"]')))
time.sleep(1.5)
# 定位验证码图片的元素
captcha_element = driver.find_element(By.XPATH,'//*[@id="slideBg"]')

# 获取验证码图片的URL
captcha_image_url = captcha_element.get_attribute("style")
print("提取到背景图片的style内容:" + captcha_image_url)

# 使用正则表达式匹配图片元素属性中的URL
url_pattern = r'url\("([^"]+)\*\*?"\)'
match = re.search(url_pattern, captcha_image_url)

if match:
    # 提取括号里面的网址
    url = match.group(1)
    print("提取的网址:", url)
else:
    print("未找到匹配的网址!")
    sys.exit(1) 

#下载、调整图片
resize_png = get_bg_offset(url)

if not os.path.exists(resize_png):
    print(f"文件 '{resize_png}' 不存在!")
    sys.exit(1)
else:
    #通过打码平台得到偏移量,转换成数字
    move_x = float(base64_api(resize_png))
    print(f"背景图片空缺位置的起始x坐标为{move_x}")

#移动滑块move_x个像素
move_slider(move_x,driver)

# 切换回主文档
driver.switch_to.default_content()

#暂停程序的运行,控制台按任意键后退出程序,关闭浏览器
os.system("pause")
#退出浏览器
driver.quit()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值