巧用 selenium 解决验证码,模拟登陆某网站

本文以模拟登录B站为例,介绍了使用Python的Selenium库和超级鹰打码平台破解点选验证码的方法。先介绍了验证码及打码平台,接着说明了准备工作,然后阐述实现思路,最后给出Python代码实现,包括获取API、分析B站登录界面和具体操作步骤,最终成功模拟登录。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


来源:Python数据之道

作者:叶庭云

整理:Lemon

一、前言

1. 介绍

验证码多种多样,有图形文字的、有模拟点选的、有拖动滑动的,但其实归根结底都需要人来对某种情形做一些判断,然后把结果返回并提交。

如果此时提交的验证码结果是正确的,并且通过了一些验证码的检测,就能成功突破这个验证码了。既然验证码就是让人来识别的,那么机器怎么办呢?

如果我们也不会什么算法,怎么去解这些验证码呢?此时我们需要利用可以帮助我们来识别验证码的工具或平台就,让工具或平台把验证码识别的结果返回给我们,我们拿着结果提交,那不就好了吗?

有专门的打码平台帮助我们来识别各种各样的验证码,平台内部对算法和人力做了集成,可以 7x24 小时来识别各种验证码,包括识别图形、坐标点、缺口等各种验证码,返回对应的结果或坐标,正好可以解决我们的问题,比如超级鹰

B站最新登录验证为点选验证码,以模拟登录 B 站来熟悉 selenium 库的使用和打码平台的使用方法。

这个验证码上面显示了几个汉字,同时在图中也显示了几个汉字,我们需要按照顺序依次点击汉字在图中的位置,点击完成之后确认提交,即可完成验证。这种验证码如果我们没有任何图像识别算法基础的话,是很难去识别的,所以这里我们可以借助打码平台来帮助我们识别汉字的位置。

2. 准备工作

本文用到的 Python 库是 Selenium,使用的浏览器为 Chrome,确保已经正确安装好 Selenium 库、Chrome 浏览器,并配置好 ChromeDriver,

使用的打码平台是超级鹰,链接为:https://www.chaojiying.com/,在使用之前请读者自行注册账号并获取一些题分供测试,另外还可以了解平台可识别的验证码的类别。

打码平台能提供的服务种类一般都非常广泛,可识别的验证码类型也非常多,其中就包括点触验证码。

超级鹰平台同样支持简单的图形验证码识别,超级鹰平台提供了如下一些服务:

  • 英文数字:提供最多 20 位英文数字的混合识别;

  • 中文汉字:提供最多 7 个汉字的识别;

  • 纯英文:提供最多 12 位的英文识别;

  • 纯数字:提供最多 11 位的数字识别;

  • 任意特殊字符:提供不定长汉字英文数字、拼音首字母、计算题、成语混合、集装箱号等字符的识别;

  • 坐标选择识别:如复杂计算题、选择题四选一、问答题、点击相同的字、物品、动物等返回多个坐标的识别;

本例需要处理的就是坐标多选识别的情况。我们先将验证码图片提交给平台,平台会返回识别结果在图片中的坐标位置,然后我们再解析坐标模拟点击,下面我们就用程序来实现。

二、实现思路

三、Python代码实现

1. 获取API

通过官方网站下载对应的 Python API,链接为:https://www.chaojiying.com/api-14.html。API 是 Python 2 版本的,用 requests 库来实现的。我们可以简单更改几个地方,即可将其修改为 Python 3 版本。

修改之后的 API 如下所示:

# -*- coding: UTF-8 -*-
# Chaojiying_Client类  用于提交要识别的图片  返回json结果
class Chaojiying_Client(object):
    def __init__(self, username, password, soft_id):
        self.username = username
        password = password.encode('utf-8')
        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/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
        }

    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)
        logging.info(r.json())
        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)
        logging.info(r.json())
        return r.json()

  • 这里定义了一个 Chaojiying 类,其构造函数接收三个参数,分别是超级鹰的用户名、密码以及软件 ID,保存以备使用。

  • 最重要的一个方法叫作 post_pic,它需要传入图片对象和验证码类型的代号。该方法会将图片对象和相关信息发给超级鹰的后台进行识别,然后将识别成功的 json 返回。

  • 另一个方法叫作 report_error,它是发生错误时的回调。如果验证码识别错误,调用此方法会返回相应的题分。

