小编最近想做个自动巡检网页的小工具。发现简单的操作只需要用到cPAMIE就可实现。但有个页面登陆认证时需要用到验证码。验证码图片如下:
这就需要用到验证码识别技术。查了很多资料,发现网上的文章都是需要把图片存成二进制,工作量大。后来找到一个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