Python突破文字点选验证码实现自动登录

大概步骤

  1. 打开网页
  2. 输入账号、密码并且点击登录按钮
  3. 截图
  4. 获取验证码图片的坐标
  5. 裁剪验证码图片
  6. 使用接口,获得验证码坐标
  7. 按顺序点击验证码并且点击确定

每一步函数的代码

对象初始化

BIG_PATH = './big_path.jpg'
SMALL_PATH = './small_path.jpg'
img_code_obj = ""
url = '你猜猜~'

def __init__(self, username, password):
    self.zb = None
    self.username = username
    self.password = password
    self.page = None

打开网页

async def open_the_webpage(self):
    '''
    1.打开网页,并且输入账号密码,点击登录按钮
    2.当验证码出来后,截取整个网页以及验证码
    3.接入打码平台,获取验证码坐标数据
    4.对验证码进行操作,并且点击确定
    '''
    # 启动 pyppeteer 属性设置
    browser = await pyppeteer.launch(headless=False)
    self.page = await browser.newPage()
    await self.page.setViewport({'width': 1400, 'height': 800})
    await self.page.goto(self.url)

    # 登录
    await self.login()

输入账号、密码并且点击登录按钮

async def login(self):
    '''
    进行登录操作
    '''
    # 等待页面加载完成
    await self.page.waitFor('div[class="wel"]')
    # 找到密码输入界面
    button = await self.page.querySelector('div[class="one"]')
    await button.click()
    # 输入用户名和密码
    await self.page.waitFor('input[placeholder="请输入账号"')
    await self.page.type('input[placeholder="请输入账号"]', self.username, {'delay': 100})
    await self.page.type('input[placeholder="请输入密码"]', self.password, {'delay': 100})
    button = await self.page.querySelector('button[class="el-button btn el-button--default"]')
    await button.click()

截图整个页面

async def intercept_a_web_page(self):
    # 当验证码出来后,截取整个网页以及验证码
    # 等待验证码出来
    time.sleep(3)
    # 截取整个网页
    await self.page.screenshot({'path': self.BIG_PATH})
    # 获取验证码图片坐标
    await self.get_xpath_element()

获取验证码图片坐标

async def get_xpath_element(self):
    # 获取验证码的element元素
    el = await self.page.xpath("//div[starts-with(@style,'background-image: url')]")
    self.zb = await el[0].boundingBox()

    # 裁剪验证码图片
    await self.image_shot()

裁剪验证码图片

async def image_shot(self):
    # 截取一部分图片
    left = int(self.zb['x'])
    upper = int(self.zb['y'])
    right = int(self.zb['x']) + int(self.zb['width'])
    lower = int(self.zb['y']) + int(self.zb['height'])

    # 打开一个文件
    img = Image.open(self.BIG_PATH)
    # 切图片
    img_obj = img.crop((left, upper, right, lower))
    # 保存图片
    img_obj.save(self.SMALL_PATH)

    # 使用接口,获得验证码坐标
    coordinate = await self.base64_api()
    # 按顺序点击验证码并点击确定
    await self.image_click(coordinate)

使用接口,获得验证码坐标

async def base64_api(self, typeid=27):
    with open(self.SMALL_PATH, 'rb') as f:
        base64_data = base64.b64encode(f.read())
        b64 = base64_data.decode()
    data = {"username": 'sb9728',
            "password": 'sb9728565',
            "typeid": typeid,
            "image": b64
            }
    reps = requests.post("https://api.ttshitu.com/predict", json=data)
    if reps.status_code == 200:
        result = reps.json()
        return result
    else:
        return {'code': '-1'}

按顺序点击验证码并点击确定

async def image_click(self, coordinate):
    result_list = coordinate['data']['result'].split('|')
    # 操作鼠标点击指定坐标
    for itme in result_list:
        x = itme.split(',')[0]
        y = itme.split(',')[1]
        await self.page.mouse.click(int(self.zb['x']) + int(x), int(self.zb['y']) + int(y), {'delay': 500})
    el = await self.page.xpath("//div[starts-with(@class,'geetest_submit_')]")
    await el[0].click()

全部代码

import pyppeteer
import asyncio
import time
from PIL import Image
import base64
import requests


