Araña web en python

Adrian Ferreres Esteller raro82 en hotmail.com
Lun Abr 25 12:24:10 CEST 2005


Saludos lista:

      Estoy intentando realizar una araña web muy sencilla en python pero me 
da un error de socket que yo entiendo que se debe a que el socket, en algun 
lado, se cierra antes de lo previsto. El error concreto es este:

socket.error: (9, 'Bad file descriptor')

Se da en la linea 65 y el codigo de la araña es el siguiente:

import socket
import sys
from string import split
from string import find
import os
import string
import re

def aranya_web (URL,num,socket,error=1):

   mi_re = re.compile('href *= *"([^"]+)|href *= *([^ >]+)', re.IGNORECASE)

#Función que obtiene los links de una página web y devuelve una lista con 
sus enlaces
   def get_links(fn):
      enlaces=[]
      f = open(fn)
      l = f.readline()
      while l:
         for link in mi_re.findall(l):
            enlaces.append(string.join(link,''))
         l = f.readline()

      return enlaces

#Función devuelve una ruta en disco donde almacenar las páginas que la araña 
se baja
   def ruta_disco (URL):

      if URL[1]=="":
         archivo="index.htm"
         directorio=URL[0]

      else:
         archivo=URL[len(URL)-1]
         directorio=""
         for i in xrange(1,len(URL)-1):
            directorio=directorio+URL[i]+"/"


      if not os.access (directorio,os.F_OK):
         os.makedirs (directorio)

      return directorio+archivo

#Funcion que obtiene la dirección URL definitava de la página web objetivo
   def ruta_web (URL,socket):

      if URL[1]=="":
         direccion="/index.htm"
         http_request="GET "+direccion+" HTTP/1.0\r\n\r\n"

         if not socket.send (http_request):
            return "/index.html"
         else:
            return direccion

      else:
         direccion=""
         for i in xrange(1,len(URL)):
            direccion=direccion+"/"+URL[i]

      return direccion

#Funcion que, dado una dirección URL y una ruta en disco, graba una página 
web en el archivo de dicha ruta
   def pagina_web (file,direccion,socket):

      f=open (file,'w')
      http_request="GET "+direccion+" HTTP/1.0\r\n\r\n"

      if not socket.send(http_request):
         f.close()
         return -1

      linea=socket.recv (1024)

      fin_cabecera=False

      while linea:
         if fin_cabecera:
            f.write (linea)

         else:
            fin=find (linea,"\r\n\r\n")
            if fin!=-1:
               f.write(linea[fin+4:])
               fin_cabecera=True

         linea=socket.recv (1024)

      socket.close()
      f.close()
      return 1

#De la URL original nos desacemos de la subcadena "http://"
   URL= URL[7:]
#Transformamos la cadena URL en una lista donde cada uno de sus miembros son 
las subcadenas que estaban separadas por '/'
   URL= split (URL,'/')
#Obtenemos la ruta en disco donde guardar la página a bajarse
   file= ruta_disco (URL)
#Obtenemos la direccion URL de la página
   direccion=ruta_web (URL,socket)
#Nos descargamos la página al disco duro
   resultado=pagina_web (file,direccion,socket)

   if resultado==-1:
      return -1
   else:
      lista_link=get_links (file)

#Si no hay mas links en la página acabamos

   if len(lista_link)==0:
      return 1
   else:
#Si hay links en la página hacemos una llamada recursiva por cada link para 
bajarnos las páginas. Num indica el maximo de llamadas recursivas permitidas

      if num>0:
         for i in xrange (len(lista_link)):
            error=error*aranya_web (lista_link[i],num- 
len(lista_link),socket)
   return error



#Se pasa una direccion URL inicial
path= sys.argv[1]
URL= path[7:]
URL= split (URL,'/')

#Se conecta el socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect ((URL[0],80))

#Se descargan todas las páginas
resultado= aranya_web (path,20,s)

#Si el las descargas ha habido un error se comunica
if resutlado>0:
   print "Recorrido de la web realizado con exito"
else:
   print "se ha producido un error en la descarga de al menos una web"

s.close ()


¿Alguien me puede hechar luz sobre este asunto? Muchas gracias




Más información sobre la lista de distribución Python-es