爬虫Python验证码识别入门
作者:李国宝 发布时间:2021-01-31 15:31:19
标签:爬虫,Python,验证码
目录
爬虫Python验证码识别
1、批量下载验证码图片
2、识别代码看看效果
3、折腾降噪、去干扰
爬虫Python验证码识别
前言:
二值化、普通降噪、8邻域降噪
tesseract、tesserocr、PIL
参考文献--代码地址:https://github.com/liguobao/python-verify-code-ocr
1、批量下载验证码图片
import shutil
import requests
from loguru import logger
for i in range(100):
url = 'http://xxxx/create/validate/image'
response = requests.get(url, stream=True)
with open(f'./imgs/{i}.png', 'wb') as out_file:
response.raw.decode_content = True
shutil.copyfileobj(response.raw, out_file)
logger.info(f"download {i}.png successfully.")
del response
2、识别代码看看效果
from PIL import Image
import tesserocr
img = Image.open("./imgs/98.png")
img.show()
img_l = img.convert("L")# 灰阶图
img_l.show()
verify_code1 = tesserocr.image_to_text(img)
verify_code2 = tesserocr.image_to_text(img_l)
print(f"verify_code1:{verify_code1}")
print(f"verify_code2:{verify_code2}")
毫无疑问,无论是原图还是灰阶图,一无所有。
3、折腾降噪、去干扰
Python图片验证码降噪 - 8邻域降噪
from PIL import Image
# https://www.cnblogs.com/jhao/p/10345853.html Python图片验证码降噪 — 8邻域降噪
def noise_remove_pil(image_name, k):
"""
8邻域降噪
Args:
image_name: 图片文件命名
k: 判断阈值
Returns:
"""
def calculate_noise_count(img_obj, w, h):
"""
计算邻域非白色的个数
Args:
img_obj: img obj
w: width
h: height
Returns:
count (int)
"""
count = 0
width, height = img_obj.size
for _w_ in [w - 1, w, w + 1]:
for _h_ in [h - 1, h, h + 1]:
if _w_ > width - 1:
continue
if _h_ > height - 1:
continue
if _w_ == w and _h_ == h:
continue
if img_obj.getpixel((_w_, _h_)) < 230: # 这里因为是灰度图像,设置小于230为非白色
count += 1
return count
img = Image.open(image_name)
# 灰度
gray_img = img.convert('L')
w, h = gray_img.size
for _w in range(w):
for _h in range(h):
if _w == 0 or _h == 0:
gray_img.putpixel((_w, _h), 255)
continue
# 计算邻域非白色的个数
pixel = gray_img.getpixel((_w, _h))
if pixel == 255:
continue
if calculate_noise_count(gray_img, _w, _h) < k:
gray_img.putpixel((_w, _h), 255)
return gray_img
if __name__ == '__main__':
image = noise_remove_pil("./imgs/1.png", 4)
image.show()
看下图效果:
这样差不多了,不过还可以提升
提升新思路:
这边的干扰线是从某个点发出来的红色线条,
其实我只需要把红色的像素点都干掉,这个线条也会被去掉。
from PIL import Image
import tesserocr
img = Image.open("./imgs/98.png")
img.show()
# 尝试去掉红像素点
w, h = img.size
for _w in range(w):
for _h in range(h):
o_pixel = img.getpixel((_w, _h))
if o_pixel == (255, 0, 0):
img.putpixel((_w, _h), (255, 255, 255))
img.show()
img_l = img.convert("L")
# img_l.show()
verify_code1 = tesserocr.image_to_text(img)
verify_code2 = tesserocr.image_to_text(img_l)
print(f"verify_code1:{verify_code1}")
print(f"verify_code2:{verify_code2}")
看起来OK,上面还有零星的蓝色像素掉,也可以用同样的方法一起去掉。
甚至OCR都直接出效果了
好了,完结撒花。
不过,后面发现,有些红色线段和蓝色点,是和验证码重合的。
这个时候,如果直接填成白色,就容易把字母切开,导致识别效果变差。
当前点是红色或者蓝色,判断周围点是不是超过两个像素点是黑色。
是,填充为黑色。
否,填充成白色。
最终完整代码:
from PIL import Image
import tesserocr
from loguru import logger
class VerfyCodeOCR():
def __init__(self) -> None:
pass
def ocr(self, img):
""" 验证码OCR
Args:
img (img): imgObject/imgPath
Returns:
[string]: 识别结果
"""
img_obj = Image.open(img) if type(img) == str else img
self._remove_pil(img_obj)
verify_code = tesserocr.image_to_text(img_obj)
return verify_code.replace("\n", "").strip()
def _get_p_black_count(self, img: Image, _w: int, _h: int):
""" 获取当前位置周围像素点中黑色元素的个数
Args:
img (img): 图像信息
_w (int): w坐标
_h (int): h坐标
Returns:
int: 个数
"""
w, h = img.size
p_round_items = []
# 超过了横纵坐标
if _w == 0 or _w == w-1 or 0 == _h or _h == h-1:
return 0
p_round_items = [img.getpixel(
(_w, _h-1)), img.getpixel((_w, _h+1)), img.getpixel((_w-1, _h)), img.getpixel((_w+1, _h))]
p_black_count = 0
for p_item in p_round_items:
if p_item == (0, 0, 0):
p_black_count = p_black_count+1
return p_black_count
def _remove_pil(self, img: Image):
"""清理干扰识别的线条和噪点
Args:
img (img): 图像对象
Returns:
[img]: 被清理过的图像对象
"""
w, h = img.size
for _w in range(w):
for _h in range(h):
o_pixel = img.getpixel((_w, _h))
# 当前像素点是红色(线段) 或者 绿色(噪点)
if o_pixel == (255, 0, 0) or o_pixel == (0, 0, 255):
# 周围黑色数量大于2,则把当前像素点填成黑色;否则用白色覆盖
p_black_count = self._get_p_black_count(img, _w, _h)
if p_black_count >= 2:
img.putpixel((_w, _h), (0, 0, 0))
else:
img.putpixel((_w, _h), (255, 255, 255))
logger.info(f"_remove_pil finish.")
# img.show()
return img
if __name__ == '__main__':
verfyCodeOCR = VerfyCodeOCR()
img_path = "./imgs/51.png"
img= Image.open(img_path)
img.show()
ocr_result = verfyCodeOCR.ocr(img)
img.show()
logger.info(ocr_result)
来源:https://www.cnblogs.com/liguobao/p/15111849.html


