Previous articleWrite a simple introduction to puppeteer, out of curiosity to think a question, puppeteer can break captcha?? So, just take the front-end net to try (purely out of learning)

Basic process:

1. Open the front-end network and click Login.

2. Enter the account and password.

3. Click the verification button, slide through the verification, and finally log in successfully.

Code implementation:

githubYou can 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((a)= > {   
                  try {
                      resolve(1)}catch (e) {
                      reject(0) } }, delay); })}let page = null
 let btn_position = null
 let times = 0 // The number of times to reroute
 const distanceError = [- 10.2.3.5] // Distance error

 async function run() {
  const browser = await puppeteer.launch({
      headless:false // I set it to false so that you can see the effect. Setting it to true will not open the browser
  });
  page = await browser.newPage();

  // 1. Open the front-end network
  await page.emulate(iPhone);
  await page.goto('https://www.qdfuns.com/');
  await timeout(1000);
  
  // 2. Go to the login page
  page.click('a[data-type=login]')
  await timeout(1000);

  // 3. Enter the account password
  page.type('input[data-type=email]'.'Your account number')
  await timeout(500);
  page.type('input [placeholder = password]'.'Your password')
  await timeout(1000);
  
  // 4. Click Verify
  page.click('.geetest_radar_tip')
  await timeout(1000);

  btn_position = await getBtnPosition();

  / / 5. Sliding
  drag(null)}/** * Calculates the distance the button needs to slide ** / 
 async function calculateDistance() {
  const distance = await page.evaluate((a)= > {

    // Compare pixels to find the approximate position of the gap
    function compare(document) {
      const ctx1 = document.querySelector('.geetest_canvas_fullbg'); // Finish the picture
      const ctx2 = document.querySelector('.geetest_canvas_bg');  // The image with the gap
      const pixelDifference = 30; / / pixel
      let res = []; // Save the x coordinate with a large pixel difference

      // Compare pixels
      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); }}}}// Return the maximum and minimum values of the pixel difference. The minimum value is 7 pixels smaller to the left, and the maximum value is 54 pixels to the left
      return {min:res[0]7 -.max:res[res.length- 1]- 54}}return compare(document)})return distance;
 }

 /** * Calculate the slider position */
 async function getBtnPosition() {
  const btn_position = await page.evaluate((a)= > {
    const {clientWidth,clientHeight} = document.querySelector('.geetest_popup_ghost')
    return {btn_left:clientWidth/2- 104..btn_top:clientHeight/2+59}})return btn_position;
 }

 /** * Try sliding the button * @param distance ** /  
 async function tryValidation(distance) {
  // Divide the distance into two sections to simulate the behavior of a normal person
  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);
  
  // Check whether the validation is successful
  const isSuccess = await page.evaluate((a)= > {
    return document.querySelector('.geetest_success_radar_tip_content') && document.querySelector('.geetest_success_radar_tip_content').innerHTML
  })
  await timeout(1000);
  // Determine whether to recalculate the distance
  const reDistance = await page.evaluate((a)= > {
    return document.querySelector('.geetest_result_content') && document.querySelector('.geetest_result_content').innerHTML
  })
  await timeout(1000);
  return {isSuccess:isSuccess==='Validation successful'.reDistance:reDistance.includes('The monster ate the puzzle')}}/**
  * 拖动滑块
  * @param distance 滑动距离
  * */ 
 async function drag(distance) {
  distance = distance || await calculateDistance();
  const result = await tryValidation(distance.min)
  if(result.isSuccess) {
    await timeout(1000);
    / / login
    console.log('Validation successful')
    page.click('#modal-member-login button')}else if(result.reDistance) {
    console.log('Recalculate slide distance record, recalculate slide')
    times = 0
    await drag(null)}else {
    if(distanceError[times]){
      times ++
      console.log('Reslide')
      await drag({min:distance.max,max:distance.max+distanceError[times]})
    } else {
      console.log('Slide failed')
      times = 0
      run()
    }
  }
 }

 run()


Copy the code

package.json

{
  "name": "demo"."version": "1.0.0"."dependencies": {
    "puppeteer": "^ 1.0.0"}}Copy the code

run

1. Save the two files to a folder and switch to the current path

2. npm i

3. Add the account and password of the front-end network

4. node run

demo

The following illustration can be divided into four steps:

1. Open the login page and enter the pre-written inputThe account password

2. Drag the slider for the first time”Eaten by a monster“, so recalculate the gap distance for the new image.

3. Second and third drag the prompt“Not correctly co-spelled”, so drag again.

4. The verification is successful.The login.

(Please place your mouse over the GIF to see the demo, or please drag to a new window to open the GIF)

instructions

1. Swipe validation has three canvas, which only needs classname to be‘geetest_canvas_fullbg’As well as‘geetest_canvas_bg’For pixel difference comparison.ps:The former is the complete image, the latter is the image with the gap.

2. Each chipped image has oneShadow of misdirection, so when comparing the difference between pixels, the calculated distance is respectivelyMislead the shadowAs well asgap. Therefore, for the sliding distance, I take ‘{min:res[0]-7, Max :res[res.length-1]-54}’. When the gap is to the left of the misleading shadow,Min (minimum distance)The value is the sliding distance, otherwise it isMax (maximum distance) minus slider width.

3. Sliding results are divided into three cases:Authentication is successful.Be ate.failure.“Being eaten”Will re-request the image, so recalculate the distance and then slide;“Failure”Then reslide, if executed4Times still fail, then againrunThe whole process.

The whole process is roughly like this, interested friends can communicate