PIL+selenium+Tesseract 实现验证码的登录(山东大学图书馆)

  • PIL安装:(vscode+python)
pip install pillow

PIL 是一个python用的图形处理的库 非常实用(相当于opencv 有一点)

#PIL 是python中用来处理图片的一个库
from PIL  import Image, ImageDraw, ImageFont, ImageFilter
import random

# 随机字母:
def rndChar():
    return chr(random.randint(65, 90))

# 随机颜色1:
def rndColor():
    return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255))

# 随机颜色2:
def rndColor2():
    return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))

# 240 x 60:
width = 60 * 4
height = 60
#创建一个image
image = Image.new('RGB', (width, height), (255, 255, 255))
# 创建Font对象:
font = ImageFont.truetype(r'D:\softwareInstall\python\Lib\site-packages\matplotlib\mpl-data\fonts\ttf\cmb10.ttf', 36)
# 创建Draw对象,有了draw才可以在图片上画图:
draw = ImageDraw.Draw(image)
# 填充每个像素:
for x in range(width):
    for y in range(height):
        draw.point((x, y), fill=rndColor())
# 输出文字:
for t in range(4):
    draw.text((60 * t + 10, 10), rndChar(), font=font, fill=rndColor2())
# 模糊:
image = image.filter(ImageFilter.BLUR)
image.save('code.jpg', 'jpeg')
  • selenium的安装使用:

selenium 是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样

官方文档:https://python-selenium-zh.readthedocs.io/zh_CN/latest/1.%E5%AE%89%E8%A3%85/

获取山东大学图书馆的验证码php 图片!!

  •  中途遇到的问题:

img标签中的src为php文件

<img src="imgcode.php" alt="看不清楚,换一张" style="cursor: pointer;" onClick="javascript: newgdcode(this,this.src);" />

   一般情况下,src属性值应该为某张图片的路径,而这个例子中,src值为php文件,这是问什么?

首先来看看,这个imagecode.php 文件。imagecode.php 文件的结果是输出一张图片到浏览器中(单独执行imagecode.php 文件,就可以知道结果),我们可以理解为这张图片的路径就是imagecode.php,所以把“imagecode.php”作为src的值是没有问题的。

注意:这里src="imgcode.php",并不是包含"imgcode.php"文件, 运行到这里会去执行imgcode.php文件,imgCode.php产生一副图片,就可以了。

   所以,问题的关键是这个php文件的结果就是一张图片,所以它可以作为img标签中src的值。

  •  代码实现:
#爬取山东大学图书馆的登录  (验证码)
# 网址:http://58.194.172.34/reader/login.php

from selenium import webdriver
import time
driver = webdriver.Chrome("C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe")
driver.get("http://58.194.172.34/reader/login.php")

driver.find_element_by_name('number').send_keys("201700301296")
driver.find_element_by_name('passwd').send_keys("687299")
# 点击登录按钮
# driver.find_element_by_css_selector('input.btn btn-danger').click()
#获取验证码img 里面的src里面的php图片(php图片需要用网址打开!)
php_img=driver.find_element_by_id('regimg').get_attribute('src')
driver_img=webdriver.Chrome()
driver.get(php_img)
#接下来在获取到的 验证码页面截图即可
# 点击登录按钮
login_button = driver.find_element_by_xpath("//input[@type='submit']").click()
time.sleep(3)
  •  实现验证码登录(自动)

参考https://blog.csdn.net/MrLevo520/article/details/51901579

其中出现了很多报错问题,在安装pytesser中出现了很多问题:

首先PIL模块的安装,然后才能安装pytesser 模块:

下载后得到 “pytesser_v0.0.1.zip”,是一个压缩文件,使用方法: 

1、在 “D:/softwareInstall/python/Lib/site-packages“ 路径下新建一个文件夹,命名 “pytesser” 。把 “pytesser_v0.0.1.zip” 里的文件解压到该目录:

2、将 “pytesser.py” 改名为 “__init__.py”。

3、打开 “__init__.py” 文件,将 “tesseract_exe_name” 变量的值改为 “‘D:/softwareInstall/python/Lib/site-packages/pytesser/tesseract’”(原值为 “‘tesseract’”)。

4、pytesser 模块依赖于 PIL 模块,如果是按照上面的方法安装 PIL 的话,需要把 “init.py” 文件里的 “import Image” 改成 “from PIL import Image” 。 

5.因为现在使用的python3 所以在pytesser的XXX.py文件中会有出错的现象:

__init__.py:

 

 util.py:(file函数改成open函数)

其次安装好的pytesser要在环境变量里面添加才可以好好使用不报错:

代码示例:(识别验证码 但是由于pytesser的识别效果比较差,只适合没有干扰的数字的识别,像是:

 ,而这种就识别不出来了!

#爬取山东大学图书馆的登录  (验证码)
# 网址:http://58.194.172.34/reader/login.php

from selenium import webdriver
import time
from PIL import Image,ImageEnhance
import pytesser
import os

driver = webdriver.Chrome("C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe")
driver.get("http://58.194.172.34/reader/login.php")

driver.find_element_by_name('number').send_keys("*********")
driver.find_element_by_name('passwd').send_keys("********")
# #获取验证码img 里面的src里面的php图片(php图片需要用网址打开!)
# php_img=driver.find_element_by_id('regimg').get_attribute('src')
# driver_img=webdriver.Chrome()
# driver.get(php_img)



#-------------------对验证码进行区域截图-----------------
driver.get_screenshot_as_file('image1.png')#比较好理解
im =Image.open('image1.png')
box = (219,260,262,285)  #设置要裁剪的区域
region = im.crop(box)     #此时,region是一个新的图像对象。
#region.show()#显示的话就会被占用,所以要注释掉
region.save("image_code.png")
im=Image.open("image_code.png")
imgry = im.convert('L')#图像加强,二值化
sharpness =ImageEnhance.Contrast(imgry)#对比度增强
sharp_img = sharpness.enhance(2.0)
sharp_img.save("image_code.jpg")
im=Image.open("image_code.jpg")

code= pytesser.image_to_string(im).strip()#code即为识别出的图片数字str类型
print (code)
time.sleep(3)
# 输入验证码
driver.find_element_by_name('code').send_keys(code)

login_button = driver.find_element_by_xpath("//input[@type='submit']").click()
time.sleep(3)
# 退出浏览器
driver.quit()

 实现简单的 图片验证码的识别

import pytesseract
from PIL import Image
import os
from collections import defaultdict
 
 
#获取图片中像素点数量最多的像素,一般为背景图片
def get_threshold(image):
    '''
    defaultdict()在dict()的基础上添加了一个missing(key)的方法,
    在调用一个不存在的key的时候,defaultdict函数会调用“missing”,
    返回一个int,set,list,dict对应的默认数值,不会出现keyerror的情况。
    '''
    pixel_dict=defaultdict(int)
    #像素及像素出现次数的字典
    rows,cols=image.size
    for i in range(rows):
        for j in range(cols):
            pixel=image.getpixel((i,j))#检索指定坐标点的像素的RGB颜色值
            pixel_dict[pixel]+=1
    count_max=max(pixel_dict.values())#获取像素出现最多的次数
    pixel_dict_reverse={v:k for  k,v in pixel_dict.items()}# items()函数以列表返回可遍历的(键, 值) 元组数组   
    threshold=pixel_dict_reverse[count_max]#获取出现次数最多的像素点
    return threshold
 
#按照阈值进行二值化处理
#threshold:像素阈值
def get_bin_table(threshold):
    #获取灰度转二值的映射table
    table=[]
    for i in range(256):
        rate=0.1#在threshold的适当范围内进行处理
        if threshold*(1-rate)<=i<=threshold*(1+rate):
            table.append(1)
        else:
            table.append(0)
    return table
 
#去掉二值化处理后的图片中的噪声点
def cut_noise(image):
    rows,cols=image.size 
    change_pos=[]#记录噪声点的位置
    #遍历图片中的每个点,除掉边缘
    for i in range(1,rows-1):
        for j in range(1,cols-1):
            #pixel_set用来记录该点附近的黑色像素的数量
            pixel_set=[]
            #取该点的领域为该点附近的黑色像素的数量
            for m in range(i-1,i+2):
                for n in range(j-1,j+2):
                    if image.getpixel((m,n))!=1:#1为白色,0为黑色
                        pixel_set.append(image.getpixel((m,n)))
                        
            #如果该位置的九宫格内的黑色数量小于等于4,则判断为噪音
            if len(pixel_set)<=4:
                change_pos.append((i,j)) 
    #对相应位置进行像素修改,将噪声处的像素置为1(白色)
    for pos in change_pos:
        image.putpixel(pos,1)           
    return image #返回修改后的图片
 
#识别图片中的数字加字母
#传入参数为图片路径,返回结果为识别结果
def OCR_Img(img_path):
    image=Image.open(img_path)#打开图片文件
    imgry=image.convert('L')#转化为灰度图
    
    #获取图片中的出现次数最多的像素即为该图片的背景
    max_pixel=get_threshold(imgry)
    
    #将图片进行二值化处理,阈值为图片背景颜色
    table=get_bin_table(threshold=max_pixel)
    out=imgry.point(table,'1') #???
    
    #去掉图片中的噪声(孤立点)
    out=cut_noise(out)
    
    #保存图片
#     out.save('E://figures/img_gray.jpg')
    #仅识别图片中的数字
#     text=pytesseract.image_to_string(out,config='digits')
    #识别图片中的数字和字母
    text=pytesseract.image_to_string(out)
    
    #去掉识别结果中的特殊字符
    exclude_char_list='.:\\|\'\"?![],()~@#$%^&*_+-={};<>/¥‘ '
    text=''.join([x for x in text if x not in exclude_char_list])
    return text
 
       
def main():
    #识别指定文件目录下的图片
    #图片存放目录img
    dir='./'
    correct_count=0 #图片总数
    total_count=0 #识别正确的图片数量
    #遍历img下的png,jpg文件
    for file in os.listdir(dir):
        if file.endswith('.png') or file.endswith('.jpg'):
            image_path='%s/%s'%(dir,file)#图片路径
            
            anwser=file.split('.')[0]#图片名称,即验证码的正确文字
            recognizition=OCR_Img(image_path)#图片识别的文字结果
            
            print((anwser,recognizition))
            if recognizition==anwser:
                correct_count+=1
            total_count+=1
    print('Total count:%d,correct:%d.'%(total_count,correct_count))
 
 
main()
 

<img src="imgcode.php" alt="看不清楚,换一张" style="cursor: pointer;" onClick="javascript: newgdcode(this,this.src);" />

   一般情况下,src属性值应该为某张图片的路径,而这个例子中,src值为php文件,这是问什么?

首先来看看,这个imagecode.php 文件。imagecode.php 文件的结果是输出一张图片到浏览器中(单独执行imagecode.php 文件,就可以知道结果),我们可以理解为这张图片的路径就是imagecode.php,所以把“imagecode.php”作为src的值是没有问题的。

注意:这里src="imgcode.php",并不是包含"imgcode.php"文件, 运行到这里会去执行imgcode.php文件,imgCode.php产生一副图片,就可以了。

   所以,问题的关键是这个php文件的结果就是一张图片,所以它可以作为img标签中src的值。

猜你喜欢

转载自www.cnblogs.com/kekexxr/p/11566226.html