2. 分析B站登录界面

进入登陆界面,定位用户名和密码对应的标签,模拟输入我们的账号和密码,点击登录,此时页面会弹出验证码。

对进行验证码的获取,然后提交给「超级鹰」进行识别,接收到汉字的坐标后,处理数据,然后用动作链进行模拟点击操作,最后定位点击确认,实现成功登录 B 站。

3. 具体实现

导入用的库

from selenium import webdriver
from time import sleep
from PIL import Image
from selenium.webdriver import ActionChains
import random
import requests
from hashlib import md5
import logging

日志输出和 webdriver.Chrome() 配置

# 日志输出配置
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s: %(message)s')
# 初始化一个webdriver.Chrome()对象
chrome_driver = r'D:\python\pycharm2020\chromedriver.exe'
options = webdriver.ChromeOptions()
# 关闭左上方 Chrome 正受到自动测试软件的控制的提示
options.add_experimental_option('useAutomationExtension', False)
options.add_experimental_option("excludeSwitches", ['enable-automation'])
browser = webdriver.Chrome(options=options, executable_path=chrome_driver)

用 selenium 打开登录页面,进行模拟登录

# 登录函数   访问页面->输出账号、密码->点击登录
def login():
    browser.get('https://passport.bilibili.com/login')
    browser.maximize_window()
    # ID定位用户名,密码输入框
    username = browser.find_element_by_id('login-username')
    password = browser.find_element_by_id('login-passwd')
    username.send_keys('your username')
    password.send_keys('your password')
    # Xpath定位登录按钮并点击
    browser.find_element_by_xpath('//*[@id="geetest-wrap"]/div/div[5]/a[1]').click()
    sleep(random.random()*3)

将当前页面进行截图并保存下来,裁剪出验证码区域

def save_img():
    # save_screenshot:将当前页面进行截图并保存下来
    browser.save_screenshot('page.png')
    # Xpath定位验证码图片的位置
    code_img_ele = browser.find_element_by_xpath('/html/body/div[2]/div[2]/div[6]/div/div')
    location = code_img_ele.location  # 验证码左上角的坐标x,y
    size = code_img_ele.size  # 验证码图片对应的长和宽

    # 得到左上角和右下角的坐标
    rangle = (
        int(location['x'] * 1.25), int(location['y'] * 1.25), int((location['x'] + size['width']) * 1.25),
        int((location['y'] + size['height']) * 1.25)
    )
    image1 = Image.open('./page.png')
    # code_img_name = './code.png'
    # crop根据rangle元组内的坐标进行裁剪 裁剪出验证码区域
    frame = image1.crop(rangle)
    frame.save('./code.png')
    return code_img_ele

将点击登录后的页面进行截图,然后定位到验证码的位置,通过location()方法获取验证码左上角的坐标, size() 获取验证码的宽和高,左上角坐标加上宽和高就是验证码右下角的坐标。获取坐标后就可以用 crop() 方法来进行裁剪,然后将裁剪到的验证码图片保存。

缩小图片

def narrow_img():
    # 缩小图片
    code = Image.open('./code.png')
    small_img = code.resize((169, 216))
    small_img.save('./small_img.png')
    print(code.size, small_img.size)

此时虽然获取了验证码图片,但是还不能直接提交给超级鹰。因为超级鹰识别的验证码图片的宽和高有限制,最好不超过460px*310px。但是截取到的验证码图片宽高为338px*432px,这时就要先将图片缩小一倍再提交即可,等到收到坐标数据再将坐标乘2。

将验证码提交给超级鹰进行识别

def submit_img():
    # 将验证码提交给超级鹰进行识别
    # 用户中心->软件ID 生成你的软件ID->替换掉96001  绑定微信可以得到1000积分 免费使用
    chaojiying = Chaojiying_Client('你的用户名', '密码', '生成的软件ID')
    with open('./small_img.png', 'rb') as f:
        im = f.read()
    # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
    result = chaojiying.PostPic(im, 9004)['pic_str']
    logging.info(result)
    return result

