# -*- coding:utf-8 -*- import os import random import re import ssl import time from urllib.request import urlretrieve import undetected_chromedriver as uc from PIL import Image from lxml import etree 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 class CrackGeetest(): def __init__(self): self.url = 'https://gsxt.amr.jiangxi.gov.cn/indexmain.jsp?' self.company_name = "南昌银行" def chrome_operate(self): chrome_options = webdriver.ChromeOptions() # chrome_options.add_argument('--headless') chrome_options.add_argument('--no-sandbox') chrome_options.add_argument('--disable-gpu') chrome_options.add_argument('--lang=zh-CN') chrome_options.add_argument('--hide-scrollbars') # 禁止加载图片 chrome_options.add_argument('blink-settings=imagesEnabled=false') # 指定浏览器分辨率 chrome_options.add_argument('--start-maximized') ssl._create_default_https_context = ssl._create_unverified_context uc.TARGET_VERSION = 110 # 指定chrome版本 self.browser = uc.Chrome(options=chrome_options) self.wait = WebDriverWait(self.browser, 10) self.browser.get(self.url) time.sleep(2) self.browser.find_element(By.XPATH, '//*[@id="entname"]').click() time.sleep(0.5) self.browser.find_element(By.XPATH, '//*[@id="entname"]').clear() time.sleep(0.5) self.browser.find_element(By.XPATH, '//*[@id="entname"]').send_keys(self.company_name) time.sleep(0.5) self.browser.find_element(By.XPATH, '//*[@id="serach"]').click() time.sleep(1) def mk_img_dir(self): """ 创建图片目录文件 :return: """ if not os.path.exists('../national_enterprise_credit/Image'): os.mkdir('../national_enterprise_credit/Image') def get_geetest_image(self): """ 获取验证码图片 :return: 图片location信息 """ bg = [] fullgb = [] while bg == [] and fullgb == []: etree_html = etree.HTML(self.browser.page_source) bg = etree_html.xpath('//div[@class="gt_cut_bg_slice"]') fullgb = etree_html.xpath('//div[@class="gt_cut_fullbg_slice"]') # soup = BeautifulSoup(self.browser.page_source, 'lxml') # bg = soup.find_all('div', class_='gt_cut_bg_slice') # fullgb = soup.find_all('div', class_='gt_cut_fullbg_slice') bg_url = re.findall('url\(\"(.*?)\"\);', bg[0].get('style'))[0].replace('webp', 'jpg') fullgb_url = re.findall('url\(\"(.*?)\"\);', fullgb[0].get('style'))[0].replace('webp', 'jpg') bg_location_list = [] fullgb_location_list = [] for each_bg in bg: location = {} location['x'] = int(re.findall('background-position: (.*)px (.*)px;', each_bg.get('style'))[0][0]) location['y'] = int(re.findall('background-position: (.*)px (.*)px;', each_bg.get('style'))[0][1]) bg_location_list.append(location) for each_fullgb in fullgb: location = {} location['x'] = int(re.findall('background-position: (.*)px (.*)px;', each_fullgb.get('style'))[0][0]) location['y'] = int(re.findall('background-position: (.*)px (.*)px;', each_fullgb.get('style'))[0][1]) fullgb_location_list.append(location) self.mk_img_dir() urlretrieve(url=bg_url, filename='../national_enterprise_credit/Image/bg.jpg') print('缺口图片下载完成!') urlretrieve(url=fullgb_url, filename='../national_enterprise_credit/Image/fullgb.jpg') print('背景图片下载完成!') return bg_location_list, fullgb_location_list def get_merge_image(self, filename, location_list): """ 根据图片位置合并还原 :param filename: 图片 :param location: 位置 :return:合并后的图片对象 """ im = Image.open(filename) new_im = Image.new('RGB', (260, 116)) im_list_upper = [] im_list_lower = [] for location in location_list: if location['y'] == -58: im_list_upper.append(im.crop((abs(location['x']), 58, abs(location['x']) + 10, 116))) if location['y'] == 0: im_list_lower.append(im.crop((abs(location['x']), 0, abs(location['x']) + 10, 58))) x_offset = 0 for img in im_list_upper: new_im.paste(img, (x_offset, 0)) x_offset += img.size[0] x_offset = 0 for img in im_list_lower: new_im.paste(img, (x_offset, 58)) x_offset += img.size[0] new_im.save('Image/' + re.split('[./]', filename)[1] + '1.jpg') return new_im def is_px_equal(self, img1, img2, x, y): """ 判断两个像素是否相同 :param img1: 图片1 :param img2:图片2 :param x:位置1 :param y:位置2 :return:像素是否相同 """ pix1 = img1.load()[x, y] pix2 = img2.load()[x, y] threshold = 60 if abs(pix1[0] - pix2[0]) < threshold and abs(pix1[1] - pix2[1]) < threshold and abs(pix1[2] - pix2[2]) < threshold: return True else: return False def get_gap(self, img1, img2): """ 获取缺口偏移量 :param img1: 不带缺口图片 :param img2: 带缺口图片 :return: """ left = 60 for i in range(left, img1.size[0]): for j in range(img1.size[1]): if not self.is_px_equal(img1, img2, i, j): left = i return left return left def get_track(self, distance): """ 根据偏移量和手动操作模拟计算移动轨迹 :param distance: 偏移量 :return: 移动轨迹 """ # 移动轨迹 tracks = [] # 当前位移 current = 0 # 减速阈值 mid = distance * 4 / 5 # 时间间隔 t = 0.2 # 初始速度 v = 0 while current < distance: if current < mid: a = random.uniform(2, 5) else: a = -(random.uniform(12.5, 13.5)) v0 = v v = v0 + a * t x = v0 * t + 1 / 2 * a * t * t current += x if 0.6 < current - distance < 1: x = x - 0.53 tracks.append(round(x, 2)) elif 1 < current - distance < 1.5: x = x - 1.4 tracks.append(round(x, 2)) elif 1.5 < current - distance < 3: x = x - 1.8 tracks.append(round(x, 2)) else: tracks.append(round(x, 2)) return tracks def get_slider(self): """ 获取滑块 :return:滑块对象 """ try: slider = self.wait.until(EC.element_to_be_clickable((By.XPATH, '//div[@class="gt_slider"]/div[contains(@class,"gt_slider_knob")]'))) return slider except TimeoutError: print('加载超时...') def move_to_gap(self, slider, tracks): """ 将滑块移动至偏移量处 :param slider: 滑块 :param tracks: 移动轨迹 :return: """ action = ActionChains(self.browser) action.click_and_hold(slider).perform() for x in tracks: action.move_by_offset(xoffset=x, yoffset=-1).perform() action = ActionChains(self.browser) time.sleep(0.6) action.release().perform() def success_check(self): """ 验证是否成功 :return: """ try: if re.findall('gt_success', self.browser.page_source, re.S): print('验证成功!') return True else: print('验证失败!') return False except TimeoutError: print('加载超时...') finally: time.sleep(10000) # self.browser.close() if __name__ == '__main__': check = CrackGeetest() check.chrome_operate() bg_location_list, fullgb_location_list = check.get_geetest_image() img1 = check.get_merge_image('Image/fullgb.jpg', fullgb_location_list) img2 = check.get_merge_image('Image/bg.jpg', fullgb_location_list) distance = check.get_gap(img1, img2) * 1.138 slider = check.get_slider() tracks = check.get_track(distance) print(tracks) check.move_to_gap(slider, tracks) # time.sleep(0.5) CHECK = check.success_check()
标签:bg,return,滑块,get,self,极验,验证码,fullgb,location From: https://www.cnblogs.com/yoyo1216/p/17166810.html