0


Python + selenium 解决验证码问题思路(超详细)

提示:这里提供 selenium 破解验证码的思路,使用打码平台从而破解验证码

一、第一步剖析平台验证码类型

这里我用唯品会做案例,我们先分析登录接口有没有 frame页面。

通过元素定位发现 body标签下都没有frame,这样子可以判定直接可以定位网站登录的元素,不用切换到frame子页面。

二、编写selenium代码

1.引入库 所需要的模块

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import requests
import time
from PIL import Image
from selenium.webdriver.common.action_chains import ActionChains
from yun import base64_api

2. 定义一个初始属性

class Get_url(object):
    def __init__(self):
        # 初始化谷歌驱动
        self.driver = webdriver.Chrome()
        self.url = 'https://passport.vip.com/login?src=https%3A%2F%2Forder.vip.com%2Forder%2Forderlist'

3.找到账户登录的元素然后点击

我这边使用xpath定位,找到账户登录的元素然后使用selemiun点击

4.短信验证登录

找到短信验证登录的元素然后使用selemiun点击


5.找到手机号输入框

使用xpath定位元素

6.输入手机号之后会有这样类型的验证码

现在的思路是要找到图片的url地址

7.找到验证码1图片的url地址

8.找到验证码2图片的url地址

9. 现在可以按照思路编写代码了

因为程序运行的太快所以要让程序休眠2秒钟,这个方法的目的就是获取验证码1,验证码2的url地址

    def run(self):
        img_url = []
        # 访问wph url
        self.driver.get(self.url)
        # 找到账户登录 然后模拟点击
        self.driver.find_element(By.XPATH, '/html/body/div[2]/div/div[1]/div[1]/div/div[1]/div[2]').click()
        time.sleep(2)

        # 点击短信验证
        self.driver.find_element(By.XPATH, '//*[@id="J_login_form"]/div[5]/div/div/div[1]/a').click()
        time.sleep(2)

        # 输入手机号
        self.driver.find_element(By.XPATH, '//*[@id="J_mobile_login_phone"]').send_keys(输入自己的手机号)
        time.sleep(3)

        # 获取验证码图片1 url
        aa = self.driver.find_element(By.XPATH, '//div[@class="c-tab-content"]/div[2]/div[2]/div/div[3]/div/div/div/div/div/div/img').get_attribute('src')
        # 把url添加到列表
        img_url.append(aa)
        time.sleep(1)
        # 获取验证码图片2
        bb = self.driver.find_element(By.XPATH, '//div[@class="vipsc_code_pop vipsc_d_hide"]/div/img').get_attribute('src')
        # 把图片二添加到列表
        img_url.append(bb)
        # 返回列表
        return img_url

10.获取到两张验证码的url 下载它们

    # requests 下载两张图片
    def get_conten(self, img_url):
        # 用 enumerate函数遍历 index返回url_deta坐标
        for index, url_date in enumerate(img_url):
            # 下载图片 图片以下标命名 保存到本目录下
            res = requests.get(url_date).content
            with open(f'{index}.jpg', mode='wb') as f:
                f.write(res)
                print('写入完成')

11.合成两张图片为一张图片

因为后面要上传验证码到打码平台,所以要把条件验证码 和 验证码 合成一张图片

    # 合成两张照片
    def blend_two_images2(self):
        # 打开需要点击的验证码图片
        img1 = Image.open("1.jpg")

        img1 = img1.convert('RGBA')

        # 打开条件的验证码图片
        img2 = Image.open("0.jpg")

        img2 = img2.convert('RGBA')

        r, g, b, alpha = img2.split()

        alpha = alpha.point(lambda i: i > 0 and 204)

        img = Image.composite(img2, img1, alpha)

        img.show()
        # 保存合成后的图片并命名为wph.png
        img.save("wph.png")

        return

12.合成图片之后就变成了

把条件验证码合成到了里面

13.接入打码平台 然后把合成好的图片上传到接口

上传之后接口会返回 11|21,31|41,51|61 这样的坐标我们需要处理一下数据

    def obtain_xy(self):
        # 云打码 解析图片路径  (获取图片之后提交给打码平台)
        img_path = 'wph.png'
        # 写入平台的账户名 密码 然后传入照片 选择验证码类型
        rrr = base64_api(uname=(输入平台的用户名), pwd=(输入平台的密码), img=img_path, typeid=20)
        # 接收平台返回的信息 然后分割处理成自己想要的信息格式 ['11,21','31,41','51,61']的格式
        xydate = rrr.split('|')

        list_xy = []
        # 循坏遍历数据 然后放到列表
        for i in xydate:
            list_xy.append(i)
        # 传入参数到click方法
        # res.click(list_xy)
        return list_xy

