0


Python验证码识别和生成(5000字详细实例和概念讲解)

哈喽O(∩_∩)O

  1. :.,,.-:*``*:-.,,.-:*``*:
  2. ╭╧╮ ╭╧╮ ╭╧╮ ╭╧╮
  3. ║周║║末║║快║║乐║
  4. └﹏┘└﹏┘└﹏┘└﹏┘
  5. * * * * * * * * * * * * *

╒╧╕ ╒╧╕ ╒╧╕ ╒╧╕ ╒╧╕

|財||招||吉||大||閣|

|源||財||祥||吉||家|

|廣||進||如||大||平|

|進||寶||意||利||安|

╘═╛ ╘═╛ ╘═╛ ╘═╛ ╘═╛

今天,我研究了一下Python爬虫的功能——验证码识别

比如某网站有这样一张人机验证的图片

我要用程序识别出验证码是什么,并输入验证码,打开网站,爬取内容。

ddddocr

ddddocr是一款开源库,专门用来识别验证码,方便快捷

安装

终端运行:pip install ddddocr

使用

ddddocr接收这几个参数
参数名默认值说明use_gpuFalseBool 是否使用gpu进行推理,如果该值为False则device_id不生效device_id0
int cuda设备号,目前仅支持单张显卡

classification
参数名默认值说明img0bytes 图片的bytes格式

试一下

在编译器中输入如下代码:

  1. import ddddocr
  2. ocr=ddddocr.DdddOcr(old=True)
  3. with open("1.jpg", 'rb') as f:
  4. image = f.read()
  5. print(ocr.classification(image))

1.jpg是这样的

输出结果:

可以看到,成功识别出了 z4ta

但是,这个广告看着就很难受,有没有什么方法能去掉呢?

首先,我们来判断一下验证码和前面的广告是库作者拼接在一个字符串里,

还是是两个分别的字符串,分别输出

我们输出这个字符串的第0项看看

  1. import ddddocr
  2. ocr=ddddocr.DdddOcr(old=True)
  3. with open("1.jpg", 'rb') as f:
  4. image = f.read()
  5. print(ocr.classification(image)[0])

输出:z

这就证明这是两个字符串,不影响正常使用

去除广告

我们按住 Ctrl,把光标移到“import ddddocr” 的ddddocr上,发现ddddocr变蓝了

然后我们单击ddddocr,出来这个界面

这就是ddddocr的代码

我们找到这里

把这几行代码注释掉,改成 pass

再运行刚才的文件,发现输出变成了只有 z4ta

标记验证码

效果图:

可以看到,程序把 Z 、4、T、A 都用红圈圈了出来

程序(请安装opencv)

  1. import ddddocr
  2. import cv2
  3. det = ddddocr.DdddOcr(det=True)
  4. with open("1.jpg", 'rb') as f:
  5. image = f.read()
  6. poses = det.detection(image)
  7. print(poses)
  8. im = cv2.imread("1.jpg")
  9. for box in poses:
  10. x1, y1, x2, y2 = box
  11. im = cv2.rectangle(im, (x1, y1), (x2, y2), color=(0, 0, 255), thickness=2)
  12. cv2.imwrite("result.jpg", im)

注意,1.jpg是我们要识别的验证码的图片

源码阅读

  1. import warnings
  2. warnings.filterwarnings('ignore')
  3. import io
  4. import os
  5. import onnxruntime
  6. from PIL import Image
  7. import numpy as np

这里使用onnxruntime模型,使用filterwarnings过滤了可能出现的警告。PIL用于读入图片和缩放,使用numpy转化为矩阵。

  1. class DdddOcr(object):
  2. def __init__(self, use_gpu: bool = False, device_id: int = 0):
  3. self.__graph_path = os.path.join(os.path.dirname(__file__), 'common.onnx')
  4. if use_gpu:
  5. self.__providers = [
  6. ('CUDAExecutionProvider', {
  7. 'device_id': device_id,
  8. 'arena_extend_strategy': 'kNextPowerOfTwo',
  9. 'cuda_mem_limit': 2 * 1024 * 1024 * 1024,
  10. 'cudnn_conv_algo_search': 'EXHAUSTIVE',
  11. 'do_copy_in_default_stream': True,
  12. }),
  13. ]
  14. else:
  15. self.__providers = [
  16. 'CPUExecutionProvider',
  17. ]
  18. self.__ort_session = onnxruntime.InferenceSession(self.__graph_path, providers=self.__providers)
  19. self.__charset = ["", "掀", ...] # 省略亿点点代码

此处定义了Ddddocr类,
名字意义

  1. self.__graph_path

模型位置

  1. self.__providers

模型参数

  1. self.__ort_session

模型session

  1. self.__charset

字符集

  1. ... # 上面的代码
  2. def classification(self, img: bytes):
  3. image = Image.open(io.BytesIO(img)) # 使用BytesIO+pillow读入图片
  4. image = image.resize((int(image.size[0] * (64 / image.size[1])), 64), Image.ANTIALIAS).convert('L') # 缩放为验证码大小,转为二值图
  5. image = np.array(image).astype(np.float32) # 转为float32的矩阵
  6. image = np.expand_dims(image, axis=0) / 255.
  7. image = (image - 0.5) / 0.5
  8. ort_inputs = {'input1': np.array([image])} # 设置模型输入
  9. ort_outs = self.__ort_session.run(None, ort_inputs) # 获取结果
  10. result = []
  11. last_item = 0
  12. for item in ort_outs[0][0]: # 遍历模型,获取结果
  13. if item == last_item:
  14. continue
  15. else:
  16. last_item = item
  17. if item != 0:
  18. result.append(self.__charset[item])
  19. return ''.join(result) # 返回result

