潭州课堂25班:Ph201805201 爬虫基础 第十课 图像处理- 极验验证码 (课堂笔记)

用 python 的  selenium  访问  https://www.huxiu.com/

自动通过验证码

# -*- coding: utf-8 -*-
# 斌彬电脑
# @Time : 2018/9/11 0011 4:38
'''
滑动验证码之  极验 验证码
https://www.huxiu.com/
'''

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains     # 动作链
import requests,re
from PIL import Image
from io import BytesIO      # 不写入磁盘,显示图片文件
import time, random

class JiYan():
    def __init__(self):
        # 浏览器参数
        options = Options()
        options.add_argument('--window-size=1366,768')
        self.dri = webdriver.Chrome(chrome_options=options)
        self.btn = WebDriverWait(self.dri, 10)

    # 访问页面
    def to_request(self):
        self.dri.get('https://www.huxiu.com/')
        # 找到登录按钮
        self.btn.until(EC.presence_of_element_located((By.XPATH, '//a[@class="js-login"]'))).click()
        # 找到输入框
        f = self.btn.until(EC.presence_of_element_located((By.XPATH, '//input[@id="sms_username"]')))
        # 输入内容
        f.send_keys('13605838837')

    # 获取验证码图片
    def get_img(self):
        #
        # 没有缺陷的图片
        g_img = self.dri.find_elements_by_xpath( '//div[@class="gt_cut_fullbg gt_show"]/div')
        # print(len(g_img))
        # 拿到图片的 url 和 偏移量
        style_list = [i.get_attribute('style') for i in g_img]
        # print(style_list)
        # 匹配到连接 因为每个连接是一样的,所以只要匹配到一个就行
        # 验证码的图片连接
        img_url = re.search(r'url("(.*?)");',style_list[0]).group(1)
        # print(img_url)
        # 图片二进制的值
        img_con = requests.get(img_url).content
        #  得到完整的验证码
        get_po = self.get_img2(style_list, img_con)
        # get_po.show()                   #   显示出来


        # 有缺陷的图片
        bg_g_img = self.dri.find_elements_by_xpath( '//div[@class="gt_cut_bg gt_show"]/div')
        # 拿到图片的 url 和 偏移量
        style_list = [i.get_attribute('style') for i in bg_g_img]
        # 匹配到连接 因为每个连接是一样的,所以只要匹配到一个就行
        # 验证码的图片连接
        img_url2 = re.search(r'url("(.*?)");',style_list[0]).group(1)
        # print(img_url)
        # 图片二进制的值
        img_con = requests.get(img_url2).content
        #  得到完整的验证码
        bg_get_po = self.get_img2(style_list, img_con)
        # bg_get_po.show()
        # 调用比较函数
        return self.contrast(get_po, bg_get_po)

    # 拼接验证码
    def get_img2(self,style_list,image):
        #  拿到偏移量
        #                                          ?可能有的时候没有
        po_list = [re.findall(r'background-position: -(.*?)px -?(.*?)px;', i) for i in style_list]
        # print(po_list)
        # 新建图片
        im_new = Image.new('RGB',(260,116))
        im = Image.open(BytesIO(image))
        up = 0
        dn = 0
        for i in po_list[:26]:      #  前26个,上半部分
            # print(i)
            #     左上角x,   y   右上角 x,   y
            cro = im.crop((int(i[0][0]),58, int(i[0][0])+10,116))           # 拿到偏移量,进行裁剪
            #   up 为粘贴位置
            im_new.paste(cro,(up,0))                          #  把裁剪下的图片粘贴到新建空白图片上,得到张新图
            up += 10                        # 每张小图的宽度是10px,

        for i in po_list[26:]:      #  后26个,下半部分
            # print(i)
            #     左上角x,   y   右上角 x,   y
            cro = im.crop((int(i[0][0]),0, int(i[0][0])+10,58))           # 拿到偏移量,进行裁剪
            #   up 为粘贴位置
            im_new.paste(cro,(dn,58))                          #  把裁剪下的图片粘贴到新建空白图片上,得到张新图
            dn += 10                        # 每张小图的宽度是10px,

        return im_new

    #   有缺陷的图片与无缺陷的图片对比,得到距离值
    def  contrast(self,cut,no_cut):
        def contrast_pi(px1,px2):
            for i in range(3):      #  像素点的差达到指定值(RGB),
                if abs(px1[i] - px2[i]) > 50:
                    return False

        for i in range(260):        # 宽度像素点
            for j in range(116):    # 高度像素点
                px1 = cut.getpixel((i,j))   # 取得第一张每个像素点的值
                px2 = no_cut.getpixel((i,j))   # 取得第二张每个像素点的值
                if contrast_pi(px1,px2) is False :    #   比较两张图片同一位置的像素点的值
                    # 如果找到两张图片的像素差值达到要求,就返回 i ,得到滑动的距离
                    return  i

    # 控制浏览器滑动
    def slide(self, distance):
        # 可见滑动
        dis = self.btn.until(EC.visibility_of_element_located((By.XPATH, '//div[@class="gt_slider_knob gt_show"]')))
        # 点出不放
        ActionChains(self.dri).click_and_hold(dis).perform()
        time.sleep(0.5)
        # 移动     传入距离的值,X,Y
        # ActionChains(self.dri).move_by_offset(distance-5, 0).perform()
        for i in self.track(distance-5):
            ActionChains(self.dri).move_by_offset(i, 0).perform()
        time.sleep(0.6)
        # 释放-
        ActionChains(self.dri).release(dis).perform()

    # 模拟人拖动
    def track(self,distance):
        t = 0.2                   # 时间
        current = 0                 # 当前
        mid = distance * 3/5
        speed = 0                   # 速度
        move_distance_list = []
        while current < distance:   #  当前小于距离时,
            if current < mid:       # 如果当前小于中间距离
                a = 2               #  加速度
            else:a = -5
            move_distance = speed*t+0.5*a*t*t
            move_distance_list.append(round( move_distance ))       #  整数添加进列表
            speed += (a*t)
            current += move_distance

        offset = sum(move_distance_list) - distance
        if offset > 0:
            move_distance_list.extend([-1]*offset)
        elif offset < 0:
            move_distance_list.extend( [1]*abs(offset) )
        #                         - 左移,          0 停止       右移
        move_distance_list.extend([-1,-1,-1,-1,-1,0,0,0,1,1,1,1,1,1,0,0,0,0,0,-1.-1.-1.])
        return move_distance_list


    # 让类可以像函数一样调用 h() 执行类
    #def __call__(self, *args, **kwargs):

h = JiYan()
h.to_request()
time.sleep(2)
distance = h.get_img()
h.slide(distance)

  

 在 linux 下

python 的文字识别库(视觉系统)

进行安装 

(视觉系统)要与 pyghon 交互,所以还要安装pytesseract

d

原文地址:https://www.cnblogs.com/gdwz922/p/9627588.html