调用已获取的API,传入参数:'你的用户名', '密码','生成的软件ID'

解析返回的汉字的坐标点的结果

def parse_data(result):
    node_list = []  # 存储即将被点击的点的坐标  [[x1,y1],[x2,y2]]
    print(result)
    if '|' in result:
        nums = result.split('|')
        for i in range(len(nums)):
            x = int(nums[i].split(',')[0])
            y = int(nums[i].split(',')[1])
            xy_list = [x, y]
            node_list.append(xy_list)
    else:
        print(result.split(',')[0])
        print(result.split(',')[1])
        x = int(result.split(',')[0])
        y = int(result.split(',')[1])
        xy_list = [x,y]
        node_list.append(xy_list)
    return node_list

超级鹰识别返回的结果的数据格式为:98,136|87,77 我们可以将数据以' | '进行分割,保存到列表中,再以逗号分割将x,y的坐标保存,得到[ [123,12],[234,21] ]这一格式,然后遍历这一列表,使用动作链对每一个列表元素对应的x,y指定的位置进行模拟点击操作,最后定位并点击确认,可成功实现登录 B 站。

按顺序模拟点击每个坐标点

def click_codeImg(all_list, code_img_ele):
    # 遍历列表,使用动作链对每一个列表元素对应的x,y指定的位置进行点击操作
    for item in all_list:
        x = item[0] * 1.6
        y = item[1] * 1.6
        # move_to_element_with_offset移动到距某个元素(左上角坐标)多少距离的位置
        ActionChains(browser).move_to_element_with_offset(code_img_ele, x, y).click().perform()
        sleep(random.random())
        logging.info('点击成功!')

    sleep(random.random()*2)
    # 完成动作链点击操作后,定位确认按钮并点击
    browser.find_element_by_xpath('/html/body/div[2]/div[2]/div[6]/div/div/div[3]/a').click()

主函数调用

# -*- coding: UTF-8 -*-
def main():
    # 进入登录界面,输入账号密码
    login()
    # 保存页面截图,并根据坐标裁剪获取验证码图片
    code_img_ele = save_img()
    # 缩小图片
    narrow_img()
    # 将图片提交给超级鹰,获取返回的识别结果
    result = submit_img()
    # 解析返回结果,将数据格式化
    all_list = parse_data(result)
    # 在页面验证码上完成点击操作并登录
    click_codeImg(all_list, code_img_ele)

main()

运行效果如下:

鼠标是放在左边的,没有动过,不是人工悄悄点的哦,这样我们就成功实现了 selenium 模拟登录 B 站。

可以从一份超市数据集中分析出啥?

10大Python数据可视化库!