生成验证码

如果你觉得用别人的验证码不过瘾的话,可以自己做验证码

代码比较简单

  1. from PIL import Image,ImageDraw,ImageFont
  2. import random
  3. def getRandomColor():
  4. r = random.randint(0, 255)
  5. g = random.randint(0, 255)
  6. b = random.randint(0, 255)
  7. return (r,g,b)
  8. def getRandomStr():
  9. num_random = str(random.randint(1,9))
  10. random_upper_alpha = chr(random.randint(65,90))
  11. random_char = random.choice([num_random,random_upper_alpha])
  12. return random_char
  13. image = Image.new('RGB',(120,40),(255,255,255))
  14. draw = ImageDraw.Draw(image)
  15. font = ImageFont.truetype(r'K:\msyh.ttc',size=24)
  16. for i in range(4):
  17. draw.text((10+i*30,10),getRandomStr(),getRandomColor(),font=font)
  18. width = 120
  19. height = 40
  20. for i in range(5):
  21. x1 = random.randint(0,width)
  22. x2 = random.randint(0,width)
  23. y1 = random.randint(0,height)
  24. y2 = random.randint(0,height)
  25. draw.line((x1,x2,y1,y2),fill=getRandomColor())
  26. for i in range(20):
  27. draw.point([random.randint(0,width),random.randint(0,height)],fill=getRandomColor())
  28. x = random.randint(0,width)
  29. y = random.randint(0,height)
  30. draw.arc((x,y,x+5,y+5),0,90,fill=getRandomColor())
  31. image.save('1.jpg')

模拟登录网站

我们可以自己做一个简单的页面(Html)

再自己破解。

  1. import unittest
  2. from PIL import Image
  3. from selenium import webdriver
  4. from time import sleep
  5. import ddddocr
  6. class WeChat(unittest.TestCase):
  7. # def __init__(self):
  8. def setUp(self) -> None:
  9. self.driver = webdriver.Chrome()
  10. # 自己的网站
  11. self.driver.get('website.html')
  12. # 全屏打开
  13. self.driver.maximize_window()
  14. self.driver.implicitly_wait(10)
  15. self.ocr = ddddocr.DdddOcr()
  16. def test_login_success(self):
  17. # 打开自己的网站会有安全认证
  18. self.driver.find_element('id', 'details-button').click()
  19. self.driver.find_element('id', 'proceed-link').click()
  20. self.driver.find_element('xpath', '//*[@id="layui-layer1"]/div[3]/a').click()
  21. sleep(1)
  22. self.driver.find_element('id', 'account').send_keys('BluetoothHaAdmin')
  23. self.driver.find_element('id', 'password').send_keys('000000')
  24. # 先获取屏幕截图,在找元素,定位大小,通过定位出来的地方截图后使用识别验证码模块,将其
  25. # 以二进制的方式识别后,输出后填写到填写验证码的位置
  26. self.driver.save_screenshot('Login_page.png')
  27. yzm_btn = self.driver.find_element('id', 'id_img')
  28. # 获取图片元素的位置
  29. loc = yzm_btn.location
  30. # 获取图片的宽高
  31. size = yzm_btn.size
  32. # 获取验证码上下左右的位置
  33. left = loc['x']
  34. top = loc['y']
  35. right = (loc['x'] + size['width'])
  36. bottom = (loc['y'] + size['height'])
  37. val = (left, top, right, bottom)
  38. # 打开网页截图
  39. login_pic = Image.open('Login_page.png')
  40. # print(val)
  41. # 通过上下左右的值,去截取验证码
  42. yzm_pic = login_pic.crop(val)
  43. yzm_pic.save('yzm.png')
  44. with open('yzm.png', 'rb') as f:
  45. img_bytes = f.read()
  46. # print (img_bytes)
  47. res = self.ocr.classification(img_bytes)
  48. print("验证码:", res, type(res))
  49. self.driver.find_element('id', 'id_webVerificationCode').send_keys(res)
  50. sleep(1)
  51. self.driver.find_element('id', 'id_loginButton').click()
  52. sleep(12)
  53. self.driver.quit()
  54. if __name__ == '__main__':
  55. ocr = ddddocr.DdddOcr()
  56. wechat = WeChat()
  57. # 点击安全提醒
  58. sleep(12)
  59. #退出
  60. wechat.driver.quit()

最后

今天写了一篇长文,大家看了我的文章可能有一些收获

三连必回,其他不多说了了,拜拜!

标签: 爬虫 验证码 python

本文转载自: https://blog.csdn.net/m0_64036070/article/details/124738704
版权归原作者 YR_T 所有, 如有侵权,请联系我们删除。

“Python验证码识别和生成(5000字详细实例和概念讲解)”的评论:

还没有评论