AttributeError: el objeto ‘NoneType’ no tiene el atributo ‘strip’ con Python WebCrawler

Estoy escribiendo un progtwig de python para rastrear twitter usando una combinación de urllib2, el contenedor de python twitter para la api, y BeautifulSoup. Sin embargo, cuando ejecuto mi progtwig, recibo un error del siguiente tipo:

ray_krueger RafaelNadal

Traceback (most recent call last): File "C:\Users\Public\Documents\Columbia Job\Python Crawler\Twitter Crawler\crawlerversion9.py", line 78, in  crawl(start_follower, output, depth) File "C:\Users\Public\Documents\Columbia Job\Python Crawler\Twitter Crawler\crawlerversion9.py", line 74, in crawl crawl(y, output, in_depth - 1) File "C:\Users\Public\Documents\Columbia Job\Python Crawler\Twitter Crawler\crawlerversion9.py", line 74, in crawl crawl(y, output, in_depth - 1) File "C:\Users\Public\Documents\Columbia Job\Python Crawler\Twitter Crawler\crawlerversion9.py", line 64, in crawl request = urllib2.Request(new_url) File "C:\Python28\lib\urllib2.py", line 192, in __init__ self.__original = unwrap(url) File "C:\Python28\lib\urllib.py", line 1038, in unwrap url = url.strip() AttributeError: 'NoneType' object has no attribute 'strip' 

No estoy familiarizado con este tipo de error (nuevo en Python) y buscarlo en línea ha dado muy poca información. También he adjuntado mi código, pero ¿tienes alguna sugerencia?

Gracias Snehizzy

 import twitter import urllib import urllib2 import htmllib from BeautifulSoup import BeautifulSoup import re start_follower = "NYTimeskrugman" depth = 3 output = open(r'C:\Python27\outputtest.txt', 'a') #better to use SQL database thanthis api = twitter.Api() #want to also begin entire crawl with some sort of authentication service def site(follower): followersite = "http://mobile.twitter.com/" + follower return followersite def getPage(follower): thisfollowersite = site(follower) request = urllib2.Request(thisfollowersite) response = urllib2.urlopen(request) return response def getSoup(response): html = response.read() soup = BeautifulSoup(html) return soup def get_more_tweets(soup): links = soup.findAll('a', {'href': True}, {id : 'more_link'}) for link in links: b = link.renderContents() if str(b) == 'more': c = link['href'] d = 'http://mobile.twitter.com' +c return d def recordlinks(soup,output): tags = soup.findAll('div', {'class' : "list-tweet"})#to obtain tweet of a follower for tag in tags: a = tag.renderContents() b = str (a) output.write(b) output.write('\n\n') def checkforstamp(soup): times = nsoup.findAll('a', {'href': True}, {'class': 'status_link'}) for time in times: stamp = time.renderContents() if str(stamp) == '3 months ago': return True def crawl(follower, output, in_depth): if in_depth > 0: output.write(follower) a = getPage(follower) new_soup = getSoup(a) recordlinks(new_soup, output) currenttime = False while currenttime == False: new_url = get_more_tweets(new_soup) request = urllib2.Request(new_url) response = urllib2.urlopen(request) new_soup = getSoup(response) recordlinks(new_soup, output) currenttime = checkforstamp(new_soup) users = api.GetFriends(follower) for u in users[0:5]: x = u.screen_name y = str(x) print y crawl(y, output, in_depth - 1) output.write('\n\n') output.write('\n\n\n') crawl(start_follower, output, depth) print("Program done. Look at output file.") 

Cuando tu lo hagas

 request = urllib2.Request(new_url) 

en crawl() , new_url es None . Como new_url de get_more_tweets(new_soup) , eso significa que get_more_tweets() está devolviendo None .

Eso significa que nunca se alcanzó el return d , lo que significa que str(b) == 'more' nunca fue verdad, o soup.findAll() no devolvió ningún enlace, así for link in links no hace nada.

AttributeError: el objeto ‘NoneType’ no tiene atributo ‘strip’

Significa exactamente lo que dice: url.strip() requiere primero averiguar qué es url.strip , es decir, buscar el atributo de strip de url . Esto falló porque url es un 'NoneType' object , es decir, un objeto cuyo tipo es NoneType , es decir, el objeto especial None .

Presumiblemente, se esperaba que la url fuera una str , es decir, una cadena de texto, ya que tienen un atributo de strip .

Esto sucedió dentro del File "C:\Python28\lib\urllib.py" , es decir, el módulo urllib . Ese no es su código, por lo que miramos hacia atrás a través del rastreo de excepciones hasta que encontramos algo que escribimos: request = urllib2.Request(new_url) . Solo podemos suponer que el new_url que pasamos al módulo urllib2 eventualmente se convierte en una variable url algún lugar dentro de urllib .

Entonces, ¿de dónde vino new_url ? Buscamos la línea de código en cuestión (observe que hay un número de línea en el rastreo de excepción) y vemos que la línea inmediatamente anterior es new_url = get_more_tweets(new_soup) , por lo que estamos usando el resultado para get_more_tweets .

Un análisis de esta función muestra que busca a través de algunos enlaces, intenta encontrar uno etiquetado como “más” y nos da la URL del primer enlace que encuentra. El caso que no hemos considerado es cuando no hay tales enlaces. En este caso, la función acaba de llegar al final e implícitamente devuelve Ninguno (así es como Python maneja las funciones que llegan al final sin un retorno explícito, ya que no hay especificación de un tipo de retorno en Python y dado que siempre se debe devolver un valor) , que es de donde viene ese valor.

Presumiblemente, si no hay un enlace ‘más’, entonces no deberíamos intentar seguir el enlace en absoluto. Por lo tanto, arreglamos el error verificando explícitamente este valor de retorno de None , y omitiendo urllib2.Request en ese caso, ya que no hay un enlace que seguir.

Por cierto, este valor None sería un valor “marcador de posición” más idiomático para el tiempo currenttime aún no determinado que el valor False que está utilizando actualmente. También puede considerar ser un poco más coherente al separar palabras con guiones bajos en sus variables y nombres de métodos para facilitar la lectura. 🙂

Cuando estás haciendo: request = urllib2.Request(new_url) , new_url supone que es una cadena, este error dice que es None .

Obtiene el valor de get_more_tweets función get_more_tweets , por lo tanto, devolvió None algún lugar.

 def get_more_tweets(soup): links = soup.findAll('a', {'href': True}, {id : 'more_link'}) for link in links: b = link.renderContents() if str(b) == 'more': c = link['href'] d = 'http://mobile.twitter.com' +c return d 

Cuando miramos este código, la función devuelve solo cuando str(b)=="more" en algún enlace, por lo que su problema es “¿Por qué nunca str (b) ==” más “sucede?”.

Estás pasando None lugar de una cadena a urllib2.Request() . Mirando el código, esto significa que new_url es None veces. Y mirando su función get_more_tweets() , que es la fuente de esta variable, vemos esto:

 def get_more_tweets(soup): links = soup.findAll('a', {'href': True}, {id : 'more_link'}) for link in links: b = link.renderContents() if str(b) == 'more': c = link['href'] d = 'http://mobile.twitter.com' +c return d 

Esta función está devolviendo un valor solo si b es "more" porque su statement de return está sangrada debajo de su if . Si es igual a cualquier otro valor, no se devuelve ningún valor (es decir, None ).

urllib2.Request() devolver siempre una URL válida aquí o debe verificar el valor de retorno de None antes de pasarlo a urllib2.Request() .