Python爬虫之验证码处理

1、了解常见验证码

在日常生活与工作中,在进行各类设计个人账户安全的操作时,往往需要填写各种验证码来进行验证,短信、语音、文字、问答、图片、拖拽、旋转腾挪、拼图接图...千奇百怪,各种各样,种类繁多,花样迭起!

就拿奇葩验证码鼻祖的12306来说,如今我们在12306中可以碰到各种有趣,各种类型的验证码的原因,要归功于为抢票事业做出巨大贡献的——黄牛们,它的“进化史”就是一部不断与黄牛和抢票软件“斗智斗勇”的历史。

Python爬虫之验证码处理_第1张图片

目前我们常见的验证码,无非就是文本、图像以及音频这三大类。

Python爬虫之验证码处理_第2张图片

而当文本验证码仍容易被机器“击破”时,图像验证码就应运而生了。通常是会提供一些物体、动物、植物、人、风景之类的图像,让我们选择正确的图像进行标记。这就是以12306为首的图像验证码了,但是这个还不算后来图像验证码又增加了新的玩法,比如旋转图片,比如拼图以及宫格,目的还是为了对抗爬虫这些机器。

Python爬虫之验证码处理_第3张图片

接下来是音频验证码,这种相比前两种数量相对要小一些,主要是会给我们一段录音,里面有随机的单词或数字,有的会加一些噪音,我们基于录音输入其中听到的单词或数字,或者把它读出来。从安全性上来说,声音验证码比文本和图像等级要提升一个层级,因为机器想要听录音并分辨,这个难度会非常大。

Python爬虫之验证码处理_第4张图片

2、验证码的处理方案

  • 手动输入(input) 这种方法仅限于登录一次就可持续使用的情况

  • 图像识别引擎解析 使用光学识别引擎处理图片中的数据,目前常用于图片数据提取,较少用于验证码处理

  • 打码平台 爬虫常用的验证码解决方案

3、图像识别引擎

OCR,即Optical Character Recognition,光学字符识别,是指通过扫描字符,然后通过其形状将其翻译成电子文本的过程,对应图形验证码来说,它们都是一些不规则的字符,这些字符是由字符稍加扭曲变换得到的内容,我们可以使用OCR技术来讲其转化为电子文本,然后将结果提取交给服务器,便可以达到自动识别验证码的过程

tesserocr与pytesseract是Python的一个OCR识别库,但其实是对tesseract做的一层Python API封装,pytesseract是Google的Tesseract-OCR引擎包装器;所以它们的核心是tesseract,因此在安装tesserocr之前,我们需要先安装tesseract。

图片识别引擎环境的安装

1、引擎的安装

mac环境下直接执行命令

brew install --with-training-tools tesseract

windows环境下的安装 可以通过exe安装包安装,下载地址可以从GitHub项目中的wiki找到。安装完成后记得将Tesseract 执行文件的目录加入到PATH中,方便后续调用。

linux环境下的安装

sudo apt-get install tesseract-ocr
2 

2、Python库的安装

# PIL用于打开图片文件
pip/pip3 install pillow

# pytesseract模块用于从图片中解析数据
pip/pip3 install pytesseract

本次案例我们使用图片识别引擎识别验证码登陆古诗文网

Python爬虫之验证码处理_第5张图片

通过分析我们发现验证码点击刷新的链接是:

Python爬虫之验证码处理_第6张图片

所以我们请求10次本链接获取10张图片,进行图片识别

import time
from PIL import Image
import pytesseract
import requests

headers = {
   "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36"
}
image_url = 'https://so.gushiwen.org/RandCode.ashx'
# 下载验证码图片
session = requests.Session()  # 使用session是为了保证验证码的请求和登陆请求信息一致


for i in range(10):
   r = session.get(image_url, headers=headers)
   with open('images/code'+str(i)+'.jpg', 'wb') as fp:
       fp.write(r.content)
   time.sleep(10)
   print('下载完成第'+str(i)+'张!')

# 依次识别并保存到文件中

