基本的流程:
1. 打开前端网,点击登录。
2. 填写账号,密码。
3. 点解验证按钮,通过滑动验证,最后成功登陆。
代码实现:
github上可以checkout。
具体代码如下所示:
run.js
const puppeteer = require('puppeteer');
const devices = require('puppeteer/DeviceDescriptors');
const iPhone = devices['iPhone 6 Plus'];
let timeout = function (delay) {
return new Promise((resolve, reject) => {
setTimeout(() => {
try {
resolve(1)
} catch (e) {
reject(0)
}
}, delay);
})
}
let page = null
let btn_position = null
let times = 0 // 执行重新滑动的次数
const distanceError = [-10,2,3,5] // 距离误差
async function run() {
const browser = await puppeteer.launch({
headless:false //这里我设置成false主要是为了让大家看到效果,设置为true就不会打开浏览器
});
page = await browser.newPage();
// 1.打开前端网
await page.emulate(iPhone);
await page.goto('https://www.qdfuns.com/');
await timeout(1000);
// 2.打开登录页面
page.click('a[data-type=login]')
await timeout(1000);
// 3.输入账号密码
page.type('input[data-type=email]','你的账号')
await timeout(500);
page.type('input[placeholder=密码]','你的密码')
await timeout(1000);
// 4.点击验证
page.click('.geetest_radar_tip')
await timeout(1000);
btn_position = await getBtnPosition();
// 5.滑动
drag(null)
}
/**
* 计算按钮需要滑动的距离
* */
async function calculateDistance() {
const distance = await page.evaluate(() => {
// 比较像素,找到缺口的大概位置
function compare(document) {
const ctx1 = document.querySelector('.geetest_canvas_fullbg'); // 完成图片
const ctx2 = document.querySelector('.geetest_canvas_bg'); // 带缺口图片
const pixelDifference = 30; // 像素差
let res = []; // 保存像素差较大的x坐标
// 对比像素
for(let i=57;i<260;i++){
for(let j=1;j<160;j++) {
const imgData1 = ctx1.getContext("2d").getImageData(1*i,1*j,1,1)
const imgData2 = ctx2.getContext("2d").getImageData(1*i,1*j,1,1)
const data1 = imgData1.data;
const data2 = imgData2.data;
const res1=Math.abs(data1[0]-data2[0]);
const res2=Math.abs(data1[1]-data2[1]);
const res3=Math.abs(data1[2]-data2[2]);
if(!(res1 < pixelDifference && res2 < pixelDifference && res3 < pixelDifference)) {
if(!res.includes(i)) {
res.push(i);
}
}
}
}
// 返回像素差最大值跟最小值,经过调试最小值往左小7像素,最大值往左54像素
return {min:res[0]-7,max:res[res.length-1]-54}
}
return compare(document)
})
return distance;
}
/**
* 计算滑块位置
*/
async function getBtnPosition() {
const btn_position = await page.evaluate(() => {
const {clientWidth,clientHeight} = document.querySelector('.geetest_popup_ghost')
return {btn_left:clientWidth/2-104,btn_top:clientHeight/2+59}
})
return btn_position;
}
/**
* 尝试滑动按钮
* @param distance 滑动距离
* */
async function tryValidation(distance) {
//将距离拆分成两段,模拟正常人的行为
const distance1 = distance - 10
const distance2 = 10
page.mouse.click(btn_position.btn_left,btn_position.btn_top,{delay:2000})
page.mouse.down(btn_position.btn_left,btn_position.btn_top)
page.mouse.move(btn_position.btn_left+distance1,btn_position.btn_top,{steps:30})
await timeout(800);
page.mouse.move(btn_position.btn_left+distance1+distance2,btn_position.btn_top,{steps:20})
await timeout(800);
page.mouse.up()
await timeout(4000);
// 判断是否验证成功
const isSuccess = await page.evaluate(() => {
return document.querySelector('.geetest_success_radar_tip_content') && document.querySelector('.geetest_success_radar_tip_content').innerHTML
})
await timeout(1000);
// 判断是否需要重新计算距离
const reDistance = await page.evaluate(() => {
return document.querySelector('.geetest_result_content') && document.querySelector('.geetest_result_content').innerHTML
})
await timeout(1000);
return {isSuccess:isSuccess==='验证成功',reDistance:reDistance.includes('怪物吃了拼图')}
}
/**
* 拖动滑块
* @param distance 滑动距离
* */
async function drag(distance) {
distance = distance || await calculateDistance();
const result = await tryValidation(distance.min)
if(result.isSuccess) {
await timeout(1000);
//登录
console.log('验证成功')
page.click('#modal-member-login button')
}else if(result.reDistance) {
console.log('重新计算滑距离录,重新滑动')
times = 0
await drag(null)
} else {
if(distanceError[times]){
times ++
console.log('重新滑动')
await drag({min:distance.max,max:distance.max+distanceError[times]})
} else {
console.log('滑动失败')
times = 0
run()
}
}
}
run()
package.json
{
"name": "demo",
"version": "1.0.0",
"dependencies": {
"puppeteer": "^1.0.0"
}
}
运行
1. 将这个两个文件保存到文件夹下面,终端切换到当前路径下
2. npm i
3. 补上前端网的账号,密码
4. node run
演示
下图演示可以分为四步:
1. 打开登陆页面,输入事先写好的账号密码。
2. 第一次拖动滑块提示“被怪兽吃了”,所以重新计算了新的图片的缺口距离。
3. 第二,三次拖动提示“没正确合拼”,所以重新拖动。
4. 验证成功,登录。
(请将鼠标放到gif上查看演示效果,或者请拖到新窗口打开gif)
说明
1. 滑动验证有三个canvas,其中只需要 classname为‘geetest_canvas_fullbg'以及‘geetest_canvas_bg'的进行像素差对比。ps:前者是完整图片,后者是带缺口的图片。
2. 每个带缺口的图片都有一块误导的阴影,所以对比像素差的时候,计算出的距离分别是误导阴影以及缺口的。因此,滑动距离的取值,我取‘{min:res[0]-7,max:res[res.length-1]-54}'。当缺口比误导阴影靠左时, min(距离最小值) 值就是滑动距离,否则就是 max(距离最大值)减去滑块宽度 。
3. 滑动结果分三种情况:验证成功,被吃了,失败。 “被吃了” 会重新请求图片,所以重新计算了距离再滑动; “失败” 则重新滑动,如果执行 4 次依然失败,则重新run整个流程。
总结
以上所述是小编给大家介绍的使用puppeteer破解极验的滑动验证码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]