14.处理好坐标数据之后就模拟人的操作来点击验证码

    #  定位验证码图片位置
    def run_tow(self):
        element = self.driver.find_element(By.XPATH, '//div[@class="ui-form-item-group"]/div/div/div/div/div/img')
        # 把鼠标悬停到该元素 验证码2才会出来
        ActionChains(self.driver).move_to_element(element).perform()

    # 解析坐标列表 ['1,2','3,4','5,6']的格式分析
    def click(self, i):
        # 这是'1,2'坐标格式
        xy1 = i[0].split(',')
        # 这是'3,4'
        xy2 = i[1].split(',')
        # '5,6'
        xy3 = i[2].split(',')

        # 定位验证码2的元素
        click1 = self.driver.find_element(By.XPATH, '//div[@class="ui-form-item-group"]/div/div/div/div[2]/div/img')
        # 使用动作链完成验证码点击坐标1 并让程序延迟1秒执行
        ActionChains(self.driver).move_to_element_with_offset(click1, xy1[0], xy1[1]).click().perform()
        time.sleep(1)
        # 使用动作链完成验证码点击坐标2 并让程序延迟1秒执行
        ActionChains(self.driver).move_to_element_with_offset(click1, xy2[0], xy2[1]).click().perform()
        time.sleep(1)
        # 使用动作链完成验证码点击坐标3 并让程序延迟1秒执行
        ActionChains(self.driver).move_to_element_with_offset(click1, xy3[0], xy3[1]).click().perform()
        time.sleep(1)
        # 点击获取验证码
        self.driver.find_element(By.XPATH, '//div[@class="sms-component-wrap"]/div/div/div/div/div/a').click()
        # 点击登录
        self.driver.find_element(By.XPATH, '//*[@id="J_mobile_login_submit"]').click()

15. from yun import base64_api 是打码平台的文件

读者可以找打码平台的文件下来,作者这边用的是云打码平台

以下是云打码文件的内容

import base64
import json
import requests
# 一、图片文字类型(默认 3 数英混合):
# 1 : 纯数字
# 1001:纯数字2
# 2 : 纯英文
# 1002:纯英文2
# 3 : 数英混合
# 1003:数英混合2
#  4 : 闪动GIF
# 7 : 无感学习(独家)
# 11 : 计算题
# 1005:  快速计算题
# 16 : 汉字
# 32 : 通用文字识别(证件、单据)
# 66:  问答题
# 49 :recaptcha图片识别
# 二、图片旋转角度类型:
# 29 :  旋转类型
#
# 三、图片坐标点选类型:
# 19 :  1个坐标
# 20 :  3个坐标
# 21 :  3 ~ 5个坐标
# 22 :  5 ~ 8个坐标
# 27 :  1 ~ 4个坐标
# 48 : 轨迹类型
#
# 四、缺口识别
# 18 : 缺口识别(需要2张图 一张目标图一张缺口图)
# 33 : 单缺口识别(返回X轴坐标 只需要1张图)
# 五、拼图识别
# 53:拼图识别
def base64_api(uname, pwd, img, typeid):
    with open(img, 'rb') as f:
        base64_data = base64.b64encode(f.read())
        b64 = base64_data.decode()
    data = {"username": uname, "password": pwd, "typeid": typeid, "image": b64}
    result = json.loads(requests.post("http://api.ttshitu.com/predict", json=data).text)
    if result['success']:
        return result["data"]["result"]
    else:
        return result["message"]
    return

if __name__ == "__main__":
    img_path = 'wph.png'
    result = base64_api(uname='nameguan', pwd='1111', img=img_path, typeid=27)
    print(result)

三 总结:下面是全部代码

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import requests
import time
from PIL import Image
from selenium.webdriver.common.action_chains import ActionChains
from yun import base64_api

"""
思路: 1找到能发验证码url网址然后 selenium自动化点击手机验证

"""

