Selenium + 超级鹰实现猎聘网滑块验证码自动登录

Selenium + 超级鹰实现猎聘网滑块验证码自动登录

image-20251225230038895

本文介绍如何使用 Selenium 驱动 Chrome 浏览器,结合超级鹰打码平台识别腾讯滑块验证码缺口位置,实现猎聘网(liepin.com)的自动登录。

注意:本文仅用于技术学习与交流,请遵守目标网站的《使用协议》和《机器人协议》,勿用于非法用途。

环境准备

  1. Python 3.8+

  2. 安装依赖:

    pip install selenium
    
  3. 下载与本地 Chrome 浏览器版本匹配的 ChromeDriver,并确保可执行路径在环境变量中。

  4. 注册超级鹰账号,获取用户名、密码、软件ID,并准备好用于滑块识别的题型(通常为“相似图片点击”或专用滑块类型)。

超级鹰介绍

https://www.chaojiying.com/

image-20251225230932573

滑块类型

image-20251225230959402

返回的是

image-20251225231145656

核心思路

  1. 使用 Selenium 打开猎聘首页,模拟点击密码登录。
  2. 输入手机号和密码,点击登录按钮触发腾讯滑块验证码。
  3. 切换到验证码 iframe,截取背景图(含缺口)。
  4. 将背景图上传至超级鹰识别,返回缺口横坐标。
  5. 根据识别结果计算滑动距离(需减去经验偏移量)。
  6. 使用 ActionChains 生成并执行自然滑动轨迹,完成验证。

image-20251225230251777

腾讯滑块验证码弹窗截图

image-20251225230326741

超级鹰识别结果示例

image-20251225230411007

注意事项

  • 超级鹰题型选择非常重要,推荐使用“腾讯滑块专用”或“缺口位置”类型。
  • 偏移量 -55 需根据实际测试微调,不同时期可能在 50~60 之间变化。
  • 腾讯风控不断升级,反检测措施可能需要持续更新。
  • 建议加入失败重试机制(刷新验证码、重新识别)以提高成功率。

通过以上步骤,即可实现猎聘网滑块验证码的自动化识别与登录。祝大家玩得开心,技术交流,理性使用!

image-20251225230500082

完整代码1 招聘main

import logging
import random
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 配置日志(带时间戳,方便调试)
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger(__name__)

def setup_driver():
    """初始化 Chrome 浏览器并强化反检测"""
    options = webdriver.ChromeOptions()

    # 窗口设置
    options.add_argument("--start-fullscreen")  # 全屏运行,更接近真人操作

    # 核心反检测参数
    options.add_argument("--disable-blink-features=AutomationControlled")
    options.add_experimental_option("excludeSwitches", ["enable-automation"])
    options.add_experimental_option('useAutomationExtension', False)
    options.add_argument("--disable-infobars")
    options.add_argument("--no-sandbox")
    options.add_argument("--disable-dev-shm-usage")
    options.add_argument("--disable-extensions")
    options.add_argument("--disable-plugins-discovery")
    options.add_argument("--disable-web-security")
    options.add_argument("--allow-running-insecure-content")

    driver = webdriver.Chrome(options=options)

    # 深度隐藏 webdriver 特征
    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
        "source": """
            Object.defineProperty(navigator, 'webdriver', {get: () => false});
            Object.defineProperty(navigator, 'plugins', {get: () => [1, 2, 3, 4, 5]});
            Object.defineProperty(navigator, 'languages', {get: () => ['zh-CN', 'zh']});
            window.chrome = {
                runtime: {},
                loadTimes: () => undefined,
                csi: () => undefined
            };
            Object.defineProperty(navigator, 'permissions', {
                get: () => ({ query: () => Promise.resolve({ state: "granted" }) })
            });
        """
    })

    # 设置常见 User-Agent
    driver.execute_cdp_cmd("Network.setUserAgentOverride", {
        "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
    })

    logger.info("浏览器初始化完成,反检测措施已启用")
    return driver

def login(driver):
    """执行猎聘网登录流程"""
    try:
        driver.get("https://www.liepin.com/")
        logger.info("已打开猎聘首页")

        WebDriverWait(driver, 15).until(
            EC.presence_of_element_located((By.ID, "home-banner-login-container"))
        )
        logger.info("登录入口已加载")

        # 点击“密码登录”
        driver.find_element(By.XPATH, '//*[@id="home-banner-login-container"]/div/div/div/div/div[2]/div/div[2]').click()
        logger.info("已切换到密码登录方式")

        # 输入账号密码(请替换为自己的)
        driver.find_element(By.ID, "login").send_keys("1366xxxx621")
        driver.find_element(By.ID, "pwd").send_keys("555xxxxc@")
        logger.info("已填写账号密码")

        # 勾选协议
        driver.find_element(By.XPATH, '//*[@id="home-banner-login-container"]/div/div/div/div/div[4]/div/label/span[1]/input').click()
        logger.info("已勾选用户协议")

        # 点击登录触发验证码
        driver.find_element(By.XPATH, '//*[@id="home-banner-login-container"]/div/div/div/div/div[3]/div/form/button').click()
        logger.info("已点击登录按钮,等待验证码出现...")

        time.sleep(3)

    except Exception as e:
        logger.error(f"登录过程出错: {e}")
        driver.save_screenshot("login_error.png")
        raise

