1、图形验证码识别技术

阻碍我们爬虫的,有时候正是在登录或者请求一些数据时候的图形验证码。因此这里我们讲解一种能将图片翻译成文字的技术。将图片翻译成文字一般被称为光学文字识别(Optical Character Recognition),简写为OCR。实现OCR的库不是很多,特别是开源的。因为这块存在一定的技术壁垒(需要大量的数据、算法、机器学习、深度学习知识等),并且如果做好了具有很高的商业价值。因此开源的比较少。这里介绍一个比较优秀的图像识别开源库:Tesseract

2、Tesseract

2.1 定义

Tesseract是一个将图像翻译成文字的OCR(光学文字识别,Optical Character Recognition),目前由谷歌赞助。Tesseract是目前公认最优秀、最准确的开源OCR库。Tesseract具有很高的识别度,也具有很高的灵活性,他可以通过训练识别任何字体。

2.2 Windows系统安装Tesseract

Windows在Python中调用Tesseract时,既需要安装tesseract.exe,也需要安装pytesseract库;
在链接中载可执行文件:https://github.com/tesseract-ocr/

  1. pip install pytesseract

在ubuntu下通过以下命令进行安装

  1. sudo apt install tesseract-ocr

2.3 设置环境变量

安装完成后,如果想要在命令行中使用Tesseract,那么应该设置环境变量。Mac和Linux在安装的时候就默认已经设置好了。

在Windows下把tesseract.exe所在的路径添加到PATH环境变量中。

还有需要把训练的数据文件路径(tessdata)也放到环境变量中。
在环境变量中,添加一个

TESSDATA_PREFIX=D:\Tesseract-OCR\tessdata

进入cmd输入下面的命令查看版本,正常运行则安装成功

tesseract --version

2.4 在命令行中使用tesseract识别图像

tesseract 图片路径 识别后文件保存路径
不需要加尾缀,默认会添加尾缀txt

tesseract demo.png test

识别中文图像,需要下载语言安装包
语言安装包地址:https://github.com/tesseract-ocr/tessdat
中文语言安装包文件名:chi_sim.traineddata

2.5 在代码中使用tesseract识别图像

import pytesseract
from PIL import Image

pytesseract.pytesseract.tesseract_cmd = r"F:\Tesseract-OCR\tesseract.exe"
tessdata_dir_config = r"--tessdata-dir 'F:\Tesseract-OCR\tessdata'"
img = Image.open("demo.jpg")
print(pytesseract.image_to_string(img, config=tessdata_dir_config, lang="eng"))

2.6 用pytesseract处理图形验证码

验证码接口:https://passport.lagou.com/vcode/create?from=register&refresh=1513081451891

import pytesseract
import os
from PIL import Image
from urllib import request


def get_img():
    url = "https://passport.lagou.com/vcode/create?from=register&refresh=1513081451891"
    if not os.path.exists("img"):
        os.mkdir("img")
    request.urlretrieve(url, "img/test.png")
    img = Image.open("img/test.png")
    return img


def recognition(img):
    pytesseract.pytesseract.tesseract_cmd = r"F:\Tesseract-OCR\tesseract.exe"
    tessdata_dir_config = r"--tessdata-dir 'F:\Tesseract-OCR\tessdata'"
    result = pytesseract.image_to_string(img, config=tessdata_dir_config, lang="eng")
    print(result)


if __name__ == '__main__':
    img = get_img()
    recognition(img)

注意:
tesseract识别白底黑字的二维码比较准确,其他效果很一般;

登入图鉴 二维码识别网站

通过图鉴 二维码识别网站的API登入 图鉴 二维码识别网站
总结:
图片base64解码那里卡了很久,但其实很简单,页面中一共有两个是关于验证码的,一个是变化的url接口,一个是不变的src属性,当发现拿src解码时出错,应该要第一时间拿获取到的src属性和页面中的去对比的,通过长度等,去比较哪里不一样,这里是因为网页中的src属性中是自动换行了的,Base64一行不能超过76字符,超过则添加回车换行符,获取到的src属性中换行符都是被%0A替代了,所以在base64解码的时候会报错填充不正确(Incorrect padding),所以只需将%0A替换成\n,再进行解码就正常了;

from tujianAPI import base64_api
from selenium import webdriver
from PIL import Image
from configparser import ConfigParser
import base64
import time
import os


class TujianSpider(object):
    def __init__(self, user, password):
        self.url = "http://www.ttshitu.com/login.html"
        self.driver = webdriver.Chrome()
        self.user = user
        self.password = password

    def login(self, captcha):
        if not self.driver.find_element_by_name("userName").get_attribute("value"):
            self.driver.find_element_by_name("userName").send_keys(user)
            self.driver.find_element_by_name("password").send_keys(password)
        self.driver.find_element_by_name("captcha").send_keys(captcha)
        btn = self.driver.find_element_by_xpath("//button[@class='layui-btn layui-btn-normal full-width']")
        self.driver.execute_script("arguments[0].click();", btn)

    def save_img_captcha(self):
        img_base64 = self.driver.find_element_by_id("captchaImg").get_attribute("src").split(",")[1].replace('%0A', '\n')
        print(img_base64)
        img_byte = base64.b64decode(img_base64)
        if not os.path.exists("img"):
            os.mkdir("img")
        with open('img/demo.jpg', 'wb') as f:
            f.write(img_byte)

    def get_captcha(self):
        img = Image.open("img/demo.jpg")
        captcha = base64_api(uname=self.user, pwd=self.password, img=img)
        print(captcha)
        return captcha

    def run(self):
        # 1 selenium打开登入页面
        self.driver.get(self.url)
        while True:
            # 2 保存验证码图片
            self.save_img_captcha()
            # 3 调用图鉴提供的接口,识别保存下来的图片验证码
            captcha = self.get_captcha()
            # 4 传入验证码,登入
            self.login(captcha)
            time.sleep(1)
            # 5 登入成功后,结束循环
            if self.driver.current_url != self.url:
                break


def userdata():
    cfg = ConfigParser()
    r = cfg.read("userdata.ini")
    user = cfg.get("user", "user")
    password = cfg.get("password", "password")
    return user, password


if __name__ == '__main__':
    user, password = userdata()
    tujianspider = TujianSpider(user, password)
    tujianspider.run()