class Get_url(object):
    def __init__(self):
        # 初始化谷歌驱动
        self.driver = webdriver.Chrome()
        self.url = 'https://passport.vip.com/login?src=https%3A%2F%2Forder.vip.com%2Forder%2Forderlist'

    # 输入手机号
    def run(self):
        img_url = []
        # 访问wph url
        self.driver.get(self.url)
        self.driver.maximize_window()
        # 找到账户登录 然后点击
        self.driver.find_element(By.XPATH, '/html/body/div[2]/div/div[1]/div[1]/div/div[1]/div[2]').click()
        time.sleep(2)

        # 点击短信验证
        self.driver.find_element(By.XPATH, '//*[@id="J_login_form"]/div[5]/div/div/div[1]/a').click()
        time.sleep(2)

        # 输入手机号
        self.driver.find_element(By.XPATH, '//*[@id="J_mobile_login_phone"]').send_keys('110')
        time.sleep(3)

        # 获取验证码图片1 url
        aa = self.driver.find_element(By.XPATH, '//div[@class="c-tab-content"]/div[2]/div[2]/div/div[3]/div/div/div/div/div/div/img').get_attribute('src')
        # 把url添加到列表
        img_url.append(aa)
        time.sleep(1)
        # 获取验证码图片2
        bb = self.driver.find_element(By.XPATH, '//div[@class="vipsc_code_pop vipsc_d_hide"]/div/img').get_attribute('src')
        # 把图片二添加到列表
        img_url.append(bb)
        # 返回列表
        return img_url

    # requests 下载两张图片
    def get_conten(self, img_url):
        # 用 enumerate函数遍历 index返回url_deta坐标
        for index, url_date in enumerate(img_url):
            # 下载图片 图片以下标命名 保存到本目录下
            res = requests.get(url_date).content
            with open(f'{index}.jpg', mode='wb') as f:
                f.write(res)
                print('写入完成')

    # 合成两张照片
    def blend_two_images2(self):
        # 打开需要点击的验证码图片
        img1 = Image.open("1.jpg")

        img1 = img1.convert('RGBA')

        # 打开条件的验证码图片
        img2 = Image.open("0.jpg")

        img2 = img2.convert('RGBA')

        r, g, b, alpha = img2.split()

        alpha = alpha.point(lambda i: i > 0 and 204)

        img = Image.composite(img2, img1, alpha)

        img.show()
        # 保存合成后的图片并命名为wph.png
        img.save("wph.png")

        return

    def obtain_xy(self):
        # 云打码 解析图片路径  (获取图片之后提交给打码平台)
        img_path = 'wph.png'
        # 写入平台的账户名 密码 然后传入照片 选择验证码类型
        rrr = base64_api(uname='nameguan', pwd='11111', img=img_path, typeid=20)
        # 接收平台返回的信息 然后分割处理成自己想要的信息格式 ['11,21','31,41','51,61']的格式
        xydate = rrr.split('|')

        list_xy = []
        # 循坏遍历数据 然后放到列表
        for i in xydate:
            list_xy.append(i)
        # 传入参数到click方法
        # res.click(list_xy)
        return list_xy

    #  定位验证码图片位置
    def run_tow(self):
        element = self.driver.find_element(By.XPATH, '//div[@class="ui-form-item-group"]/div/div/div/div/div/img')
        # 把鼠标悬停到该元素 验证码2才会出来
        ActionChains(self.driver).move_to_element(element).perform()

    # 解析坐标列表 ['1,2','3,4','5,6']的格式分析
    def click(self, i):
        # 这是'1,2'坐标格式
        xy1 = i[0].split(',')
        # 这是'3,4'
        xy2 = i[1].split(',')
        # '5,6'
        xy3 = i[2].split(',')

        # 定位验证码2的元素
        click1 = self.driver.find_element(By.XPATH, '//div[@class="ui-form-item-group"]/div/div/div/div[2]/div/img')
        # 使用动作链完成验证码点击坐标1 并让程序延迟1秒执行
        ActionChains(self.driver).move_to_element_with_offset(click1, xy1[0], xy1[1]).click().perform()
        time.sleep(1)
        # 使用动作链完成验证码点击坐标2 并让程序延迟1秒执行
        ActionChains(self.driver).move_to_element_with_offset(click1, xy2[0], xy2[1]).click().perform()
        time.sleep(1)
        # 使用动作链完成验证码点击坐标3 并让程序延迟1秒执行
        ActionChains(self.driver).move_to_element_with_offset(click1, xy3[0], xy3[1]).click().perform()
        time.sleep(1)
        # 点击获取验证码
        self.driver.find_element(By.XPATH, '//div[@class="sms-component-wrap"]/div/div/div/div/div/a').click()
        # 点击登录
        self.driver.find_element(By.XPATH, '//*[@id="J_mobile_login_submit"]').click()

if __name__ == '__main__':
    res = Get_url()
    img_url = res.run()
    # 把img传入
    res.get_conten(img_url)
    res.blend_two_images2()

    i = res.obtain_xy()
    # 把i传入
    res.run_tow()
    res.click(i)
提示:这里对文章进行总结:

以上的思路总结是:

需要找到平台的验证码然后下载处理后上传至打码平台,然后打码平台返回坐标,之后就用selenium处理坐标然后点击


本文转载自: https://blog.csdn.net/weixin_56309364/article/details/124917958
版权归原作者 官麒 所有, 如有侵权,请联系我们删除。

“Python + selenium 解决验证码问题思路(超详细)”的评论:

还没有评论