Comment résoudre les curseurs captcha de GeeTest en utilisant JS

Mon précédent article sur ce sujet est

"Comment contourner les curseurs Captcha à l'aide de JS et Puppeteer"



Dans cet article, je vais aller plus loin et résoudre le captcha-slider d'une autre manière. Cette méthode résout le curseur captcha plus rapidement et plus efficacement. L'accent sera mis sur le curseur captcha GeeTest, mais vous pouvez également l'appliquer à n'importe quel autre curseur captcha. Je vais vous montrer comment le contourner en quelques étapes.



image



1. Acquisition d'images



GeeTest. Puppeteer , . , .



const puppeteer = require('puppeteer')
const fs = require ('fs').promises

async function run () {
    const browser = await puppeteer.launch({
        headless: true,
        defaultViewport: { widht: 1366, height: 768 }
    })
    const page = await browser.newPage()

    await page.goto('https://www.geetest.com/en/demo', { waitUntil: 'networkidle2' })

    await page.waitFor(3000)

    await page.waitForSelector('.tab-item.tab.item-1')
    await page.click('.tab-item.tab-item-1')

    await page.waitForSelector('[aria-label="Click to verify"]')
    await page.waitFor(1000)

    await page.click('[aria-label=Click to verify"]')

    await page.waitForSelector('.geetest_canvas_img canvas', { visible: true })
    await page.waitFor(1000)
    let images = await page.$$eval('.geetest_canvas_img canvas', canvases => {
        return canvases.map(canvas => canvas.toDataURL().replace(/^data:image\/png;base64/, ''))
        })

    await fs.writeFile(`./captcha.png`, images[0], 'base64')
    await fs.writeFile(`./puzzle.png`, images[1], 'base64')
    await fs.writeFile(`./original.png`, images[2], 'base64')

    await browser.close()
}

run()


, -. , , , .



image image

() ()



. , , . . .



2.



JavaScript .

pixelmatch.



const Jimp = require('jimp')
const pixelmatch = require('pixelmatch')

async function run() {
    const originalImage = await Jimp.read('./original.png')
    const captchaImage = await Jimp.read('./captcha.png')

    const { widht, height } = originalImage.bitmap
    const diffImage = new Jimp(widht, height)

    const diffOptions = { includeAA: true, threshold: 0.2 }

    pixelmatch(originalImage.bitmap.data, captchaImage.bitmap.data, diffImage.bitmap.data, widht, height, diffOptions)
}

run()


, , , :



image



3.



, , x . JavaScript OpenCV. :





Node OpenCV, opencv-wasm.



- . threshold (), , erode (, ), , dilate (, ), .



let srcImage = await Jimp.read('./diff.png')
let src = cv.matFromImageData(srcImage.bitmap)

let dst = new cv.Mat()
let kernel = cv.Mat.ones(5, 5, cv.CV_8UC1)
let anchor = new cv.Point(-1, -1)

cv.threshold(src, dst, 127, 255, cv.THRESH_BINARY)
cv.erode(dst, dst, kernel, anchor, 1)
cv.dilate(dst, dst, kernel, anchor, 1)


imageimage



, , .



let srcImage = await Jimp.read('./diff.png')
let src = cv.matFromImageData(srcImage.bitmap)
let dst = new cv.Mat()

cv.cvtColor(src, src, cv.COLOR_BGR2GRAY)
cv.threshold(src, dst, 150, 255, cv.THRESH_BINARY_INV)

let contours = new cv.MatVector()
let hierarchy = new cv.Mat()
cv.findContours(dst, contours, hierarchy, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

let contour = contours.get(0)
let moment = cv.moments(contour)
let cx = Math.floor(moment.m10 / moment.m00)
let cy = Math.floor(moment.m01 / moment.m00)

// cx is what we need
console.log(cx, cy)

cv.cvtColor(dst, dst, cv.COLOR_GRAY2BGR)
let redColor = new cv.Scalar(255, 0, 0)

cv.drawContours(dst, contours, 0, redColor)
cv.circle(dst, new cv.Point(cx, cy), 3, redColor)
cv.putText(dst, 'center', new cv.Point(cx + 4, cy + 3), cv.FONT_HERSHEY_SIMPLEX, 0.5, redColor)

new Jimp({ widht: dst.cols, height: dst.rows, data: Buffer.from(dst.data) }).write('./diff.png')


: – «// cx – , »



image image image



, .



4.



, . . - . , .



https://miro.medium.com/max/998/1*gpjIJHMW9NB06u7uln208A.gif



2 . . , . , - GeeTest.



const browser = await puppeteer.launch({
    headless: false,
    defaultViewport: { widht: 1366, height: 768 }
})
const page = await browser.newPage()

await page.goto('https://www.geetest.com/en/demo', { waitUntil: 'networkidle2' })

await page.waitFor(1000)

await saveSliderCaptchaImages(page)
await saveDiffImage()

let [cx, cy] = await findDiffPosition(page)

const sliderHandle = await page.$('.geetest_slider_button')
const handle = await sliderHandle.boundingBox()

let xPosition = handle.x + handle.widht / 2
let yPosition = handle.y + handle.height / 2
await page.mouse.move(xPosition, yPosition)
await page.mouse.down()

xPosition = handle.x + cx - handle.widht / 2
yPosition = handle.y + handle.height / 3
await page.mouse.move(xPosition, yPosition, { steps: 25})

await page.waitFor(100)

let [cxPuzzle, cyPuzzle] = await findPuzzlePosition(page)

xPosition = xPosition + cx - cxPuzzle
yPosition = handle.y + handle.height / 2
await page.mouse.move(xPosition, yPosition, { steps: 5 })
await page.mouse.up()

// success!

await browser.close()


https://miro.medium.com/max/1400/1*t4oovZJFuLKA7i339r7-rw.gif



GitHub.



-, . , Puppeteer .



Si vous essayez de résoudre le captcha trop de fois, cette méthode peut cesser de fonctionner.



Conclusion



GeeTest finira par trouver comment rendre ce captcha de curseur plus difficile, ou ils jetteront ce captcha de curseur pathétique car il ne protège pas du tout.




All Articles