zoukankan      html  css  js  c++  java
  • 滑动验证

    虎x网

    import time
    import re
    import requests
    from io import BytesIO
    from PIL import Image
    import random
    from selenium import webdriver
    from selenium.common.exceptions import TimeoutException
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.action_chains import ActionChains
    
    
    class Geek_Huxiu(object):
    
        def __init__(self):
            self.driver = webdriver.Chrome(r'F:Python视屏10爬虫包chromedriver_win32chromedriver.exe')
            self.driver.set_window_size(1366, 768)
    
        def run(self):
            self.driver.get("https://www.huxiu.com/")  # 打开浏览器
    
            WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.XPATH, '//*[@class="js-register"]')))
            login_btn = self.driver.find_element_by_xpath('//*[@class="js-register"]')
            login_btn.click()
    
            WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable((By.XPATH, '//div[@class="gt_slider_knob gt_show"]')))
    
            # 模拟拖动
            self.analog_drag()
    
        def analog_drag(self):
            # 鼠标移动到拖动按钮,显示出拖动图片
            element = self.driver.find_element_by_xpath('//div[@class="gt_slider_knob gt_show"]')
            ActionChains(self.driver).move_to_element(element).perform()
            time.sleep(3)
    
            # 刷新一下极验证图片
            element = self.driver.find_element_by_xpath('//a[@class="gt_refresh_button"]')
            element.click()
            time.sleep(1)
    
            # 获取图片地址和位置坐标列表
            cut_image_url, cut_location = self.get_image_url('//div[@class="gt_cut_bg_slice"]')
            full_image_url, full_location = self.get_image_url('//div[@class="gt_cut_fullbg_slice"]')
            # print(cut_image_url)
            # print(cut_location)
    
            # 根据坐标拼接图片
            cut_image = self.splicing_image(cut_image_url, cut_location)
            full_image = self.splicing_image(full_image_url, full_location)
    
            # 将图片存储到本地
            cut_image.save("cut.jpg")
            full_image.save("full.jpg")
    
            # 根据两个图片计算距离
            distance = self.get_distance(cut_image, full_image)
    
            # 开始移动
            self.start_move(distance)
    
            # 如果出现error
            try:
                WebDriverWait(self.driver, 5, 0.5).until(
                    EC.element_to_be_clickable((By.XPATH, '//div[@class="gt_ajax_tip gt_error"]')))
                print("验证失败")
                return
            except TimeoutException as e:
                pass
    
            # 判断是否验证成功
            try:
                WebDriverWait(self.driver, 10, 0.5).until(
                    EC.element_to_be_clickable((By.XPATH, '//div[@class="gt_ajax_tip gt_success"]')))
            except TimeoutException:
                print("again times")
                time.sleep(3)
                # 失败后递归执行拖动
                self.analog_drag()
            else:
                print("验证成功")
    
        def get_image_url(self, xpath):
            link = re.compile('background-image: url("(.*?)"); background-position: (.*?)px (.*?)px;')  # 为了获取url  x坐标  y坐标
            elements = self.driver.find_elements_by_xpath(xpath)  # 获取所有图片的标签
            image_url = None
    
            location = list()  # 创建空列表
    
            for element in elements:
                style = element.get_attribute('style')
                groups = link.search(style)  # 正则匹配  style中内容
    
                url = groups[1]    # 获取url
                x_pos = groups[2]  # 获取x
                y_pos = groups[3]  # 获取y
                location.append((int(x_pos), int(y_pos)))  # (x,y) 坐标  t添加到列表
                if not image_url:  # 不存在 image_url时候
                    image_url = url  # image_url = url
            return image_url, location  # 返回一个图片url   坐标列表
    
        def splicing_image(self, image_url, location):
            res = requests.get(image_url)
            file = BytesIO(res.content)
            img = Image.open(file)
            image_upper = []
            image_down = []
            for pos in location:
                if pos[1] == 0:
                    # y值为0的坐标  属于图片上半部分,高度58
                    image_upper.append(img.crop((abs(pos[0]), 0, abs(pos[0]) + 10, 58)))
                else:
                    # y值为58的坐标 属于图片下半部分,高度58
                    image_down.append(img.crop((abs(pos[0]), 58, abs(pos[0]) + 10, img.height)))
            # 画布的x轴偏移量
            x_offset = 0
            # 创建一张画布
            # print(image_upper)
            # print('- -' * 30)
            # print(image_down)
            new_img = Image.new("RGB", (260, img.height))
            for img in image_upper:
                new_img.paste(img, (x_offset, 58))
                print(img)
                x_offset += img.width
    
            x_offset = 0
            for img in image_down:
                new_img.paste(img, (x_offset, 0))
                x_offset += img.width
    
            return new_img
    
        def get_distance(self, cut_image, full_image):
    
            # print(cut_image.size)
            threshold = 50
            for i in range(0, cut_image.size[0]):
                for j in range(0, cut_image.size[1]):
                    pixel1 = cut_image.getpixel((i, j))
                    pixel2 = full_image.getpixel((i, j))
                    res_R = abs(pixel1[0] - pixel2[0])  # 计算RGB差
                    res_G = abs(pixel1[1] - pixel2[1])  # 计算RGB差
                    res_B = abs(pixel1[2] - pixel2[2])  # 计算RGB差
    
                    if res_R > threshold and res_G > threshold and res_B > threshold:
                        return i  # 需要移动的距离
    
        # 移动滑块
        def start_move(self, distance):
            element = self.driver.find_element_by_xpath('//div[@class="gt_slider_knob gt_show"]')
    
            # 使用滑块的一半进行偏移设置
            distance -= element.size.get('width') / 2
            distance += 15
    
            # 按下鼠标左键
            ActionChains(self.driver).click_and_hold(element).perform()
            time.sleep(0.5)
            while distance > 0:
                if distance > 20:
                    # 如果距离大于20,就让他移动快一点
                    span = random.randint(5, 8)
                else:
                    # 快到缺口了,就移动慢一点
                    span = random.randint(2, 3)
                ActionChains(self.driver).move_by_offset(span, 0).perform()
                distance -= span
                time.sleep(random.randint(10, 60) / 100)
    
            ActionChains(self.driver).move_by_offset(distance, 1).perform()
            ActionChains(self.driver).release(on_element=element).perform()
    
    
    if __name__ == '__main__':
        h = Geek_Huxiu()
        h.run()
  • 相关阅读:
    突出展示案例
    下拉菜单案例
    推送人群的选择【技术篇】
    Couchbase 中的分布式储存
    开始了大概三四天的Rails学习之路
    分层架构与公司组织
    极光推送助推视频App,打造最活跃手机新媒体平台
    极光推送CTO黄鑫:技术人员要建立自己的知识图谱
    Android SDK教程
    Android消息推送 SDK 集成指南
  • 原文地址:https://www.cnblogs.com/clbao/p/10845818.html
Copyright © 2011-2022 走看看