JD sliding verification code cracking of selenium and PIL

Keywords: Selenium Attribute npm jupyter

Single layer graph slide verification code of selenium and PIL

How to crack the slide verification code

There are various mechanisms of anti climbing on the market, among which the sliding verification code is divided into two-layer graph and single-layer graph:
1. The style code in JS can be modified in the console, the image with sliding gap and the complete image can be obtained by modifying the display attribute, the color comparison between the two images can be carried out to determine the sliding distance, and the landing can be realized by simulating the track of human activity verification code;
2. Single layer graph does not have complete graph, so it is more difficult than double layer graph. The biggest difficulty lies in the calculation of distance and sliding track

preparation in advance

Before we start, we need to prepare:

  1. Download the required class package: pilot (inheriting PIL), Selenium, time
  2. Install browser debugging tools (this article uses chrome driver)
    Chrome driver debugging download address: link: http://npm.taobao.org/mirrors/chromedriver/
  3. Prepare debugging tools. The tools used in this article are jupyter notebook, which can be pycharm

Code operation

Imported classes and packages:

from collections import Counter
from PIL import Image
from selenium import webdriver
import time
from selenium.webdriver.common.action_chains import ActionChains
  1. First of all, the method is encapsulated by creating a class to facilitate subsequent calls
class JDlogin():
    def __init__(self):#Define function, link login page
        self.driver = driver = webdriver.Chrome()#Start debugging tool
        self.driver.get('https://passport.jd.com/new/login.aspx')#Get the JD landing page
        time.sleep(2)
  1. After that, the image is acquired through selenium, and then delivered to PIL for image processing
	def get_picture(self):#Get pictures
		#Click "account login" through xpath search button
        self.driver.find_element_by_xpath('.//div[@class="login-tab login-tab-r"]/a').click()
        time.sleep(1)
        #Location account input box
        self.driver.find_element_by_xpath('.//input[@id="loginname"]').send_keys('Your JD Account number')
        time.sleep(1)
        #Location password input box
        self.driver.find_element_by_xpath('.//input[@id="nloginpwd"]').send_keys('Your JD Password')
        time.sleep(1)
        #Locate the login button and click it. The verification code image will be displayed
        self.driver.find_element_by_xpath('.//div[@class="login-btn"]/a').click()
        time.sleep(1)
        #Modify the JS hidden slider and take a screenshot to get the verification code picture, and save it to the current directory, named slice.png (the same is true for the double-layer graph, but the ClassName and xpath need to be changed)
        js = 'document.getElementsByClassName("JDJRV-smallimg")[0].style.display="none"'
        self.driver.execute_script(js)
        slice_path = './slice.png'
        self.driver.find_element_by_xpath('.//div[@class="JDJRV-bigimg"]').screenshot(slice_path)
        time.sleep(1)
        #Restore JS changes after 1 second stop, and return to the original state of the page (or the double-layer diagram)
        js = 'document.getElementsByClassName("JDJRV-smallimg")[0].style.display="block"'
        self.driver.execute_script(js)

Effect after hiding slider:

  1. Process the obtained verification code image (graying, binarization, noise reduction)
    The double-layer graph can directly compare two pictures, while the single-layer graph needs to process and then compare itself. This paper is a single-layer graph example
 	def shape(self, w, h, image):  # Binary, change all points to 0 or 255
        tem = 0
        for x in range(w):
            for y in range(h):
                tem += image.getpixel((x, y))
        pixel_ave = tem / w / h * 0.7
        for x in range(w):
            for y in range(h):
                p = image.getpixel((x, y))
                if p < pixel_ave:
                    image.putpixel((x, y), 0)
                else:
                    image.putpixel((x, y), 255)
        return image

    def reducenoise(self, image):#Noise reduction treatment
        w, h = image.size
        for x in range(0, 40):  # Handle leftmost
            for y in range(h):
                image2 = image.putpixel((x, y), 255)
        return image

    def make_picture(self):  # Processing pictures, graying and two value, noise reduction
        im = Image.open('slice.png')
        im2 = im.convert("L")
        w, h = im2.size
        im3 = self.shape(w, h, im2)
        im4 = self.reducenoise(im3)
        return im3

Effect after image processing:

  1. Calculate the distance from the left edge of the verification image to the left edge of the notch (that is, the drag distance of the slider)
    def get_juli(self, image):  # Calculate distance
        w, h = image.size
        ls = []
        for i in range(31, w - 31):#Place the slider at the left most of the picture, and the notch coordinate x cannot be less than 31
            for j in range(10, h):
                if image.getpixel((i, j)) < 100:
                    count = 0
                    for k in range(i, i + 31):
                        if image.getpixel((k, j)) < 100:
                            count += 1
                        else:
                            break
                    if count > 27: ls.append(i)

        return Counter(ls).most_common(1)[0][0]
  1. Design drag track (the most difficult point)
    We need to design the rules of dragging the slider to simulate human operation, so as to avoid the verification of the computer
    When I design, I have a success rate of 1 / 3-1 / 5, but the success rate is different every day, and the machine is also learning. I recommend you to design together, which can be commented at the bottom of this article

    def get_track(self, distance):  # Design drag track
        ls = [1]
        while 1:
            i = ls[-1] * 2
            ls.append(i)
            if sum(ls) > distance * 0.7:
                break

        ls.append(int(distance - sum(ls)))

        return ls
  1. Execute the instruction of dragging the slider through selenium to realize the verification login
    def drog_btn(self, track):  # Drag slider
    	#Positioning slider
        ele = self.driver.find_element_by_xpath('.//div[@class="JDJRV-slide-inner JDJRV-slide-btn"]')
        #Design drag action chain (click and hold)
        ActionChains(self.driver).click_and_hold(ele).perform()
        #According to the design track, realize the slider drag
        for i in track:
            ActionChains(self.driver).move_by_offset(i, 0).perform()
		#Sleep for 0.25 seconds, disguise the judgment process of adults
        time.sleep(0.25)
        #Release the slider, similar to releasing the mouse
        ActionChains(self.driver).release().perform()
        time.sleep(2)
  1. Judge whether it is successful or not. If it fails, try again (alas, the verification code is not so easy to crack. JD is also a powerful company. It must be very strong in anti climbing. It always needs experiments.)
    def check(self):#Try again
        self.get_picture()
        image = self.make_picture()
        distance = self.get_juli(image)
        track = self.get_track(distance)
        self.drog_btn(track)
  1. Execution code:
if __name__ == '__main__':
    login = JDlogin()
    login.get_picture()
    image = login.make_picture()
    distance = login.get_juli(image)
    track = login.get_track(distance)
    login.drog_btn(track)
    time_int = 0
    while time_int < 5:
        input("Need to try again")
        login.driver.refresh()
        login.check()
        time_int += 1

Successfully verified the picture of landing:

Disclaimer: This article is only for technology sharing, pure personal hobby, not engaged in any business behavior and illegal behavior, and also hope that people who learn from it will mainly learn from it and abide by the law. If JD causes any loss, I will not be responsible for it. I just try to be lazy, log in without hands, and don't do any illegal acts. If someone causes your company's loss due to the code in this article, JD is required to find the murderer by itself, which has nothing to do with me ~ O.O

Posted by Kev on Sun, 10 May 2020 01:54:26 -0700