Python Web Scraping: procesamiento de CAPTCHA

En este capítulo, entendamos cómo realizar el raspado web y el procesamiento de CAPTCHA que se utiliza para probar un usuario para humano o robot.

¿Qué es CAPTCHA?

La forma completa de CAPTCHA es Completely Automated Public Turing test to tell Computers and Humans Apart, lo que sugiere claramente que se trata de una prueba para determinar si el usuario es humano o no.

Un CAPTCHA es una imagen distorsionada que, por lo general, no es fácil de detectar mediante un programa de computadora, pero un ser humano puede de alguna manera entenderla. La mayoría de los sitios web utilizan CAPTCHA para evitar que los bots interactúen.

Cargando CAPTCHA con Python

Supongamos que queremos hacer el registro en un sitio web y hay un formulario con CAPTCHA, luego antes de cargar la imagen CAPTCHA necesitamos conocer la información específica requerida por el formulario. Con la ayuda del siguiente script de Python, podemos comprender los requisitos del formulario de registro en el sitio web llamadohttp://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)

En el script de Python anterior, primero definimos una función que analizará el formulario utilizando el módulo lxml python y luego imprimirá los requisitos del formulario de la siguiente manera:

{
   '_formkey': '5e306d73-5774-4146-a94e-3541f22c95ab',
   '_formname': 'register',
   '_next': '/places/default/index',
   'email': '',
   'first_name': '',
   'last_name': '',
   'password': '',
   'password_two': '',
   'recaptcha_response_field': None
}

Puede comprobar en la salida anterior que toda la información excepto recpatcha_response_fieldson comprensibles y sencillos. Ahora surge la pregunta de cómo podemos manejar esta compleja información y descargar CAPTCHA. Se puede hacer con la ayuda de la biblioteca Python de almohada de la siguiente manera;

Paquete Pillow Python

Pillow es una bifurcación de la biblioteca de imágenes de Python que tiene funciones útiles para manipular imágenes. Se puede instalar con la ayuda del siguiente comando:

pip install pillow

En el siguiente ejemplo lo usaremos para cargar el 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

El script de Python anterior está usando pillowpython y definir una función para cargar la imagen CAPTCHA. Debe usarse con la función denominadaform_parser()que se define en el script anterior para obtener información sobre el formulario de registro. Este script guardará la imagen CAPTCHA en un formato útil que además se puede extraer como cadena.

OCR: extracción de texto de una imagen con Python

Después de cargar el CAPTCHA en un formato útil, podemos extraerlo con la ayuda del Reconocimiento óptico de caracteres (OCR), un proceso de extracción de texto de las imágenes. Para este propósito, vamos a utilizar el motor Tesseract OCR de código abierto. Se puede instalar con la ayuda del siguiente comando:

pip install pytesseract

Ejemplo

Aquí ampliaremos el script de Python anterior, que cargó el CAPTCHA usando el paquete Pillow Python, de la siguiente manera:

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')

El script de Python anterior leerá el CAPTCHA en modo blanco y negro, lo que sería claro y fácil de pasar a tesseract de la siguiente manera:

pytesseract.image_to_string(bw)

Después de ejecutar el script anterior, obtendremos el CAPTCHA del formulario de registro como salida.