python怎样识别验证码

来源:互联网 发布:淘宝html 编辑:程序博客网 时间:2024/04/30 03:06

小编最近想做个自动巡检网页的小工具。发现简单的操作只需要用到cPAMIE就可实现。但有个页面登陆认证时需要用到验证码。验证码图片如下:

python识别验证码
这就需要用到验证码识别技术。查了很多资料,发现网上的文章都是需要把图片存成二进制,工作量大。后来找到一个python OCR软件pytesser。只需要简单的一句代码就可以实现上面这种验证码的识别。但是这个插件并不支持所有的验证码识别,如果图片高低不等的话是无法实别出来的。太复杂的验证码也没办法实别。但对于这种规则的验证码还是可行的。(对于我的需求还是满足的,偷笑一个)
代码如下:
im = Image.open(‘temp1.tif‘).convert(type)
textcode = image_to_string(im)
只需要这两句就能得到你想要的。

验证码识别过程中还有一个比较头痛的问题,就是取得当前验证码图片。现在的验证码一般都是动态生成在服务器的内存里。每次调用都得到一个新的验证码。所以通过验证码生成地址是无法取得当前会话中的验证码图片的。
做了很多实验如:
urllib.urlretrieve(‘http://XXX/image.jsp‘,‘temp1.tif‘)
虽然可以取到验证码图片,但是已不是当前会话中的验证码了,就算你解出来了也用不上。
如果有哪位朋友找到了解决办法,可以告诉我,不胜感激。

最后只能通过屏幕截取的方式来取得验证码图片。
1.先把当前活动的IE页面截屏保存下来。
2.在保存下来的图片中找到验证码的坐标位置。
3.保存验证码图片。

实现如下:
import os
import ctypes
from PIL import ImageGrab
from PIL import Image,ImageDraw 
from pytesser import *
import urllib
class RECT(ctypes.Structure):
    _fields_ = [(‘left‘, ctypes.c_long),
                (‘top‘, ctypes.c_long),
                (‘right‘, ctypes.c_long),
                (‘bottom‘, ctypes.c_long)]
    def __str__(self):
        return str((self.left, self.top, self.right, self.bottom))

class Img2Code:
    def __init__(self,tempJpgFile,tempTifFile,x1,y1,x2,y2):
        self.JpgFile = tempJpgFile
        self.TifFile = tempTifFile
        self.x1 = x1
        self.y1 = y1
        self.x2 = x2
        self.y2 = y2
    def capture(self,hwnd,tempdir):
        """
        对窗口截图,传入窗口句柄及保存位置,生成的文件为temp.jpg
        """
        rect = RECT()
        ctypes.windll.user32.GetWindowRect(hwnd,ctypes.byref(rect))
        rangle = (rect.left+2,rect.top+2,rect.right-2,rect.bottom-2)
        im = ImageGrab.grab(rangle)
        jpgname = self.JpgFile + ".jpg"
        Xini1 = os.path.join(tempdir,jpgname)
        Xini111 = Xini1.replace("[url=file://]","/[/url]")
        im.save(Xini111) 
        return
    def test1(self):
        ieHWND1 = ctypes.windll.user32.FindWindowA("IEFrame",None)#获取IE的句柄
#        print ieHWND1
        getdir = os.getcwd()
        HWND_TOP = 0
        SWP_NOMOVE= 2
        SWP_NOSIZE= 1
        SWP_SHOWWINDOW= 64
        ctypes.windll.user32.SetWindowPos(ieHWND1, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW)
        import time
        time.sleep(5)#延迟5秒
        self.capture(ieHWND1,getdir)
        return True
    def getImg2Code2(self,type):
        _fname = self.JpgFile+‘.jpg‘
        im = Image.open(_fname)
#        im = Image.open(_fname).convert(type)
    #    im1=im.crop((163,261,210,276))
        im1 = im.crop((self.x1,self.y1,self.x2,self.y2))
        fn = self.TifFile + ‘1.jpg‘
        im1.save(fn)
        textcode = image_to_string(im1)
        return textcode
    def getImg2Code(self,type):
        urllib.urlretrieve(‘http://xxxx/view/login/image.jsp‘,‘temp1.tif‘)
        im = Image.open(‘temp1.tif‘).convert(type)
        textcode = image_to_string(im)
        return textcode
关于坐标定位问题,可以写成配置文件之类的,但于更改,多试几次就可以找到了。
im1=im.crop((163,261,210,276))

但这种方法也有它的缺点,就是写好的程序只能在你的机上运行,如果打包成EXE的时候放到别的电脑上,需要重新计算坐标。具体的方法可以通过查看临时的图片文件来测试。多试几次。

本文摘自:www.zhima365.com