后台回复“入群”即可加入小z数据干货交流群
<think>嗯,用户问的是在使用Selenium时如何解决验证码的问题。首先,我需要回想一下常见的验证码类型,比如数字字母、滑动验证、点击识别等。然后,用户可能遇到的情况,比如手动处理、第三方服务或者自动化破解。我得考虑不同的解决方案,比如手动输入适用于低频率的情况,但如果是自动化测试可能需要更高效的方法。 接着,要分点说明不同的策略。比如第三方平台如打码平台,或者机器学习模型自己识别,不过后者可能需要较多资源。另外,可能还要提到如何避免触发验证码的策略,比如降低登录频率、使用Cookie等。 还要考虑用户的使用场景,如果是个人项目或小规模,手动处理可能足够,但企业级应用可能需要更可靠的方案。此外,注意提醒用户遵守网站规定,避免法律问题。可能需要给出代码示例,比如使用2Captcha的API,或者用OpenCV处理简单验证码。 另外,验证码的类型不同,解决方案也不同。比如滑动验证码可能需要模拟拖动,而点式的可能需要图像识别。还要提到一些工具库,比如Tesseract,但准确率可能不高,可能需要预处理图像。 最后,总结各种方法的优缺点,让用户根据实际情况择。同时提醒用户注意道德和法律问题,不要用于非法用途。这样用户就能全面了解不同的解决方案,并根据自己的情况做出择了。在使用</think> Selenium 进行模拟登录时,验证码(CAPTCHA)是常见的难点。验证码设计的初衷就是防止自动化操作,因此完全自动化的解决方案存在技术或法律风险。以下是几种常见应对策略,需根据实际场景择: --- ### **一、规避触发验证码** 1. **降低登录频率** 频繁登录会触发验证码,合理控制操作间隔(如添加 `time.sleep`)可降低触发概率。 2. **复用登录态(推荐)** 通过保存 Cookies 或 LocalStorage 复用登录状态,避免重复登录: ```python # 登录成功后保存 Cookies driver.get("https://example.com/login") # ...执行登录操作... cookies = driver.get_cookies() with open('cookies.json', 'w') as f: json.dump(cookies, f) # 后续直接加载 Cookies 跳过登录 driver.get("https://example.com") with open('cookies.json', 'r') as f: cookies = json.load(f) for cookie in cookies: driver.add_cookie(cookie) driver.refresh() ``` --- ### **二、人工干预方案** 1. **手动输入验证码(适合低频测试)** 在自动化流程中暂停并等待用户手动输入: ```python from selenium.webdriver.support.ui import WebDriverWait # 登录页面操作... input("请手动输入验证码后按回车继续...") # 阻塞等待手动输入 # 继续后续操作 ``` --- ### **三、半自动/全自动方案** 1. **第三方验证码识别服务(推荐用于生产环境)** 使用付费 API 如 [2Captcha](https://2captcha.com/)、[DeathByCaptcha](https://www.deathbycaptcha.com/) 等: ```python from python_anticaptcha import AnticaptchaClient # 截取验证码图片并保存 driver.save_screenshot('captcha.png') # 调用 API 识别 client = AnticaptchaClient(api_key='YOUR_API_KEY') captcha_text = client.solve_captcha('captcha.png') # 输入识别结果 driver.find_element('id', 'captcha-input').send_keys(captcha_text) ``` - **优点**: 高准确率,支持复杂验证码 - **缺点**: 需付费,依赖网络 2. **OCR 本地识别(简单数字/字母验证码)** 使用 Tesseract OCR(需安装并配置环境): ```python from PIL import Image import pytesseract # 截取验证码区域 element = driver.find_element('id', 'captcha-image') element.screenshot('captcha.png') # OCR 识别 image = Image.open('captcha.png').convert('L') # 灰度处理 text = pytesseract.image_to_string(image) driver.find_element('id', 'captcha-input').send_keys(text) ``` - **缺点**: 对扭曲、干扰线验证码效果差,需预处理图像(二值化、降噪等)。 3. **机器学习模型训练** 针对特定网站验证码,收集数据集训练 CNN 模型(需技术储备)。 --- ### **四、特殊验证码处理** 1. **滑动验证码** 模拟人类滑动轨迹(需计算滑块缺口位置): ```python from selenium.webdriver import ActionChains # 定位滑块和轨道 slider = driver.find_element('id', 'slider') track = driver.find_element('id', 'track') # 模拟拖动(示例为简单匀速滑动,实际需动态轨迹) action = ActionChains(driver) action.click_and_hold(slider).move_by_offset(300, 0).release().perform() ``` - **优化**: 使用加速度算法生成轨迹,或通过 OpenCV 识别缺口位置。 2. **点验证码** 结合图像识别(如模板匹配)定位点击坐标。 --- ### **五、注意事项** 1. **法律与道德风险** 确保操作符合目标网站的 `robots.txt` 和服务条款,避免用于非法用途。 2. **反爬升级** 部分网站会通过行为分析(鼠标轨迹、点击频率)识别自动化工具,可结合 `PyAutoGUI` 模拟更自然操作。 3. **成本权衡** 第三方 API 的调用成本需与开发成本权衡,简单场景建议优先人工干预。 --- ### **总结方案择** - **测试环境/低频使用**: 手动输入或 Cookies 复用 - **生产环境/高频需求**: 第三方验证码识别服务 - **定制化需求**: OCR + 图像处理 或 自研模型 - **技术验证**: 分析验证码接口(部分网站可通过绕过前端直接调用 API) 建议优先尝试合法合规的规避方案(如复用登录态),必要时结合业务需求择技术手段。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值