提示:这里提供 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处理坐标然后点击
版权归原作者 官麒 所有, 如有侵权,请联系我们删除。