爬虫技术-验证码处理
验证码反爬虫
1. 简介
我们在浏览网站的时候经常会遇到各种各样的验证码,在多数情况下这些验证码会出现在登录账号的时候,也可能会出现在访问页面的过程中,严格来说,这些行为都算验证码反爬虫。
样例:https://my.cnki.net/Register/CommonRegister.aspx?returnUrl=https://www.cnki.net
1.1 验证码得作用
它有什么用呢?当然很多用处,如:
- 网站注册的时候加上验证码,可以一定程度上防止恶意大批量注册。
- 网站登录的时候加上验证码,可以一定程度上防止恶意密码爆破。
- 网站在发表评论的时候加上验证码,可以在一定程度上防止恶意灌水。
- 网站在投票的时候加上验证码,可以在一定程度上防止恶意刷票。
- 网站在被频繁访问的时候或者浏览行为不正常的时候,一般可能是遇到了爬虫,可以一定程度上防止爬虫的爬取。
总的来说呢,以上的行为都可以称之为验证码反爬虫行为。使用验证码可以防止各种可以用程序模拟的行为。有了验证码,机器要想完全自动化执行就会遇到一些麻烦,当然这个麻烦的大小就取决于验证码的破解难易程度了。
2. 图形验证码
2.1 逆向目标
2.2 逆向分析
2.2.1 图形验证码组成
地址:http://app.gjzwfw.gov.cn/jmopen/verifyCode.do?width=100&height=55&random=0.9567858374678466
彩色图像通常由多种颜色组成,几乎所有颜色都可以由三种原色(红色,绿色和蓝色)生成,即RGB图像。
查看RGB
: https://www.office26.com/rgb.html
验证码生成:
import random from PIL import Image, ImageDraw, ImageFont width, height, font_size, font_num = 300, 100, 48, 5 bg_color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) # 背景颜色 image = Image.new(mode='RGB', size=(width, height), color=bg_color) # 画布 draw = ImageDraw.Draw(image, mode='RGB') # 绘图类 font = ImageFont.truetype("/System/Library/Fonts/Supplemental/Academy Engraved LET Fonts.ttf", font_size) # 字体 verify = str() for i in range(font_num): x = random.randint(i * (width / font_num), (i + 1) * (width / font_num) - font_size) y = random.randint(0, height - font_size) char = random.choice([chr(alpha) for alpha in range(65, 91)] + [str(num) for num in range(10)]) # 随机参数拼接给verify verify += char color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) draw.text((x, y), char, fill=color, font=font) print(verify) image.show()
-
Image
模块中的new()
函数,创建一张图片(画布),用于绘图。 -
传入3个参数,画布的模式(
RGB
表示真彩图片)、尺寸和颜色,画布的颜色就是验证码中的背景颜色。 -
实例化一个
ImageDraw
类的对象draw
,执行绘图。对象draw
调用对应的方法执行绘图,使用draw对象将验证码中的字符画在画布
使用flask创建一个网页验证码:
import random from PIL import Image, ImageDraw, ImageFont from io import BytesIO def get_img(): width, height, font_size, font_num = 300, 100, 48, 4 bg_color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) # 背景颜色 image = Image.new(mode='RGB', size=(width, height), color=bg_color) # 画布 draw = ImageDraw.Draw(image, mode='RGB') # 绘图类 font = ImageFont.truetype("/System/Library/Fonts/Supplemental/Academy Engraved LET Fonts.ttf", font_size) # 字体 verify = str() for i in range(font_num): x = random.randint(i * (width / font_num), (i + 1) * (width / font_num) - font_size) y = random.randint(0, height - font_size) char = random.choice([chr(alpha) for alpha in range(65, 91)] + [str(num) for num in range(10)]) # 随机参数拼接给verify verify += char color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) draw.text((x, y), char, fill=color, font=font) # print(verify) # image.show() by = BytesIO() image.save(by,format='PNG') img_by = by.getvalue() return verify,img_by from flask import Flask,make_response app = Flask(__name__) @app.route('/') def index(): # 给前端返回图像 后端保留文字 text,img = get_img() print(text,'我是图像文字') resp = make_response(img) resp.content_type = 'image/png' return resp if __name__ == '__main__': app.run()
2.2.2 验证码返回
- 可以采用flask框架返回对应的数据
from flask import Flask, Response, make_response data = [] app = Flask(__name__) @app.route('/') def index(): text,img = xl_tests.get_image() data.append(text) print(data) data.clear() resp = make_response(img) resp.content_type = "image/png" return resp if __name__ == '__main__': app.run()
2.2.3 验证码识别
开源地址:https://github.com/sml2h3/ddddocr
import ddddocr ocr = ddddocr.DdddOcr() with open("verifyCode.png", 'rb') as f: img_bytes = f.read() red = ocr.classification(img_bytes) print(red)
3. 图像处理pillow
3.1 简介
Python Imaging Library
(简称:PIL
)是一个基于 Python
的图像处理库,这个库提供了广泛的文件格式支持、高效的内部表示和相当强大的图像处理能力。旨在快速访问几种基本像素格式存储的数据,为通用图像处理工具提供坚实的基础
官网:https://pillow.readthedocs.io/en/stable/reference/Image.html
3.2 使用
3.2.1 环境安装
pip install pillow==8.1.2 -i https://pypi.tuna.tsinghua.edu.cn/simple/
3.2.2 模块基本操作
-
读取基本信息
im = Image.open('dm.jpg') print(im.size) print(im.mode) print(im.info) -
图片压缩与旋转
ims = im.resize((128,128)) ims.show() ims = im.rotate(50) img = im.transpose(Image.FLIP_TOP_BOTTOM) -
图像张贴
img_re = Image.open('test.png') res = img_re.resize((200,200)) im.paste(res,box= [608,74]) im.show() -
圈核心位置:从220 0起点画长600 高489的图形
draw = ImageDraw.Draw(im) draw.rectangle([220,0,600,489],fill=None,width=5,outline='green') im.show() -
边缘提取和高斯模糊
img_edg = im.filter(ImageFilter.FIND_EDGES) img_edg.show() im_b = im.filter(ImageFilter.GaussianBlur(radius=3)) im_b.show()
4. 验证码突破实战
4.1 验证码突破
网站:http://app.gjzwfw.gov.cn/jmopen/webapp/html5/hnsbswdcx/index.html
4.1.1 获取验证码
import ddddocr import requests def img_read(): session = requests.session() ocr = ddddocr.DdddOcr() headers= { "Cookie": "JSESSIONID=3F0E43F4D1024D9BEA08E7A7AF5B4251; HWWAFSESID=5e93925f31d32fef0f0; HWWAFSESTIME=1661863949069; JMOPENSESSIONID=2aa3d571-6433-4e44-adb7-ae1d5b6ace78", } session.headers = headers res = session.get('http://app.gjzwfw.gov.cn/jmopen/verifyCode.do?width=100&height=55&random=0.08462383677727381').content with open('ss.png','wb') as ffff: ffff.write(res) red = ocr.classification(res) return red print(img_read()) # WF3d
4.2.2 验证码验证
def ocr_img(): session = requests.session() # 头部参数 顺序 反爬虫 headers = { "Cookie": "JSESSIONID=3F0E43F4D1024D9BEA08E7A7AF5B4251; HWWAFSESID=5e93925f31d32fef0f0; HWWAFSESTIME=1661863949069; JMOPENSESSIONID=2aa3d571-6433-4e44-adb7-ae1d5b6ace78", "Referer": "http://app.gjzwfw.gov.cn/jmopen/webapp/html5/hnsqymckkfcx/index.html", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" } url = 'http://app.gjzwfw.gov.cn/jmopen/checkValiCode.do' s = img_read() session.headers = headers print(s.lower()) data = { "code": s.lower() } res = session.post(url,data=data) print(res.text)
4.4.3 获取数据
def get_data(): headers = { "Referer": "http://app.gjzwfw.gov.cn/", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" } url = "http://apis.zwfw.hunan.gov.cn/H006/custom/search/addressn" params = { "jz": "1", "sz": "430100", "qx": "430121" } response = requests.post(url, headers=headers, params=params, verify=False) print(response.text)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探