美文网首页
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