# 进行二值处理
def erzhihua(image, threshold):
   ''':type image:Image.Image'''
   image = image.convert('L')
   table = []
   for i in range(256):
       if i < threshold:
           table.append(0)
       else:
           table.append(1)
   return image.point(table, '1')

# 对刚才保存的10张图片进行识别
for i in range(10):
   im = Image.open('images/code' + str(i) + '.jpg')
   im = erzhihua(im, 127)
   im.show()
   result = pytesseract.image_to_string(im, lang='eng')

   print(result)

但是很遗憾10次或者更多次数才能打码成功一次。

4、打码平台

此时我们就要寻求专业的打码平台,申请第三方的平台,宋宋试了一下阿里提供的各种免费的打码平台。链接:https://market.aliyun.com/products/?keywords=图片识别验证码,但是识别效果不是很佳(哈哈因为是免费的缘故吧!只有标记优品的那个还不错其他的也可以自行试一试)。

Python爬虫之验证码处理_第7张图片

为了测试它的识别效果,我们尝试申请成交次数最多的那个,查看官方API说明如下:

Python爬虫之验证码处理_第8张图片

因此我们使用验证码打码平台获取验证码并登录

实现思路:

使用requests.session获取图片并进行本地保存

使用打码平台识别图片

获取登录链接,登陆链接是一个post请求,并携带了你的表单中填入的用户名和密码

登陆获取cookies, 才能去访问用户的个人页

import json

from PIL import Image
import pytesseract
import requests
import urllib.request
import base64
import ssl

ssl._create_default_https_context = ssl._create_unverified_context

# 1. 使用requests.session获取图片并进行本地保存
headers = {
  "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36"
  , 'Host': 'www.xqb5200.com'
  , 'Referer': 'https://www.xqb5200.com/login.php'
}
session = requests.Session() # 使用session是为了保证验证码的请求和登陆请求信息一致
code_image_url = "https://www.xqb5200.com/checkcode.php"
r = session.get(code_image_url, headers=headers)
with open('code.jpg', 'wb') as fp:
  fp.write(r.content)

# 2. 使用打码平台识别图片
# 修改API说明修改接口地址
url = 'https://imgurlocr.market.alicloudapi.com/urlimages'
method = 'POST'
appcode = '你的APPCODE'
querys = ''
bodys = {}

f = open(r'code.jpg', 'rb')
contents = base64.b64encode(f.read())
f.close()
bodys['image'] = bytes("data:image/jpg;base64,", encoding="utf8")+contents

post_data = urllib.parse.urlencode(bodys).encode(encoding='UTF8')
request = urllib.request.Request(url, post_data)
# 根据API的要求,定义相对应的Content-Type
request.add_header('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8')
request.add_header('Authorization', 'APPCODE ' + appcode)
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
response = urllib.request.urlopen(request, context=ctx)

content = response.read()
if (content):
  code = json.loads(content.decode('utf-8'))
  print(code)
  print(code['result']['words'])
# 3. 获取登录链接,登陆链接是一个post请求,并携带了你的表单中填入的用户名和密码
  login_url = "https://www.xqb5200.com/login.php?do=submit"
# 用户名和密码大家可以注册一个新的用户
  data = {
      "username": "你的用户名",
      "password": "你的秘密",
      "checkcode": code,
      "action": "login",
      "submit": "%26%23160%3B%B5%C7%26%23160%3B%26%23160%3B%C2%BC%26%23160%3B"
  }

  # 4. 登陆获取cookies, 才能去访问用户的个人页
  response = session.post(url=login_url, headers=headers, data=data)
  response.encoding = 'utf-8'
  cookies = response.cookies
  # 查看登陆是否成功了
  with open('logsucess.html', 'wb') as fp:
      response.encoding = response.apparent_encoding
      fp.write(response.content)

这样我们还是可以识别这个验证码的,如图

Python爬虫之验证码处理_第9张图片

最后保存到本地的文件,显示登陆成功

Python爬虫之验证码处理_第10张图片

还有滑动验证码和点触验证码的使用以及selenium+验证码登陆,期待下篇文章给大家分享...

你可能感兴趣的:(python,爬虫)