Python - 网页抓取处理验证码

  • 简述

    在本章中,让我们了解如何执行网页抓取和处理用于测试用户的人或机器人的验证码。
  • 什么是验证码?

    验证码的完整形式是Completely Automated Public Turing test to tell Computers and Humans Apart,这清楚地表明这是一个判断用户是不是人的测试。
    验证码是一种扭曲的图像,通常不容易被计算机程序检测到,但人类可以设法理解它。大多数网站使用验证码来防止机器人交互。
  • 使用 Python 加载验证码

    假设我们要在网站上进行注册,并且有带有 CAPTCHA 的表单,那么在加载 CAPTCHA 图像之前,我们需要了解表单所需的具体信息。借助下一个 Python 脚本,我们可以了解http://example.webscrapping.com 网站上的注册表单的格式要求。
    
    import lxml.html
    import urllib.request as urllib2
    import pprint
    import http.cookiejar as cookielib
    def form_parsing(html):
       tree = lxml.html.fromstring(html)
       data = {}
       for e in tree.cssselect('form input'):
          if e.get('name'):
             data[e.get('name')] = e.get('value')
       return data
    REGISTER_URL = '<a target="_blank" rel="nofollow" 
       href="http://example.webscraping.com/user/register">http://example.webscraping.com/user/register'</a>
    ckj = cookielib.CookieJar()
    browser = urllib2.build_opener(urllib2.HTTPCookieProcessor(ckj))
    html = browser.open(
       '<a target="_blank" rel="nofollow" 
          href="http://example.webscraping.com/places/default/user/register?_next">
          http://example.webscraping.com/places/default/user/register?_next</a> = /places/default/index'
    ).read()
    form = form_parsing(html)
    pprint.pprint(form)
    
    在上面的 Python 脚本中,首先我们定义了一个函数,该函数将使用 lxml python 模块解析表单,然后它将打印表单要求,如下所示 -
    
    {
       '_formkey': '5e306d73-5774-4146-a94e-3541f22c95ab',
       '_formname': 'register',
       '_next': '/places/default/index',
       'email': '',
       'first_name': '',
       'last_name': '',
       'password': '',
       'password_two': '',
       'recaptcha_response_field': None
    }
    
    您可以从上面的输出中检查所有信息,除了recpatcha_response_field是可以理解和直接的。现在问题出现了,我们如何处理这些复杂的信息并下载 CAPTCHA。可以在 Python Pillow 库的帮助下完成,如下所示;
  • Python Pillow 包

    Pillow 是 Python 图像库的一个分支,具有用于处理图像的有用功能。它可以在以下命令的帮助下安装 -
    
    pip install pillow
    
    在下一个示例中,我们将使用它来加载 CAPTCHA -
    
    from io import BytesIO
    import lxml.html
    from PIL import Image
    def load_captcha(html):
       tree = lxml.html.fromstring(html)
       img_data = tree.cssselect('div#recaptcha img')[0].get('src')
       img_data = img_data.partition(',')[-1]
       binary_img_data = img_data.decode('base64')
       file_like = BytesIO(binary_img_data)
       img = Image.open(file_like)
       return img
    
    上面的python脚本正在使用pillowpython 包并定义了一个用于加载验证码图像的函数。它必须与名为的函数一起使用form_parser()这是在前面的脚本中定义的,用于获取有关注册表单的信息。此脚本将以有用的格式保存 CAPTCHA 图像,该格式可以进一步提取为字符串。
  • OCR:使用 Python 从图像中提取文本

    在以有用的格式加载 CAPTCHA 后,我们可以借助光学字符识别 (OCR) 来提取它,这是一个从图像中提取文本的过程。为此,我们将使用开源 Tesseract OCR 引擎。它可以在以下命令的帮助下安装 -
    
    pip install pytesseract
    

    例子

    在这里,我们将扩展上述 Python 脚本,该脚本使用 Pillow Python 包加载验证码,如下所示 -
    
    import pytesseract
    img = get_captcha(html)
    img.save('captcha_original.png')
    gray = img.convert('L')
    gray.save('captcha_gray.png')
    bw = gray.point(lambda x: 0 if x < 1 else 255, '1')
    bw.save('captcha_thresholded.png')
    
    上面的 Python 脚本将以黑白模式读取 CAPTCHA,这将清晰且易于传递给 tesseract,如下所示 -
    
    pytesseract.image_to_string(bw)
    
    运行上述脚本后,我们将得到注册表单的验证码作为输出。