def handle_captcha(driver):
    """处理腾讯滑块验证码"""
    try:
        # 切换到验证码 iframe
        WebDriverWait(driver, 20).until(
            EC.frame_to_be_available_and_switch_to_it((By.ID, "tcaptcha_iframe"))
        )
        logger.info("成功切换到验证码 iframe")

        # 截取背景图
        bg_element = WebDriverWait(driver, 15).until(
            EC.presence_of_element_located((By.ID, "slideBgWrap"))
        )
        bg_element.screenshot("captcha_background.png")
        logger.info("验证码背景图已保存:captcha_background.png")

        # 超级鹰识别缺口
        from chaojiying import chaojiying_main
        raw_x, _ = chaojiying_main("captcha_background.png")
        gap_x = int(raw_x) - 55  # 经验偏移量,可在 50~60 间微调
        logger.info(f"超级鹰原始X: {raw_x} → 调整后距离: {gap_x} 像素")

        # 定位滑块
        slider = WebDriverWait(driver, 15).until(
            EC.element_to_be_clickable((By.ID, "tcaptcha_drag_thumb"))
        )
        driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", slider)
        time.sleep(0.5)

        # 生成并执行滑动轨迹
        tracks = generate_smooth_tracks(gap_x)
        ActionChains(driver).reset_actions()

        actions = ActionChains(driver)
        actions.click_and_hold(slider)
        time.sleep(random.uniform(0.2, 0.4))

        for dx, dy in tracks:
            actions.move_by_offset(xoffset=dx, yoffset=dy)

        actions.release()
        actions.perform()

        logger.info(f"滑块滑动完成,共 {len(tracks)} 步")

        # 等待观察结果
        logger.info("等待验证结果 100 秒...")
        time.sleep(100)

    except Exception as e:
        logger.error(f"验证码处理失败: {e}")
        driver.save_screenshot("captcha_failure.png")
        raise

def generate_smooth_tracks(distance):
    """生成自然滑动轨迹"""
    if distance <= 0:
        return []

    tracks = []
    current = 0
    steps = random.randint(8, 15)
    mid_ratio = random.uniform(0.65, 0.80)
    mid_point = int(distance * mid_ratio)

    for i in range(steps):
        if current < mid_point:
            progress = i / (steps * mid_ratio)
            step = int(distance * (0.1 + 0.9 * progress ** 1.5)) - current
        else:
            remaining = distance - current
            step = max(1, remaining // max(1, (steps - i)))

        step = min(step, distance - current)
        if step <= 0:
            step = 1

        tracks.append((step, random.randint(-3, 3)))
        current += step
        if current >= distance:
            break

    # 轻微超调 + 修正
    tracks.append((random.randint(3, 8), random.randint(-2, 2)))
    tracks.append((-random.randint(2, 4), random.randint(-1, 1)))

    return tracks

def main():
    driver = None
    try:
        driver = setup_driver()
        login(driver)
        handle_captcha(driver)
        logger.info("=== 自动化登录流程执行完毕 ===")
    except Exception as e:
        logger.error(f"程序运行异常: {e}")
    finally:
        logger.info("程序结束,浏览器保持打开状态")

if __name__ == "__main__":
    main()

超级鹰调用接口 修改部分

#!/usr/bin/env python
# coding:utf-8

import requests
from hashlib import md5


class Chaojiying_Client(object):

    def __init__(self, username, password, soft_id):
        self.username = username
        password = password.encode('utf8')
        self.password = md5(password).hexdigest()
        self.soft_id = soft_id
        self.base_params = {
            'user': self.username,
            'pass2': self.password,
            'softid': self.soft_id,
        }
        self.headers = {
            'Connection': 'Keep-Alive',
            'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
        }

    def PostPic(self, im, codetype):
        """
        im: 图片字节
        codetype: 题目类型 参考 http://www.chaojiying.com/price.html
        """
        params = {
            'codetype': codetype,
        }
        params.update(self.base_params)
        files = {'userfile': ('ccc.jpg', im)}
        r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files,
                          headers=self.headers)
        return r.json()

    def PostPic_base64(self, base64_str, codetype):
        """
        im: 图片字节
        codetype: 题目类型 参考 http://www.chaojiying.com/price.html
        """
        params = {
            'codetype': codetype,
            'file_base64': base64_str
        }
        params.update(self.base_params)
        r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, headers=self.headers)
        return r.json()

    def ReportError(self, im_id):
        """
        im_id:报错题目的图片ID
        """
        params = {
            'id': im_id,
        }
        params.update(self.base_params)
        r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
        return r.json()


# if __name__ == '__main__':
#     chaojiying = Chaojiying_Client('jxxxxa', '6qxxxx', '9xxxx')  #用户中心>>软件ID 生成一个替换 96001
#     im = open('../png/img.png', 'rb').read()  #本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
#     print(chaojiying.PostPic(im, 9901))  #1902 验证码类型  官方网站>>价格体系 3.4+版 print 后要加()
#     # {'err_no': 0, 'err_str': 'OK', 'pic_id': '1309619302018020027', 'pic_str': '551,98', 'md5': '11371e5d53d8f4c42a86b85802990d43'}


def chaojiying_main(png_path):
    chaojiying = Chaojiying_Client('jxxxxa', '6qxxxx1', '97xxxx1')
    im = open(png_path, 'rb').read()
    result_x = chaojiying.PostPic(im, 9901)['pic_str'].split(',')[0]
    result_y = chaojiying.PostPic(im, 9901)['pic_str'].split(',')[1]
    return result_x, result_y


# if __name__ == '__main__':
#     png_path = '../png/img.png'
#     chaojiying_main(png_path)

完结:

不知道咋写了 ,就这样吧,水平有限。

posted @ 2025-12-25 23:16  随风小屋  阅读(3)  评论(0)    收藏  举报