AttributeError:'NoneType'对象没有'被剥离'属性,使用Python网页爬虫时出现

0 投票
4 回答
25206 浏览
提问于 2025-04-16 22:45

我正在写一个用Python爬取Twitter的程序,使用了urllib2、Python的Twitter API封装库和BeautifulSoup。不过,当我运行我的程序时,出现了以下类型的错误:

ray_krueger RafaelNadal

Traceback (most recent call last):
  File "C:\Users\Public\Documents\Columbia Job\Python Crawler\Twitter Crawler\crawlerversion9.py", line 78, in <module>
    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'

我对这种错误完全不熟悉(我是Python新手),在网上搜索也没找到什么有用的信息。我也附上了我的代码,你们有什么建议吗?

谢谢 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.")

4 个回答

0

当你在执行:request = urllib2.Request(new_url)时,new_url应该是一个字符串,但这个错误提示说它是None

你是从get_more_tweets这个函数里获取new_url的值,所以它在某个地方返回了None

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

当我们查看这段代码时,发现这个函数只有在某个链接上str(b)=="more"时才会返回值,所以你的问题是“为什么从来没有str(b)=="more"发生过?”

1

AttributeError: 'NoneType'对象没有'属性'的'strip'

这句话的意思就是:url.strip() 需要先弄清楚 url.strip 是什么,也就是要查找 urlstrip 属性。但这失败了,因为 url 是一个 'NoneType'对象,也就是说它的类型是 NoneType,就是那个特殊的对象 None

我们原本是希望 url 是一个 str,也就是一个文本字符串,因为字符串是有 strip 属性的。

这个错误发生在 File "C:\Python28\lib\urllib.py" 中,也就是 urllib 模块。这不是你的代码,所以我们需要往回查找错误信息,直到找到我们写的代码:request = urllib2.Request(new_url)。我们可以推测,传给 urllib2 模块的 new_url 最终在 urllib 的某个地方变成了 url 变量。

那么 new_url 是从哪里来的呢?我们查看出错的那行代码(注意错误追踪信息中有行号),发现前一行是 new_url = get_more_tweets(new_soup),所以我们使用的是 get_more_tweets 的结果。

分析这个函数可以发现,它会搜索一些链接,试图找到一个标记为“更多”的链接,并给我们返回第一个找到的链接的 URL。我们没有考虑的情况是,当没有这样的链接时。在这种情况下,函数会直接结束,隐式地返回 None(这是 Python 处理没有明确返回值的函数的方式,因为 Python 没有返回类型的规定,并且必须始终返回一个值),这就是这个值的来源。

可以推测,如果没有“更多”链接,那么我们就不应该尝试去跟随这个链接。因此,我们通过明确检查这个 None 返回值来修复错误,在这种情况下跳过 urllib2.Request,因为没有链接可以跟随。

顺便说一下,这个 None 值比你现在使用的 False 值更符合“占位符”的用法,表示尚未确定的 currenttime。你也可以考虑在变量和方法名中使用下划线来分隔单词,这样会让代码更易读。 :)

0

当你在

request = urllib2.Request(new_url)

这个函数 crawl() 里运行时,new_url 的值是 None。因为你是通过 get_more_tweets(new_soup) 来获取 new_url,这就说明 get_more_tweets() 返回的结果是 None

这意味着 return d 这行代码根本没有被执行,也就是说要么 str(b) == 'more' 这个条件从来没有成立过,要么 soup.findAll() 没有找到任何链接,所以 for link in links 这部分代码就没有任何作用。

撰写回答