美文网首页
2019-05-18

2019-05-18

作者: 莪从莈爱过伱 | 来源:发表于2019-05-18 18:47 被阅读0次

import time

from io import BytesIO

from PIL import Image

import PIL.Image as 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

from bs4 import BeautifulSoup

import re

from urllib.request import urlretrieve

BORDER = 6

class CrackGeetest():

    def __init__(self):

        #初始化设置

        self.url = 'http://gsxt.jxaic.gov.cn/'

        self.browser = webdriver.Chrome('C:\chrom\chromedriver')

        #设置显示等待时间

        self.wait = WebDriverWait(self.browser, 20)

        self.email ='一点点'

        # self.password = PASSWORD

    def __del__(self):

        self.browser.close()

        #点击图片验证按钮

    def get_geetest_button(self):

        button = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'gt_refresh_button')))

        return button

    def get_position(self):

        """

        获取验证码位置

        :return: 验证码位置元组

        """

        img = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'gt_box_holder')))

        time.sleep(2)

        #验证码位置坐标

        location = img.location

        # print(location,'验证码坐标')

        size = img.size

        # print(size,'图片大小')

        top, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], location['x'] + size['width']

        # print(top, bottom, left, right)

        return (top, bottom, left, right)

    def open(self):

        self.browser.get(self.url)

        name = self.wait.until(EC.presence_of_element_located((By.ID, 'entname')))

        name.send_keys(self.email)

        self.browser.find_element_by_xpath('//*[@id="serach"]').click()

    def get_geetest_image(self, name='captcha.png'):

        """

        获取验证码图片

        :return: 图片对象

        """

        top, bottom, left, right = self.get_position()

        print('验证码位置', top, bottom, left, right)

        screenshot = self.get_screenshot()

        captcha = screenshot.crop((left, top, right, bottom))

        captcha.save(name)

        return captcha

    def get_images(self, bg_filename='bg.jpg', fullbg_filename='fullbg.jpg'):

        """

        获取验证码图片

        :return: 图片的location信息

        """

        bg = []

        fullgb = []

        while bg == [] and fullgb == []:

            bf = BeautifulSoup(self.browser.page_source, 'lxml')

            bg = bf.find_all('div', class_='gt_cut_bg_slice')

            fullgb = bf.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 = []

        fullbg_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])

            fullbg_location_list.append(location)

        urlretrieve(url=bg_url, filename=bg_filename)

        print('缺口图片下载完成')

        urlretrieve(url=fullgb_url, filename=fullbg_filename)

        print('背景图片下载完成')

        return bg_location_list, fullbg_location_list

    def get_merge_image(self, filename, location_list):

        """

        根据位置对图片进行合并还原

        :filename:图片

        :location_list:图片位置

        """

        im = image.open(filename)

        new_im = image.new('RGB', (260, 116))

        im_list_upper = []

        im_list_down = []

        for location in location_list:

            if location['y'] == -58:

                im_list_upper.append(im.crop((abs(location['x']), 58, abs(location['x']) + 10, 166)))

            if location['y'] == 0:

                im_list_down.append(im.crop((abs(location['x']), 0, abs(location['x']) + 10, 58)))

        new_im = image.new('RGB', (260, 116))

        x_offset = 0

        for im in im_list_upper:

            new_im.paste(im, (x_offset, 0))

            x_offset += im.size[0]

        x_offset = 0

        for im in im_list_down:

            new_im.paste(im, (x_offset, 58))

            x_offset += im.size[0]

        new_im.save(filename)

        return new_im

    def get_screenshot(self):

        """

        获取网页截图

        :return: 截图对象

        """

        screenshot = self.browser.get_screenshot_as_png()

        screenshot = Image.open(BytesIO(screenshot))

        return screenshot

    def get_slider(self):

        """

        获取滑块

        :return: 滑块对象

        """

        slider = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'gt_slider_knob')))

        return slider

    def get_gap(self, image1, image2):

        """

        获取缺口偏移量

        :param image1: 不带缺口图片

        :param image2: 带缺口图片

        :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 is_pixel_equal(self, image1, image2, x, y):

        """

        判断两个像素是否相同

        :param image1: 图片1

        :param image2: 图片2

        :param x: 位置x

        :param y: 位置y

        :return: 像素是否相同

        """

        # 取两个图片的像素点

        pixel1 = image1.load()[x, y]

        print(pixel1,'图片1')

        pixel2 = image2.load()[x, y]

        print(pixel2,'图片2')

        threshold = 10

        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_track(self, distance):

        """

        根据偏移量获取移动轨迹

        :param distance: 偏移量

        :return: 移动轨迹

        """

        # 移动轨迹

        track = []

        # 当前位移

        current = 0

        # 减速阈值

        mid = distance * 4 / 5

        # 计算间隔

        t = 0.2

        # 初速度

        v = 0

        while current < distance:

            if current < mid:

                # 加速度为正2

                a = 2

            else:

                # 加速度为负3

                a = -3

            # 初速度v0

            v0 = v

            # 当前速度v = v0 + at

            v = v0 + a * t

            # 移动距离x = v0t + 1/2 * a * t^2

            move = v0 * t + 1 / 2 * a * t * t

            # 当前位移

            current += move

            # 加入轨迹

            track.append(round(move))

        return track

    def move_to_gap(self, slider, track):

        print('3')

        """

        拖动滑块到缺口处

        :param slider: 滑块

        :param track: 轨迹

        :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 crack(self):

        #打开浏览器

        self.open()

        # 点击验证按钮

        button = self.get_geetest_button()

        button.click()

        # 保存的图片名字

        bg_filename = 'bg.jpg'

        fullbg_filename = 'fullbg.jpg'

        # 获取图片

        bg_location_list, fullbg_location_list = self.get_images(bg_filename, fullbg_filename)

        # 根据位置对图片进行合并还原

        bg_img = self.get_merge_image(bg_filename, bg_location_list)

        fullbg_img = self.get_merge_image(fullbg_filename, fullbg_location_list)

        # 点按呼出缺口

        slider = self.get_slider()

        # 获取缺口位置

        gap = self.get_gap(fullbg_img, bg_img)

        print('缺口位置', gap)

        gap -= BORDER

        # # # # 点按呼出缺口

        track = self.get_track(gap)

        time.sleep(1)

        self.move_to_gap(slider, track)

        time.sleep(10)

if __name__ == '__main__':

    # login()

    crack = CrackGeetest()

    crack.crack()

相关文章

网友评论

      本文标题:2019-05-18

      本文链接:https://www.haomeiwen.com/subject/vxztzqtx.html