class auto_login:
    BIG_PATH = './big_path.jpg'
    SMALL_PATH = './small_path.jpg'
    img_code_obj = ""
    url = '你猜猜~'

    def __init__(self, username, password):
        self.zb = None
        self.username = username
        self.password = password
        self.page = None

    async def open_the_webpage(self):
        '''
        1.打开网页,并且输入账号密码,点击登录按钮
        2.当验证码出来后,截取整个网页以及验证码
        3.接入打码平台,获取验证码坐标数据
        4.对验证码进行操作,并且点击确定
        '''
        # 启动 pyppeteer 属性设置
        browser = await pyppeteer.launch(headless=False)
        self.page = await browser.newPage()
        await self.page.setViewport({'width': 1400, 'height': 800})
        await self.page.goto(self.url)

        # 登录
        await self.login()

    async def login(self):
        '''
        进行登录操作
        '''
        # 等待页面加载完成
        await self.page.waitFor('div[class="wel"]')
        # 找到密码输入界面
        button = await self.page.querySelector('div[class="one"]')
        await button.click()
        # 输入用户名和密码
        await self.page.waitFor('input[placeholder="请输入账号"')
        await self.page.type('input[placeholder="请输入账号"]', self.username, {'delay': 100})
        await self.page.type('input[placeholder="请输入密码"]', self.password, {'delay': 100})
        button = await self.page.querySelector('button[class="el-button btn el-button--default"]')
        await button.click()

        # 截图
        await self.intercept_a_web_page()

    async def intercept_a_web_page(self):
        # 当验证码出来后,截取整个网页以及验证码
        # 等待验证码出来
        time.sleep(3)
        # 截取整个网页
        await self.page.screenshot({'path': self.BIG_PATH})
        # 获取验证码图片坐标
        await self.get_xpath_element()

    async def get_xpath_element(self):
        # 获取验证码的element元素
        el = await self.page.xpath("//div[starts-with(@style,'background-image: url')]")
        self.zb = await el[0].boundingBox()

        # 裁剪验证码图片
        await self.image_shot()

    async def image_shot(self):
        # 截取一部分图片
        left = int(self.zb['x'])
        upper = int(self.zb['y'])
        right = int(self.zb['x']) + int(self.zb['width'])
        lower = int(self.zb['y']) + int(self.zb['height'])

        # 打开一个文件
        img = Image.open(self.BIG_PATH)
        # 切图片
        img_obj = img.crop((left, upper, right, lower))
        # 保存图片
        img_obj.save(self.SMALL_PATH)

        # 使用接口,获得验证码坐标
        coordinate = await self.base64_api()
        # 按顺序点击验证码并点击确定
        await self.image_click(coordinate)

    async def image_click(self, coordinate):
        result_list = coordinate['data']['result'].split('|')
        # 操作鼠标点击指定坐标
        for itme in result_list:
            x = itme.split(',')[0]
            y = itme.split(',')[1]
            await self.page.mouse.click(int(self.zb['x']) + int(x), int(self.zb['y']) + int(y), {'delay': 500})
        el = await self.page.xpath("//div[starts-with(@class,'geetest_submit_')]")
        await el[0].click()

    async def base64_api(self, typeid=27):
        with open(self.SMALL_PATH, 'rb') as f:
            base64_data = base64.b64encode(f.read())
            b64 = base64_data.decode()
        data = {"username": 'sb9728',
                "password": 'sb9728565',
                "typeid": typeid,
                "image": b64
                }
        reps = requests.post("https://api.ttshitu.com/predict", json=data)
        if reps.status_code == 200:
            result = reps.json()
            return result
        else:
            return {'code': '-1'}

    async def click_on_the_welfare_society(self):
        el = await self.page.xpath("//li[@index='9']")
        await el[0].click()
        time.sleep(10)


async def main():
    '''
    1.打开网页
    2.输入账号、密码
    3.点击登录按钮
    4.截图
    5.获取验证码图片的坐标
    6.裁剪验证码图片
    7.使用接口,获得验证码坐标
    8.按顺序点击验证码
    9.点击确定
    '''
    username = '你猜猜~'
    password = '你猜猜~'
    auto = auto_login(username, password)
    # 打开网页
    await auto.open_the_webpage()


if __name__ == '__main__':
    x = asyncio.ensure_future(main())
    asyncio.get_event_loop().run_until_complete(x)

注意点

  1. 这个自动登录,由于我刚接触 Python 爬虫的时候,是教的 pypeteer,所以是用的 pypeteer,同样的操作用 selenium 也是可以的,思路是一样的。
  2. pypeteer好像因为是异步的原因,导致不能在主函数处把每一步一个一个列出来,会导致同时进行而出现错误。
    目前我就是用递推的方式,在每一个函数的最后调用了下一步函数。
    不过这样总归是看着不够整洁,如果有大佬知道怎么解决这个问题的话,可以评论或私信。
posted @ 2023-02-08 15:25  淦丘比  阅读(817)  评论(0)    收藏  举报