viernes, 20 de agosto de 2010

Saltándose los captchas de Megaupload con python

Como todo buen gorrón me gusta las cosas gratis y fáciles, sobre todo cuando se tiene una serie de 24 capítulos que se quiere descargar sin estar pendiente rellenando captchas, y aunque las cuentas premiun no son tan caras, la verdad no me apetece gastarme una platica en algo que voy a utilizar muy rara vez, así que hice lo que cualquier persona normal haría, juntar un montón de software libre y pegarlos con un poco de python y voila mi propio gestor de descarga con reconocimiento de captchas (solo megaupload), ya se que hay muchos programas que hacen lo mismo y ademas libres (Tucan por ejemplo), pero usarlos no seria tan divertido, así que me puse a recolectar los materiales para mi "manualidad". Gestor de descargas ya tenia y no podía ser mejor que wget, solo faltaba el reconocimiento de caracteres, ocr que llaman; después de un poco de búsqueda apareció tesseract que sin lugar a dudas es el mejor programa de reconocimiento de caracteres que haya visto hasta el momento. Solo faltaban algunas librerías como pytesser para "comunicarse" con tesseract y  libxml2dom (requiere libxml2) para consultar el dom en documentos aun cuando estos estén mal formados.

Como ven, lo bonito del software libre es que con tan solo una búsqueda nos encontramos con programas maravillosos, los cuales podemos utilizar sin ninguna restricción (sí, ya se que esto no es completamente cierto). Ahora si, con ustedes el script:
import libxml2dom
import urllib2
import urllib
import pytesser
import Image

MAX_TRY = 5 # intentos antes de rendirse
WAIT_TIME = 45 # tiempo de espera en segundos
CAPTCHA_INPUT_NAME = "captcha"
TEMP_FILE_NAME   = "tempImg.gif"
ID_DOWNLOAD_LINK = "downloadlink"

def urlopen(url, data={}):
 """Abrir un recurso remoto, si se pasa data se envía por POST"""
 req = urllib2.Request(url, urllib.urlencode(data) if data else None)
 try:
  sock = urllib2.urlopen(req)
  try:
   data = sock.read()
  finally:
   sock.close()
 except IOError:
  print "el archivo no existe"
 else:
  return data

def html2dom(page):
 """Retornar representación DOM de un documento html"""
 dom = libxml2dom.parseString(page, html=1)
 return dom

def tag(elem, tag):
 """Encontrar descendientes de un elementos por su tag"""
 elements = elem.getElementsByTagName(tag)
 return elements[0] if len(elements) == 1 else elements
 
def id(elem, Id):
 return elem.getElementById(Id)
 
def attr(elem, attr):
 """Retornar atributo de un elemento"""
 return elem.getAttribute(attr)

def save_img(uri):
 """Guardar imagen en local"""
 data = urlopen(uri)
 temp = file(TEMP_FILE_NAME, 'wb')
 temp.write(data)
 temp.close()

def resolver_captcha():
 """Resolver captcha"""
 data = Image.open(TEMP_FILE_NAME)
 return pytesser.image_to_string(data)[:4]

def fill_form(page):
 """Recolectar datos de formulario"""
 try:
  form = tag(page, 'form')
  img = tag(form, 'img')

  save_img(attr(img, "src"))
 
  # crear diccionario valores a enviar
  data = dict([(attr(i, 'name'),attr(i, 'value')) for i in tag(form, 'input')])

  # "rellenar" campo captcha
  captcha = resolver_captcha()
  data[CAPTCHA_INPUT_NAME] = captcha
 except:
  return None
 else:
  return (data, captcha)

# Donde la magia sucede XD
def get(url):
 """Descargar archivo"""
 times = 1

 # solo links de megaupload
 if url.find('http://www.megaupload.com/') != 0:
  print "%s no es un link de megaupload" % url
  return 0
  
 # Abrir pagina de formulario
 page = html2dom( urlopen(url) )

 while True:
  # llenamos el formulario
  data, captcha = fill_form(page)
  
  if not data or times == MAX_TRY:
   print "Error al abrir %s, puede que el link haya sido deshabilitado" % url
   return 0

  print "%s ==> intento %d\ncaptcha = %s" % (url, times, captcha)
  times += 1

  # Enviamos formulario por POST
  page = html2dom( urlopen(url, data) )
  
  # Si el captcha esta correcto obtenemos la página de descarga
  download_page = id(page, ID_DOWNLOAD_LINK)
  
  if download_page:
   download_link = tag( download_page , 'a' )
   import subprocess, time
   
   # please wait.... XD
   time.sleep(WAIT_TIME)

   args = ['wget', '-c', attr(download_link, 'href')]
   
   # empezamos a descargar ^_^
   proc = subprocess.Popen(args)
   retcode = proc.wait()
   return 1
   
def get_from_file(file_path):
 """descargar múltiples archivos leyendo urls almacenadas en un archivo"""
 try:
  sock = file(file_path)
  try:
   lines = sock.readlines()
  finally:
   sock.close()
 except IOError:
  print "el archivo %s no existe" % file_path
 else:
  for line in lines:
   url = line.strip()
   if url:
    get( url )

if __name__ == "__main__":
 import sys

 arg = sys.argv[1:]
 
 if arg[0] == "-f":
  get_from_file(arg[1])
 elif "http" in arg[0]:
  get(arg[0])
 else:
  print "uso:\nmget link_descarga\nmget -f /ruta/archivo/links_descarga\n" 

Claro que le hacen falta algunas funcionalidades, pero para lo que lo necesito me basta y me sobra, ademas como ya dije existe una gran variedad de programas que hacen lo mismo. Si lo desean pueden descargar los archivos desde el siguiente enlace:
P.D.: Se aceptan criticas, solo no sean tan duros XD

2 Responses to “Saltándose los captchas de Megaupload con python”

Hola:
estoy tratando de implementar tu ejemplo, pero extrañamente python se queja que libxml2dom no tiene atributo parseString(), esto tiene algún sentido para ti?
He colocado el packete de la libreria en donde tengo el script.

Saludos!

sney2002 dijo...

hola Gabriel.
me parece raro, acabe de descargar la version 0.5 y me funciono.

tal vez sea mejor que lo instales, entras al directorio libxml2dom-5.0 desde un terminal y ejecutas:

python setup.py install

Deja una respuesta

 
© 2009 NovatoZ. All Rights Reserved | Powered by Blogger
Design by psdvibe | Bloggerized By LawnyDesignz