Que nuestras aplicaciones se integren con un resolvedor automático de captcha es imprescindible para automatizar ciertos procesos. Antigate.com, es un servicio que por $0.7USD resuelven 1000 captchas y el mínimo de compra son $10USD. Hoy veremos como integrar el api de este servicio a nuestra aplicación en Visual Basic .NET.

Cuando creamos una cuenta en este servicio y la cargamos con un monto mínimo en dólares, se nos entrega un API KEY que será la que integraremos con nuestro software. Cuando inicies sesión con tu cuenta podrás ver esta KEY en el menú recognition > Access Key.

El algoritmo a usar es el siguiente:

  1. El software envía el CAPTCHA por el método seleccionado (HTTP POST en multipart / form-codificar o base64 codificado) y obtiene su ID.
  2. Esperar 10 – 20 segundos (Tiempo promedio en el que los trabajadores de Antigate tardan en resolver el Captcha).
  3. Se hace una petición al servicio y se identifica con su API KEY. Puede devolver texto adivinado o CAPCHA_NOT_READY.
  4. Si recibe el código CAPCHA_NOT_READY esperar 5 segundos y repetir el paso número 3.
  5. Si obtiene OK | SOME_TEXT_HERE entonces SOME_TEXT_HERE es el texto de su captcha.

Iniciamos ahora Visual Basic .NET y vamos a proyecto > Agregar clase y la nombramos como agapi. Allí insertamos todas estas funciones que no es necesario entenderlas ya que son las que proporciona el mismo API del sitio. Pero antes, hacemos los Imports:

Imports System.IO
Imports System.Collections.Specialized
Imports System.Threading
Imports System.Text
Imports System.Net
Imports System.Drawing.Imaging

Y dentro de la clase agapi si podemos insertar todas estas funciones:

Function GetCaptcha(ByVal UrlCaptcha As String, ByVal KeyC As String) As String
        Dim MyStr As MemoryStream = Bmp2JpgUrl(UrlCaptcha)
        Dim nvc As New NameValueCollection()
        Dim CID As String
        nvc.Add("method", "post")
        nvc.Add("key", KeyC)
        nvc.Add("file", "captcha.jpg")
        Dim Res As String = UploadFileStream("http://antigate.com/in.php", nvc, MyStr)
        Dim ResStr = "ERROR"
        Dim Sp(1) As String
        Sp(0) = "|"
        Dim Resp() As String = Res.Split(Sp, StringSplitOptions.RemoveEmptyEntries)
        If Resp.Length <> 2 Then
            Return ResStr
        End If
        If Resp(0) <> "OK" Then
            Return ResStr
        End If
 
        CID = Resp(1)
        Thread.Sleep(10000)
        ResStr = GetStatusCaptcha(CID, KeyC)
        Dim ip As String = 0
        While ResStr = "ERROR" And ip < 4
            Thread.Sleep(5000)
            ResStr = GetStatusCaptcha(CID, KeyC)
        End While
        Return ResStr
    End Function
 
 
 
    Function GetStatusCaptcha(ByVal CID As String, ByVal KeyC As String) As String
        Dim LoadU = "http://antigate.com/res.php?key=" & KeyC & "&action=get&id=" & CID
        Dim Req As HttpWebRequest = CType(WebRequest.Create(LoadU), HttpWebRequest)
        Req.Method = "GET"
        Req.UserAgent = "Mozilla/4.0+(compatible;+MSIE+5.01;+Windows+NT+5.0)"
        Dim respreq As HttpWebResponse
        Dim receiveStream As Stream
        respreq = CType(Req.GetResponse(), HttpWebResponse)
        receiveStream = respreq.GetResponseStream()
        Dim StrRead As New StreamReader(receiveStream, Encoding.GetEncoding(1251))
        Dim Res As String = StrRead.ReadToEnd()
        Dim Sp(1) As String
        Sp(0) = "|"
        Dim ResStr = "ERROR"
        Dim Resp() As String = Res.Split(Sp, StringSplitOptions.RemoveEmptyEntries)
        If Resp.Length <> 2 Then
            Return ResStr
        End If
        If Resp(0) <> "OK" Then
            Return ResStr
        End If
        ResStr = Resp(1)
        Return ResStr
    End Function
 
 
    Function UploadFileStream(ByVal Url As String, ByVal nvc As NameValueCollection, ByVal FStream As Stream) As String
        Dim length As Long = 0
        Dim boundary As String = "----------------------------" & DateTime.Now.Ticks.ToString("x")
        Dim httpWebRequest2 As HttpWebRequest = CType(WebRequest.Create(Url), HttpWebRequest)
        httpWebRequest2.ContentType = "multipart/form-data; boundary=" + boundary
        httpWebRequest2.Method = "POST"
        httpWebRequest2.KeepAlive = True
        Dim memStream As New MemoryStream()
        Dim boundarybytes() As Byte = Encoding.ASCII.GetBytes(Chr(13) & Chr(10) & "--" & boundary & Chr(13) & Chr(10))
 
        Dim formdataTemplate As String = Chr(13) & Chr(10) & "--" & boundary & Chr(13) & Chr(10) & "Content-Disposition: form-data; name=""{0}"";" & Chr(13) & Chr(10) & Chr(13) & Chr(10) & "{1}"
 
        For Each key As String In nvc.Keys
            Dim formitem As String = String.Format(formdataTemplate, key, nvc(key))
            Dim formitembytes() As Byte = Encoding.GetEncoding(1251).GetBytes(formitem)
            memStream.Write(formitembytes, 0, formitembytes.Length)
        Next
 
        memStream.Write(boundarybytes, 0, boundarybytes.Length)
 
        Dim headerTemplate As String = "--" & boundary & Chr(13) & Chr(10) & "Content-Disposition: form-data; name=""file""; filename=""captcha.jpg""" & Chr(13) & Chr(10) & "Content-Type: image/pjpeg" & Chr(13) & Chr(10) & Chr(13) & Chr(10)
 
        Dim headerbytes() As Byte = System.Text.Encoding.GetEncoding(1251).GetBytes(headerTemplate)
 
        memStream.Write(headerbytes, 0, headerbytes.Length)
 
        FStream.Position = 0
        Dim buffer(FStream.Length) As Byte
        Dim bytesRead As Integer = 0
        bytesRead = FStream.Read(buffer, 0, buffer.Length)
        memStream.Write(buffer, 0, bytesRead)
        memStream.Write(boundarybytes, 0, boundarybytes.Length)
 
        httpWebRequest2.ContentLength = memStream.Length + 1
        Dim requestStream As Stream = httpWebRequest2.GetRequestStream()
        memStream.Position = 0
        Dim tempBuffer(memStream.Length) As Byte
        memStream.Read(tempBuffer, 0, tempBuffer.Length)
        memStream.Close()
        requestStream.Write(tempBuffer, 0, tempBuffer.Length)
        requestStream.Close()
        Dim webResponse2 As WebResponse = httpWebRequest2.GetResponse()
        Dim stream2 As Stream = webResponse2.GetResponseStream()
        Dim reader2 As New StreamReader(stream2, Encoding.GetEncoding(1251))
        Dim Res As String = reader2.ReadToEnd()
        webResponse2.Close()
        Return Res
    End Function
 
 
    Function Bmp2JpgUrl(ByVal LoadU As String) As Stream
        Dim Req As HttpWebRequest = CType(WebRequest.Create(LoadU), HttpWebRequest)
        Req.Method = "GET"
        Req.UserAgent = "Mozilla/4.0+(compatible;+MSIE+5.01;+Windows+NT+5.0)"
        Dim resp As HttpWebResponse = CType(Req.GetResponse(), HttpWebResponse)
        Dim receiveStream As Stream = resp.GetResponseStream()
        Dim Bmp As New Bitmap(receiveStream)
        Dim ResStream As New MemoryStream()
        Bmp.Save(ResStream, ImageFormat.Jpeg)
        Return ResStream
    End Function

Luego ya en el formulario lo siguiente será un botón y un picturebox para leer imagen, es solo un ejemplo, en donde la variable “imgurl” contiene la url completa de la imagen del captcha. Cuando se usa ReCaptcha por ejemplo, obtenemos una URL con un llave o código bastante extenso que representa a la imagen y es posible utilizarla.

Dim imgurl As String
imgurl = "http://localhost/catpcha.jpg"
Dim anticaptcha As New agapi
anticaptcha.GetCaptcha(imgurl, "Aquí tu API KEY de Antigate")
Dim txt As String
txt = anticaptcha.GetCaptcha(imgurl, "Aquí tu API KEY de Antigate")
TextBox1.Text = txt

En donde la variable de tipo string llamada “txt” es la que nos devuelve el valor de la cadena ya resuelta.

La cuestión en este tipo de software es que debemos identificar la imagen de cada tipo de captcha, podemos trabajar los elementos HTML de la página e identificarlos con su elemento ID para obtener la URL de la imagen y así pasarla como parámetro a las funciones del api de Antigate.