猜你喜欢
- 本文实例讲述了Python上下文管理器类和上下文管理器装饰器contextmanager用法。分享给大家供大家参考,具体如下:一. 什么是上
- 下面看下pandas中字符串类处理函数吧,内容如下所示:1.英文字母大小写转换及填充s = pd.Series(['lower
- 如何做一个只搜索本网站的引擎? 用下面两个文件即可实现:searchfiles.html &l
- 导语:使用 python-plotly 模块来进行压测数据的绘制,并且生成静态 html 页面结果展示。不少小伙伴在开发过程中都有对模块进行
- 之前需要做一些目标检测的训练,需要自己采集一些数据集,写了一个小demo来实现图片的采集使用方法:指定name的名称,name为分类的标签按
- 如何根据二维数组中的某一行或者某一列排序?假设data是一个numpy.array类型的二维数组,可以利用numpy中的argsort函数进
- 废话不多说,直接给大家上干货了,写的不好欢迎提出意见。具体代码如下所示:function hiddenPass(event){ var pa
- 查看数据库show databases;创建数据库create DATABASE 数据库名称create DATABASE database
- 什么是MyCAT一个彻底开源的,面向企业应用开发的大数据库集群支持事务、ACID、可以替代MySQL的加强版数据库一个可以视为MySQL集群
- 禁用默认事务为了确保数据一致性,GORM 会在事务里执行写入操作(创建、更新、删除)。如果没有这方面的要求,您可以在初始化时禁用它,这将获得
- 【译者的话】我们曾经在《透视色轮》一文中探讨过色轮的构成及作用,但你可能更多的只是将其作为了解颜色关系的一个工具,却不一定将其作为实际设计中
- 众所周知tensorflow造势虽大却很难用,因此推荐使用Keras,它缺省是基于tensorflow的,但通过修改keras.json也可
- Node.js中的事件触发器所引发的思考今天在看 Node.js 文档的时候讲到事件触发器,其中的 emit 方法让我想到了 Vue 中的自
- 场景分析一般Linux系统默认自带两个版本的python,我按照的虚拟机系统自带的版本为python2.7和python3.2,但是由于个人
- 例如,在使用 SQLCMD 实用工具连接到 SQL Server 时收到以下错误消息: Sqlcmd:错误:Microsoft SQL Na
- 函数的返回值一个函数执行后可以返回多个返回值def measure(): print('测量开始。。。。&
- 安装方法一:①进入python文件夹执行指令(前提是支持pip指令):pip3 install Beautifulsoup4②回车待安装完成
- itchat模块官方参考文档:https://itchat.readthedocs.io/zh/latest/安装pip install i
- 本文实例讲述了JS实现获取毫秒值及转换成年月日时分秒的方法。分享给大家供大家参考,具体如下:时间日期对象创建方式一var date=new
- 内置方法 说明 __init__(self,...) 初始化对象,在创建新对象时调用 __del__(self) 释放对