Due to various reasons, we were unable to achieve the goal of the vision. Recording the intermediate results here can be regarded as an ending. This article is mainly about individual cases of using selenium to solve the slider verification code.
Ideas:
-
Use selenium to open the specified website in the browser
-
Download incomplete block images and background images to local
-
Compare the similarities between the two pictures and calculate the distance to slide
-
Plan a route, move the slider
01. Implementation steps
01. Use selenium to open the browser and browse the specified website
1. Find the path of chromedriver.exe
Click Start to find the Google icon==》Right-click for more==》Open file location==》Right-click on Google shortcut==》Properties ==>Open file location==>Copy path
2. Code
from selenium import webdriver # chrome_path should be changed to your own path chrome_path = r"C:\Users\11248\AppData\Local\Google\Chrome\Application\chromedriver.exe" url = 'https://icas.jnu.edu.cn/cas/login' driver = webdriver.Chrome(chrome_path) driver.get(url)
02, download the incomplete block image and background image to the local device
1. Find the image location
Open the web page, enter the developer tools, and find the image location
2. Code
import time import requests from PIL import Image from selenium.webdriver.common.by import By from io import BytesIO time.sleep(5)# Stay for a few seconds after entering the page and wait for the page to load. target_link = driver.find_element(By.CLASS_NAME, "yidun_bg-img").get_attribute('src') template_link = driver.find_element(By.CLASS_NAME, "yidun_jigsaw").get_attribute('src') target_img = Image.open(BytesIO(requests.get(target_link).content)) template_img = Image.open(BytesIO(requests.get(template_link).content)) target_img.save('target.jpg') template_img.save('template.png')
Now I have also found a lot of test friends and created a communication group to share technology, sharing a lot of technical documents and video tutorials we collected. If you don’t want to experience the feeling of not being able to find resources when self-study, having no one to answer your questions, and persisting for a few days before giving up. You can join us to communicate. And there are many technical experts who have made certain achievements in automation, performance, security, test development, etc. Share their experience, and also share many live lectures and technical salons You can learn for free! Focus on it! Open source! ! ! QQ group number: 110685036
03. Compare the similarities between the two pictures and calculate the sliding distance
1. Use matchTemplate to get the moving distance
Because the position of the defective block in the background image is different from the brightness of the original defective image, direct comparison of the similar parts of the two images often does not yield satisfactory results. Here, the two images need to be processed to a certain extent. To avoid this brightness interference, the author first performs grayscale processing on the two pictures, then performs Gaussian processing on the images, and finally performs edge detection.
def handel_img(img): imgGray = cv2.cvtColor(img, cv2.COLOR_RGBA2GRAY) # Convert to grayscale image imgBlur = cv2.GaussianBlur(imgGray, (5, 5), 1) # Gaussian blur imgCanny = cv2.Canny(imgBlur, 60, 60) # Canny operator edge detection return imgCanny Convert JPG image to 4 channels (RGBA) def add_alpha_channel(img): """ Add alpha channel to jpg image """ r_channel, g_channel, b_channel = cv2.split(img) # Strip jpg image channels alpha_channel = np.ones(b_channel.shape, dtype=b_channel.dtype) * 255 # Create Alpha channel img_new = cv2.merge((r_channel, g_channel, b_channel, alpha_channel)) # Merge channel return img_new
2. Code
import cv2 # read image def match(img_jpg_path, img_png_path): # read image img_jpg = cv2.imread(img_jpg_path, cv2.IMREAD_UNCHANGED) img_png = cv2.imread(img_png_path, cv2.IMREAD_UNCHANGED) # Determine whether the jpg image is already 4 channels if img_jpg.shape[2] == 3: img_jpg = add_alpha_channel(img_jpg) img = handel_img(img_jpg) small_img = handel_img(img_png) res_TM_CCOEFF_NORMED = cv2.matchTemplate(img, small_img, 3) value = cv2.minMaxLoc(res_TM_CCOEFF_NORMED) value = value[3][0] # Get the moving distance return value
3. Testing effect
In order to verify whether the ideas and methods are appropriate, the slider image and the background image are spliced here to bury a small hole behind.
def merge_img(jpg_img, png_img, y1, y2, x1, x2): """ Overlay png transparent images with jpg images y1, y2, x1, x2 are the superimposed position coordinate values """ # Determine whether the jpg image is already 4 channels if jpg_img.shape[2] == 3: jpg_img = add_alpha_channel(jpg_img) # Get the alpha value of the image to be overwritten, divide the pixel value by 255, so that the value remains between 0-1 alpha_png = png_img[yy1:yy2, xx1:xx2, 3] / 255.0 alpha_jpg = 1 - alpha_png # Start overlay for c in range(0, 3): jpg_img[y1:y2, x1:x2, c] = ((alpha_jpg * jpg_img[y1:y2, x1:x2, c]) + (alpha_png * png_img[yy1:yy2, xx1:xx2, c])) return jpg_img img_jpg_path = 'target.jpg' # Readers can modify the file path by themselves img_png_path = 'template.png' # Readers can modify the file path by themselves x1 = match(img_jpg_path, img_png_path) y1 = 0 x2 = x1 + img_png.shape[1] y2 = y1 + img_png.shape[0] # Start overlay res_img = merge_img(img_jpg, img_png, y1, y2, x1, x2) cv2.imshow("res_img ", res_img) cv2.waitKey(0)
04, plan the route, move the slider
1. Click the slider to move
Use the distance obtained in Section 3 to click the slider to move it.
from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver import ActionChains def crack_slider(distance): wait = WebDriverWait(driver, 20) slider = wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'yidun_slider'))) ActionChains(self.driver).click_and_hold(slider).perform() ActionChains(self.driver).move_by_offset(xoffset=distance, yoffset=0).perform() time.sleep(2) ActionChains(self.driver).release().perform() return 0
The magical thing is that when the trap comes, no matching is successful.
2. Reasons for matching failure
There are two reasons for this:
-
The image size has changed and the distance needs to be converted.
-
When the slider slides, the relative position of the slider and the missing block changes.
First solve the problem of image size changes and find the image size on the web page: 345×172.500
Download to local image size: 480×240
So the distance needs to be processed as follows:
distance = distance / 480 * 345
Regarding the second question, I haven’t found a good measuring tool here to measure it. Fortunately, the verification code does not require high position accuracy, so just try the numbers one by one.
distance = distance /480 * 345 + 12
05, Supplement
While studying the Jiexian verification code, some websites have verified the movement trajectory. If the slide is too fast, machine operation will also be recognized. In order to simulate manual operation, excellent programmers wrote a magic movement trajectory.
For example: We can first exceed the target and then move back.
def get_tracks(distance): distance + = 20 v = 0 t=0.2 forward_tracks = [] current = 0 mid = distance * 3 / 5 while current < distance: if current < mid: a = 2 else: a = -3 s = v * t + 0.5 * a * (t ** 2) v = v + a * t current + = s forward_tracks.append(round(s)) back_tracks = [-3, -3, -2, -2, -2, -2, -2, -1, -1, -1] return {'forward_tracks': forward_tracks, 'back_tracks': back_tracks} def crack_slider(tracks): wait = WebDriverWait(driver, 20) slider = wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'yidun_slider'))) ActionChains(driver).click_and_hold(slider).perform() # Simulate holding down the left mouse button for track in tracks['forward_tracks']: ActionChains(driver).move_by_offset(xoffset=track, yoffset=0).perform() time.sleep(0.5) for back_tracks in tracks['back_tracks']: ActionChains(driver).move_by_offset(xoffset=back_tracks, yoffset=0).perform() ActionChains(driver).move_by_offset(xoffset=-4, yoffset=0).perform() ActionChains(driver).move_by_offset(xoffset=4, yoffset=0).perform() time.sleep(0.5) ActionChains(driver).release().perform()# Release the left button return 0
06, complete code
# coding=utf-8 import re import requests import time from io import BytesIO import cv2 import numpy as np from PIL import Image from selenium import webdriver from selenium.webdriver import ActionChains from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait classCrackSlider(): # Use browser screenshots to identify the gap position in the verification code, obtain the required sliding distance, and crack the sliding verification code def __init__(self): super(CrackSlider, self).__init__() self.opts = webdriver.ChromeOptions() self.opts.add_experimental_option('excludeSwitches', ['enable-logging']) # self.driver = webdriver.Chrome(ChromeDriverManager().install(), options=self.opts) chrome_path = r"C:\Users\11248\AppData\Local\Google\Chrome\Application\chromedriver.exe" self.driver = webdriver.Chrome(chrome_path, options=self.opts) self.url = 'https://icas.jnu.edu.cn/cas/login' self.wait = WebDriverWait(self.driver, 10) def get_pic(self): self.driver.get(self.url) time.sleep(5) target_link = self.driver.find_element(By.CLASS_NAME, "yidun_bg-img").get_attribute('src') template_link = self.driver.find_element(By.CLASS_NAME, "yidun_jigsaw").get_attribute('src') target_img = Image.open(BytesIO(requests.get(target_link).content)) template_img = Image.open(BytesIO(requests.get(template_link).content)) target_img.save('target.jpg') template_img.save('template.png') def crack_slider(self, distance): slider = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'yidun_slider'))) ActionChains(self.driver).click_and_hold(slider).perform() ActionChains(self.driver).move_by_offset(xoffset=distance, yoffset=0).perform() time.sleep(2) ActionChains(self.driver).release().perform() return 0 def add_alpha_channel(img): """ Add alpha channel to jpg image """ r_channel, g_channel, b_channel = cv2.split(img) # Strip jpg image channels alpha_channel = np.ones(b_channel.shape, dtype=b_channel.dtype) * 255 # Create Alpha channel img_new = cv2.merge((r_channel, g_channel, b_channel, alpha_channel)) # Merge channel return img_new def handel_img(img): imgGray = cv2.cvtColor(img, cv2.COLOR_RGBA2GRAY) # Convert to grayscale image imgBlur = cv2.GaussianBlur(imgGray, (5, 5), 1) # Gaussian blur imgCanny = cv2.Canny(imgBlur, 60, 60) # Canny operator edge detection return imgCanny def match(img_jpg_path, img_png_path): # read image img_jpg = cv2.imread(img_jpg_path, cv2.IMREAD_UNCHANGED) img_png = cv2.imread(img_png_path, cv2.IMREAD_UNCHANGED) # Determine whether the jpg image is already 4 channels if img_jpg.shape[2] == 3: img_jpg = add_alpha_channel(img_jpg) img = handel_img(img_jpg) small_img = handel_img(img_png) res_TM_CCOEFF_NORMED = cv2.matchTemplate(img, small_img, 3) value = cv2.minMaxLoc(res_TM_CCOEFF_NORMED) value = value[3][0] # Get the moving distance return value # 1. Open chromedriver and try to download pictures cs = CrackSlider() cs.get_pic() # 2. Compare pictures and calculate distance img_jpg_path = 'target.jpg' # Readers can modify the file path by themselves img_png_path = 'template.png' # Readers can modify the file path by themselves distance = match(img_jpg_path, img_png_path) distance = distance /480 * 345 + 12 # 3. Move cs.crack_slider(distance)
This ends today’s sharing. If the article is helpful to you, remember to like, collect, and follow it. I will share some useful information from time to time…