>  기사  >  웹 프론트엔드  >  Puppeteer를 사용하여 슬라이딩 인증 코드를 해독하는 방법

Puppeteer를 사용하여 슬라이딩 인증 코드를 해독하는 방법

小云云
小云云원래의
2018-02-26 09:28:526528검색

이 글은 주로 인형극을 사용하여 극한의 테스트를 통과하는 슬라이딩 검증 기능을 소개합니다. 필요한 친구들이 참고하면 좋겠습니다.

기본 프로세스:

1. 프런트 엔드 네트워크를 열고 클릭하여 로그인합니다.

2.계좌번호와 비밀번호를 입력하세요.

3. 인증 버튼을 클릭하고 슬라이딩으로 인증한 후 최종 로그인에 성공합니다.

코드 구현:

github에서 결제할 수 있습니다.

구체적인 코드는 다음과 같습니다.

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"
 }
}

Run

1. 이 두 파일을 폴더에 저장하고 터미널을 현재 경로로 전환합니다

2. -네트워크 계정 및 비밀번호 종료

4. 노드 실행

데모

아래 그림의 데모는 4단계로 나눌 수 있습니다.

1. 로그인 페이지를 열고 미리 작성된 계정 비밀번호를 입력하세요.

2. 처음으로 슬라이더를 드래그하면 "괴물에게 먹혔습니다"라는 메시지가 표시되므로 새 사진의 간격이 다시 계산됩니다.

3. 둘째, 세 번째 드래그하면 "잘못 결합되었습니다"라는 메시지가 나오므로 다시 드래그하세요.

4. 인증이 완료되었습니다. 로그인하세요.

(시연 효과를 보려면 gif 위에 마우스를 올려 놓거나, gif를 열려면 새 창으로 드래그하세요.)

Instructions

1. 클래스 이름은 'geetest_canvas_fullbg' 및 'geetest_canvas_bg'입니다. '픽셀 차이 비교를 수행합니다. ps: 전자는 완전한 그림이고, 후자는 노치 그림입니다.

2. 노치가 있는 모든 사진에는 오해의 소지가 있는 그림자가 있으므로 픽셀 차이를 비교할 때 계산된 거리는 각각 오해의 소지가 있는 그림자와 노치입니다. 따라서 슬라이딩 거리 값은 '{min:res[0]-7,max:res[res.length-1]-54}'를 사용합니다. 노치가 오해의 소지가 있는 그림자보다 더 왼쪽에 있는 경우 최소(최소 거리) 값은 슬라이딩 거리이고, 그렇지 않은 경우 최대(최대 거리)에서 슬라이더 너비를 뺀 값입니다.

3. 슬라이딩 결과는 검증 성공, 먹음, 실패 세 가지 상황으로 구분됩니다. "Eat"는 이미지를 다시 요청하므로 슬라이딩하기 전에 거리가 다시 계산됩니다. "Failed"는 4번 실행한 후에도 계속 실패하면 전체 프로세스가 다시 실행됩니다.

관련 권장 사항:


js 플러그인을 사용하여 이미지 슬라이딩 인증 코드 예시 공유 구현

위 내용은 Puppeteer를 사용하여 슬라이딩 인증 코드를 해독하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.