les comparto este script que realiza para sacar emails de una web usando una arañita que recorre enlaces internos...
lo comparto por si se les ocurre modificaciones poder mejorarlo
repo git >
https://github.com/Boredsoft/email-spider** acepta parametros
-url obligatorio con formato http://somthing.com/ (la / final es necesaria)
-max_links maxima cantidad de links a analizar antes de cortar el programa y guardar
-max_emails maxima cantidad de emails a obtener antes de finalizar el programa y guardar
-external acepta links externos, pero si no se usa junto con max_links o max_emails el programa nunca se detendra
** si la conexion de internet se cae el programa espera 30 segundos para reanudarse
** no se traba con enlaces muertos
** uso de "sort" para revisar enlaces con mayor probabilidad de tener email despues de cierto tiempo
fix 3.0
soporte para mas sistemas operativos
mejor detección de emails mediante el regex
fix v 2.0
ahora detecta mas tipos de urls internas
ahora detecta si es windows o linux para usar el comando correcto de limpiar pantalla.
# -*- coding: utf-8 -*-
## by kase: kase@boredsoft.com colaboraciones: EleKtro H@cker
import requests,re,os,time,sys
from argparse import ArgumentParser, RawTextHelpFormatter
parser = ArgumentParser(description="email spider", version="3.0", formatter_class=RawTextHelpFormatter)
## -url
parser.add_argument("-url", dest="url", help='url a analizar en formato http://web.com/')
## -max_links links
parser.add_argument("-max_links", dest="max_links", help='maximo de links internos a analizar')
## -max_emails emails
parser.add_argument("-max_emails", dest="max_emails", help='maximo de emails a analizar')
## -external default False
parser.add_argument("-external", dest="external", help='investigar links externos [si|no]')
argumento = parser.parse_args()
url_web = argumento.url
url_web_limpio = argumento.url.replace('http://','').replace('/','').replace('www.','')
links_internos = ['/']
links_visitados = []
emails_capturados = []
mailsrch = re.compile(r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[A-Z]{2}|com|org|net|edu|gov|mil|biz|info|mobi|name|aero|asia|jobs|museum|mx|com\.mx|xxx|tv|tk)\b")
#old mailsrch = re.compile(r'[\w\-][\w\-\.]+@[\w\-][\w\-\.]+[a-zA-Z]{2,6}')
urlssrch = re.compile(r'href=[\'"]?([^\'" >]+)')
contador = 0
while links_internos:
try:
## saca el ultimo link de la lista
##print links_internos
link = links_internos.pop()
## añade ese link a visitados, para no volverlo a tener en cuenta
links_visitados.append(link)
if link[0] == '/' or link == '':
r=requests.get(url_web+''+link)
else:
r=requests.get(link)
links = urlssrch.findall( r.text)
##print 'xxxxxxxxxxxxx', links
emails = mailsrch.findall(r.text)
## guarda todos los emails que se topa checando que no existan repeticiones
for email in emails:
if email not in emails_capturados:
emails_capturados.append(email)
## guarda todos los links internos que se tope checando que no existan en la cola o en vistados
for link in links:
if not argumento.external: ## verifica si usar enlaces externos o no
if link[0] == '/' or url_web_limpio in link:
if link not in links_internos and link not in links_visitados:
links_internos.append(link)
elif argumento.external == 'si':
if link not in links_internos and link not in links_visitados:
links_internos.append(link)
contador +=1
## informacion en pantalla
if contador % 50 == 0:
if sys.platform.startswith('win'):
# Windows
os.system('cls')
elif sys.platform.startswith('linux'):
# Linux
os.system('clear')
elif sys.platform.startswith('cygwin'):
# Windows (Cygwin)
os.system('cmd /c cls')
elif sys.platform.startswith('darwin'):
# MacOSX
os.system('clear')
elif sys.platform.startswith('freebsd'):
# FreeBSD
os.system('clear')
print 'web atacada:', url_web
print 'total de emails obtenidos:', len(emails_capturados)
print 'urls recorridas: ', len(links_visitados)
print 'urls faltantes: ', len(links_internos)
print '----- (~._.)~ '
## pequeño arreglo para tener mas chanse de optener emails en web grandes
## primero analiza los enlaces internos mas cortos y despues de un tiempo, analiza los mas largos primero
## en paginas tipo blog, los enlaces mas largos son los de las post con comentarios donde posiblemente existan emails
if contador %10000 == 0:
if contador <= 10000:
links_internos.sort(reverse=True)
else:
links_internos.sort()
## si ahi un maximo de links internos rompe el ciclo y termina
if argumento.max_links:
if contador >= int(argumento.max_links):
break
## si ahi un maximo de emails capturados rompe el ciclo y termina
if argumento.max_emails:
if len(emails_capturados) >= int(argumento.max_emails):
break
## si la conexion se cae duerme el proceso 20 segundos y reintenta
except:
r = os.system('ping -c 1 google.com') ## checa si hay conexion de internet
if r == 0: #si existe conexion elimina el enlace muerto
link = links_internos.pop()
else: ##sino espera 20 segundos a que se reanude la conexion de internet
time.sleep(30)
if sys.platform.startswith('win'):
# Windows
os.system('cls')
elif sys.platform.startswith('linux'):
# Linux
os.system('clear')
elif sys.platform.startswith('cygwin'):
# Windows (Cygwin)
os.system('cmd /c cls')
elif sys.platform.startswith('darwin'):
# MacOSX
os.system('clear')
elif sys.platform.startswith('freebsd'):
# FreeBSD
os.system('clear')
print 'web atacada:', url_web
print 'total de emails obtenidos:', len(emails_capturados)
print 'urls recorridas: ', len(links_visitados)
print 'urls faltantes: ', len(links_internos)
print '----- (~._.)~ CONEXION CAIDA, ESPERANDO 30 SEGUNDOS (X__X)'
f = open('%s.txt' % url_web.replace('http://','').replace('/','').replace('.','_'),'w+')
f.write("\n".join(emails_capturados))
f.close()
mejoras en las que pueden ayudarme
no soy muy bueno con expresiones regulares
estas me funcionan en el 90 de los casos, pero derrepente tienen errores (como cuando alguien usa el @ como a/o, o no detecta urls internas si no comienzan con /)
mailsrch = re.compile(r'[\w\-][\w\-\.]+@[\w\-][\w\-\.]+[a-zA-Z]{1,4}')
urlssrch = re. compile(r'href=[\'"]?/([^\'" >]+)')
funciones que pienso agregar a futuro
** comandos para pausar las tarea y guardar donde se quedaron
** serializar cada cierto tiempo la tarea para no perder el trabajo cuando se reinicie la computadora forzosamente