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()
  • 相关阅读:
    4星|《态度》:吴军博士写给读高中和大学的女儿们的信
    2星|宇见《洞察力:让营销从此直指人心》:营销讲师自创的理论,逻辑较差,洞察力不用提
    1星|《社群X平台》:没有实际工作经验的职业写手拼凑而成
    3星|《一课经济学》:70年前的经济学思想普及读物,现在看还不过时
    3.5星|《戴维斯王朝》:业绩媲美巴菲特的投资人家族的故事
    3.5星|《行为设计学:零成本改变》:明确的、可操作的、短期的、可以引起情感共鸣的目标,更有助于个人或组织做出改变
    1星|《讲法:从说教到赋能》:用伪科学概念说理,对建构主义的解释与理解比较牵强
    2星|《谁站在马云背后》:总裁律师的职责、素养、趋势。信息浓度较低,案例偏老旧肤浅
    2星|简七《巴比伦富翁新解》:浅显的理财原则,目测作者长于理财培训而不是理财实战
    使用 Visual Studio 部署 .NET Core 应用 ——.Net Core 部署到Ubuntu 16.04
  • 原文地址:https://www.cnblogs.com/clbao/p/10845818.html
Copyright © 2011-2022 走看看