使用puppeteer破解極驗(yàn)的滑動(dòng)驗(yàn)證碼
基本的流程:
1. 打開前端網(wǎng),點(diǎn)擊登錄。
2. 填寫賬號(hào),密碼。
3. 點(diǎn)解驗(yàn)證按鈕,通過滑動(dòng)驗(yàn)證,最后成功登陸。
代碼實(shí)現(xiàn):
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 // 執(zhí)行重新滑動(dòng)的次數(shù) const distanceError = [-10,2,3,5] // 距離誤差 async function run() { const browser = await puppeteer.launch({ headless:false //這里我設(shè)置成false主要是為了讓大家看到效果,設(shè)置為true就不會(huì)打開瀏覽器 }); page = await browser.newPage(); // 1.打開前端網(wǎng) 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.輸入賬號(hào)密碼 page.type('input[data-type=email]','你的賬號(hào)') await timeout(500); page.type('input[placeholder=密碼]','你的密碼') await timeout(1000); // 4.點(diǎn)擊驗(yàn)證 page.click('.geetest_radar_tip') await timeout(1000); btn_position = await getBtnPosition(); // 5.滑動(dòng) drag(null) } /** * 計(jì)算按鈕需要滑動(dòng)的距離 * */ 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坐標(biāo) // 對(duì)比像素 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); } } } } // 返回像素差最大值跟最小值,經(jīng)過調(diào)試最小值往左小7像素,最大值往左54像素 return {min:res[0]-7,max:res[res.length-1]-54} } return compare(document) }) return distance; } /** * 計(jì)算滑塊位置 */ 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; } /** * 嘗試滑動(dòng)按鈕 * @param distance 滑動(dòng)距離 * */ 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); // 判斷是否驗(yàn)證成功 const isSuccess = await page.evaluate(() => { return document.querySelector('.geetest_success_radar_tip_content') && document.querySelector('.geetest_success_radar_tip_content').innerHTML }) await timeout(1000); // 判斷是否需要重新計(jì)算距離 const reDistance = await page.evaluate(() => { return document.querySelector('.geetest_result_content') && document.querySelector('.geetest_result_content').innerHTML }) await timeout(1000); return {isSuccess:isSuccess==='驗(yàn)證成功',reDistance:reDistance.includes('怪物吃了拼圖')} } /** * 拖動(dòng)滑塊 * @param distance 滑動(dòng)距離 * */ async function drag(distance) { distance = distance || await calculateDistance(); const result = await tryValidation(distance.min) if(result.isSuccess) { await timeout(1000); //登錄 console.log('驗(yàn)證成功') page.click('#modal-member-login button') }else if(result.reDistance) { console.log('重新計(jì)算滑距離錄,重新滑動(dòng)') times = 0 await drag(null) } else { if(distanceError[times]){ times ++ console.log('重新滑動(dòng)') await drag({min:distance.max,max:distance.max+distanceError[times]}) } else { console.log('滑動(dòng)失敗') times = 0 run() } } } run() package.json { "name": "demo", "version": "1.0.0", "dependencies": { "puppeteer": "^1.0.0" } }
運(yùn)行
1. 將這個(gè)兩個(gè)文件保存到文件夾下面,終端切換到當(dāng)前路徑下
2. npm i
3. 補(bǔ)上前端網(wǎng)的賬號(hào),密碼
4. node run
演示
下圖演示可以分為四步:
1. 打開登陸頁面,輸入事先寫好的賬號(hào)密碼。
2. 第一次拖動(dòng)滑塊提示“被怪獸吃了”,所以重新計(jì)算了新的圖片的缺口距離。
3. 第二,三次拖動(dòng)提示“沒正確合拼”,所以重新拖動(dòng)。
4. 驗(yàn)證成功,登錄。
(請(qǐng)將鼠標(biāo)放到gif上查看演示效果,或者請(qǐng)拖到新窗口打開gif)
說明
1. 滑動(dòng)驗(yàn)證有三個(gè)canvas,其中只需要 classname為‘geetest_canvas_fullbg'以及‘geetest_canvas_bg'的進(jìn)行像素差對(duì)比。ps:前者是完整圖片,后者是帶缺口的圖片。
2. 每個(gè)帶缺口的圖片都有一塊誤導(dǎo)的陰影,所以對(duì)比像素差的時(shí)候,計(jì)算出的距離分別是誤導(dǎo)陰影以及缺口的。因此,滑動(dòng)距離的取值,我取‘{min:res[0]-7,max:res[res.length-1]-54}'。當(dāng)缺口比誤導(dǎo)陰影靠左時(shí), min(距離最小值) 值就是滑動(dòng)距離,否則就是 max(距離最大值)減去滑塊寬度 。
3. 滑動(dòng)結(jié)果分三種情況:驗(yàn)證成功,被吃了,失敗。 “被吃了” 會(huì)重新請(qǐng)求圖片,所以重新計(jì)算了距離再滑動(dòng); “失敗” 則重新滑動(dòng),如果執(zhí)行 4 次依然失敗,則重新run整個(gè)流程。
總結(jié)
以上所述是小編給大家介紹的使用puppeteer破解極驗(yàn)的滑動(dòng)驗(yàn)證碼,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
使用node.js對(duì)音視頻文件加密的實(shí)例代碼
本文通過實(shí)例代碼給大家介紹了使用node.js對(duì)音視頻文件加密的方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的的朋友參考下吧2017-08-08nodejs 全局變量和全局對(duì)象知識(shí)點(diǎn)及用法詳解
在本篇文章里小編給大家整理的是一篇關(guān)于nodejs 全局變量和全局對(duì)象知識(shí)點(diǎn)及用法等內(nèi)容,對(duì)此有興趣的朋友們可以學(xué)習(xí)參考下。2021-12-12如何在node.js中使用?JsonWebToken模塊進(jìn)行token加密
目前在web框架中最流行的身份驗(yàn)證是使用jsonwebtoken,簡稱jwt.可以設(shè)置加密方式,過期時(shí)間,存放個(gè)人信息,逆解析,下面這篇文章主要給大家介紹了關(guān)于如何在node.js中使用?JsonWebToken模塊進(jìn)行token加密的相關(guān)資料,需要的朋友可以參考下2023-03-03Nodejs基于LRU算法實(shí)現(xiàn)的緩存處理操作示例
這篇文章主要介紹了Nodejs基于LRU算法實(shí)現(xiàn)的緩存處理操作,結(jié)合具體實(shí)例形式分析了LRU算法的原理、功能以及nodejs使用LRU算法實(shí)現(xiàn)緩存處理操作的相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-03-03node.js中的http.response.write方法使用說明
這篇文章主要介紹了node.js中的http.response.write方法使用說明,本文介紹了http.response.write的方法說明、語法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下2014-12-12Node.js安裝、環(huán)境變量配置、報(bào)錯(cuò)解決方法
Node.js 是一個(gè)基于 Chrome JavaScript 運(yùn)行時(shí)建立的一個(gè)平臺(tái),這篇文章主要介紹了Node.js安裝、環(huán)境變量配置、報(bào)錯(cuò)解決方法,需要的朋友可以參考下2022-06-06node+axios實(shí)現(xiàn)下載外網(wǎng)文件到本地
這篇文章主要為大家介紹了node+axios實(shí)現(xiàn)下載外網(wǎng)文件到本地示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06