Catalog
1: Introduction to Polar Sliding Authentication Code
_In recent years, there have been some new types of verification codes that do not want the old ones to be unfriendly to human beings, but the difficulty of identifying them has increased several levels.Therefore, other means are needed.
_Identify the required python libraries: selenium and ChromeDriver drivers, which are different for different browsers to download.
Authentication Code Access Website: http://www.geetest.com/
_Polar sliding validation code has reached version 3.0. It is more difficult to identify related graphic validation code. The principle is to drag the picture to the gap, then validate the combined image, which generates three encryption parameters, submit the form to the background, and then validate in the background.
Pyramid also adds machine learning methods to identify malicious programs. It takes only 0.4 seconds to prevent simulation, counterfeiting and violence, and to protect resources from abuse and theft.
_Our programs generally do so as long as they are not crawled maliciously and follow the crawl protocol.Never burden the server.
2. Ideas for Identifying Polar Sliding Verification Codes
_Here we can complete the validation by simulating the browser action, and complete the validation by fully simulating the human behavior with Selenium.
_is mainly divided into three steps
(1) Simulated click validation button
(2) Identifying the position of the sliding notch
(3) Simulated dragging slider
Step (1) is also better to say that step (2) is the key step to identify the location of the interface. Image processing is used to see the location of the interface, and the method of comparison detection with the original image is used to identify the location of the gap.Get two pictures at the same time, set a contrast threshold, and then traverse the two pictures to find the pixels with the same RGB difference exceeding this threshold, then the pixel point location is the location of the gap.
_Step (3) is more difficult because the human movement track is accelerated then decelerated, and methods such as uniform and random movement cannot be verified. To simulate this process well.
3: Polar Verification Code Recognition
1. Authentication code official website: https://auth.geetest.com/login/
The official pictures are:
2. Initialize configuration
# Registered username and password email = '' password = '' class CrackGeetest(): def __init__(self): self.url = 'https://account.geetest.com/login' self.browser = webdriver.Chrome() self.wait = WebDriverWait(self.browser, 20) self.email = email self.password = password
3. Analog Click
_The first step in identifying a verification code is to simulate clicking on the initial verification button and obtaining it by waiting explicitly.
def get_geetest_button(self): """ Get Initial Validation Button Return value: Button object """ button = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_radar_tip'))) return button
_Simulate clicks at the call location:
# Click the Verify button button = self.get_geetest_button() button.click()
4. Identify gaps
_Next, identify the location of the gap. First, get two pictures and compare them. The different location is the gap.
Get pictures without gaps.Select a picture element with selenium to get a screenshot of the whole web page and clip it. The code is as follows:
def get_screenshot(self): """ //Get Screenshot of Web Page :return: Screenshot object """ screenshot = self.browser.get_screenshot_as_png() screenshot = Image.open(BytesIO(screenshot)) return screenshot def get_position(self): """ //Get Authentication Code Location :return: Authentication code position tuple """ img = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'geetest_canvas_img'))) time.sleep(2) location = img.location size = img.size top, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], location['x'] + size[ 'width'] return (top, bottom, left, right) def get_geetest_image(self, name='captcha.png'): """ //Get Authentication Code Picture :return: Picture object """ top, bottom, left, right = self.get_position() print('Verification Code Location', top, bottom, left, right) screenshot = self.get_screenshot() captcha = screenshot.crop((left, top, right, bottom)) captcha.save(name) return captcha
_Next, you need to get the second picture, which is a picture with a gap. Just click on the slider below to get the gap. The code is as follows:
def get_slider(self): """ //Get Slider :return: Slider object """ slider = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_slider_button'))) return slider
_click() triggers the click as follows:
# Point by Exhalation Gap slider = self.get_slider() slider.click()
_Next, by comparing pictures to get gaps, by traversing each coordinate point on the picture, get RGB data of the corresponding pixel points of two pictures.If within a certain range, it means two pixels are the same, and continues to compare the next pixel point.If the difference exceeds a certain range, it means that the pixel points are different, and the current location is the gap location.This is done by setting a threshold value, which is coded as follows:
def is_pixel_equal(self, image1, image2, x, y): """ //Determine if two pixels are the same :param image1: Picture 1 :param image2: Picture 2 :param x: position x :param y: position y :return: Are the pixels the same """ # Pixel points from two pictures pixel1 = image1.load()[x, y] pixel2 = image2.load()[x, y] threshold = 60 if abs(pixel1[0] - pixel2[0]) < threshold and abs(pixel1[1] - pixel2[1]) < threshold and abs( pixel1[2] - pixel2[2]) < threshold: return True else: return False def get_gap(self, image1, image2): """ //Get Gap Offset :param image1: Pictures without gaps :param image2: Picture with gaps :return: """ left = 60 for i in range(left, image1.size[0]): for j in range(image1.size[1]): if not self.is_pixel_equal(image1, image2, i, j): left = i return left return left
5. Simulate dragging
_Simulated dragging is not complicated, but it has more details.Drag the slider to the corresponding position with the relevant function.But if you drag at a uniform speed, you will inevitably recognize that it is a program, not a human operation, because humans cannot drag at a perfectly uniform speed, and it will recognize that it is a machine operation, causing the verification code to fail.
_Through different methods of detection, we found that the validation can be completed by uniformly accelerating the front slider and uniformly decelerating the rear slider.
_Here the acceleration is expressed in a, the current velocity in v, the initial velocity in vo, the displacement in x, and the time in t.
The code is as follows:
def get_track(self, distance): """ //Obtaining a moving track from an offset :param distance: Offset :return: Moving Track """ # Moving Track track = [] # Current Displacement current = 0 # Deceleration threshold mid = distance * 4 / 5 # Calculate Interval t = 0.2 # Initial velocity v = 0 while current < distance: if current < mid: # Acceleration is positive 2 a = 2 else: # Acceleration is negative 3 a = -3 # Initial velocity v0 v0 = v # Current speed v = v0 + at v = v0 + a * t # Move distance x = v0t + 1/2 * a * t^2 move = v0 * t + 1 / 2 * a * t * t # Current Displacement current += move # Join Track track.append(round(move)) return track def move_to_gap(self, slider, track): """ //Drag slider to notch :param slider: slider :param track: trajectory :return: """ ActionChains(self.browser).click_and_hold(slider).perform() for x in track: ActionChains(self.browser).move_by_offset(xoffset=x, yoffset=0).perform() time.sleep(0.5) ActionChains(self.browser).release().perform()
6:All Code
import time from io import BytesIO from PIL import Image from selenium import webdriver from selenium.webdriver import ActionChains from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC EMAIL = 'cqc@cuiqingcai.com' PASSWORD = '' BORDER = 6 INIT_LEFT = 60 # Registered username and password email = '' password = '' class CrackGeetest(): def __init__(self): self.url = 'https://account.geetest.com/login' self.browser = webdriver.Chrome() self.wait = WebDriverWait(self.browser, 20) self.email = email self.password = password def __del__(self): self.browser.close() def get_geetest_button(self): """ //Get Initial Validation Button //Return value: Button object """ button = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_radar_tip'))) return button def get_screenshot(self): """ //Get Screenshot of Web Page :return: Screenshot object """ screenshot = self.browser.get_screenshot_as_png() screenshot = Image.open(BytesIO(screenshot)) return screenshot def get_position(self): """ //Get Authentication Code Location :return: Authentication code position tuple """ img = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'geetest_canvas_img'))) time.sleep(2) location = img.location size = img.size top, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], location['x'] + size[ 'width'] return (top, bottom, left, right) def get_geetest_image(self, name='captcha.png'): """ //Get Authentication Code Picture :return: Picture object """ top, bottom, left, right = self.get_position() print('Verification Code Location', top, bottom, left, right) screenshot = self.get_screenshot() captcha = screenshot.crop((left, top, right, bottom)) captcha.save(name) return captcha def get_slider(self): """ //Get Slider :return: Slider object """ slider = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_slider_button'))) return slider def open(self): """ //Open Web page to enter user name password :return: None """ self.browser.get(self.url) email = self.wait.until(EC.presence_of_element_located((By.ID, 'email'))) password = self.wait.until(EC.presence_of_element_located((By.ID, 'password'))) email.send_keys(self.email) password.send_keys(self.password) def is_pixel_equal(self, image1, image2, x, y): """ //Determine if two pixels are the same :param image1: Picture 1 :param image2: Picture 2 :param x: position x :param y: position y :return: Are the pixels the same """ # Pixel points from two pictures pixel1 = image1.load()[x, y] pixel2 = image2.load()[x, y] threshold = 60 if abs(pixel1[0] - pixel2[0]) < threshold and abs(pixel1[1] - pixel2[1]) < threshold and abs( pixel1[2] - pixel2[2]) < threshold: return True else: return False def get_gap(self, image1, image2): """ //Get Gap Offset :param image1: Pictures without gaps :param image2: Picture with gaps :return: """ left = 60 for i in range(left, image1.size[0]): for j in range(image1.size[1]): if not self.is_pixel_equal(image1, image2, i, j): left = i return left return left def get_track(self, distance): """ //Obtaining a moving track from an offset :param distance: Offset :return: Moving Track """ # Moving Track track = [] # Current Displacement current = 0 # Deceleration threshold mid = distance * 4 / 5 # Calculate Interval t = 0.2 # Initial velocity v = 0 while current < distance: if current < mid: # Acceleration is positive 2 a = 2 else: # Acceleration is negative 3 a = -3 # Initial velocity v0 v0 = v # Current speed v = v0 + at v = v0 + a * t # Move distance x = v0t + 1/2 * a * t^2 move = v0 * t + 1 / 2 * a * t * t # Current Displacement current += move # Join Track track.append(round(move)) return track def move_to_gap(self, slider, track): """ //Drag slider to notch :param slider: slider :param track: trajectory :return: """ ActionChains(self.browser).click_and_hold(slider).perform() for x in track: ActionChains(self.browser).move_by_offset(xoffset=x, yoffset=0).perform() time.sleep(0.5) ActionChains(self.browser).release().perform() def login(self): """ //Sign in :return: None """ submit = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'login-btn'))) submit.click() time.sleep(10) print('Login Successful') def crack(self): # Enter User Name Password self.open() # Click the Verify button button = self.get_geetest_button() button.click() # Get Authentication Code Picture image1 = self.get_geetest_image('captcha1.png') # Point by Exhalation Gap slider = self.get_slider() slider.click() # Get pictures of authentication codes with gaps image2 = self.get_geetest_image('captcha2.png') # Get Gap Location gap = self.get_gap(image1, image2) print('Gap location', gap) # Minus notch displacement gap -= BORDER # Getting a moving track track = self.get_track(gap) print('Slide Track', track) # Drag slider self.move_to_gap(slider, track) success = self.wait.until( EC.text_to_be_present_in_element((By.CLASS_NAME, 'geetest_success_radar_tip_content'), 'Verification successful')) print(success) # Retry after failure if not success: self.crack() else: self.login() if __name__ == '__main__': crack = CrackGeetest() crack.crack()
This method is suitable for different polar sliding verification codes. The key lies in the idea of identification, how to identify the location of gaps, how to generate motion tracks and so on.Similar validation codes can be encountered later for this purpose.