2011-08-02 49 views
0

urllib2、apiのpython twitterラッパー、BeautifulSoupの組み合わせを使用して、Twitterのクロールを行うPythonプログラムを作成しています。私は私のプログラムを実行するときしかし、私は次のタイプのエラーが表示されます。AttributeError: 'NoneType'オブジェクトにPython WebCrawler属性 'strip'がありません

ray_krueger ラファエル・ナダル

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.") 
+0

クローラは本来、フォロワーを特定して美しいスープを使って自分のページを解析し、3ヶ月のつぶやきになるまで動作します。それから、それは各フォロワーの最初の5人のフォロワーに行きます。そして、同じプロセスを、指定した深さに達するまで繰り返します。 – snehoozle

答えて

0

あなたはcrawl()

request = urllib2.Request(new_url) 

を行うと、new_urlNoneです。 new_urlget_more_tweets(new_soup)から取得すると、get_more_tweets()Noneを返します。 return dを意味

str(b) == 'more'が本当ではなかった、またはsoup.findAll()はそうfor link in linksは何もしない任意のリンクを返さなかったのいずれかを意味し、到達していませんさん。

+0

ありがとう!私はちょうど私が自分のコードを書いた方法であることを認識しました - 私は、各ツイッターユーザーがつぶやきの1ページ以上を持つと仮定しました。しかし、これは最初の3つのつぶやきをクロールした後にヒットした第4人の場合のようには見えません。したがって、私がその4番目のユーザーに到達し、クローラがより多くのつぶやきを提供する "more"リンクを見つけようとするとき、それはしません。それは、究極のエラーを引き起こすNoneを返します。私はこれを自分のコードで考慮に入れ、あなたの更新を続けていきます。 – snehoozle

+0

それを傷つける。私はちょうどそれが2人目のユーザーであることに気づいた - Rafael Nadalはtwitterに新しい人で、つぶやきの1ページしか持っていなかった... Ha! – snehoozle

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)==」よりは「どうなりますか?」であるので、関数は、いくつかのリンク上の場合にのみ、str(b)=="more"を返します。

0

文字列ではなくNoneurllib2.Request()に渡しています。コードを見ると、new_urlNoneになることがあります。そして、この変数の源である、あなたのget_more_tweets()機能、見て、私たちはこの参照してください。

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 

をこの関数は、あなたのreturn文があなたのifの下にインデントされているためb"more"ある場合にのみ値を返しています。値が他の値と等しい場合は、値は返されません(つまりNone)。

ここで有効なURLを返すか、urllib2.Request()に渡す前にNoneの戻り値をチェックする必要があります。

1

AttributeError: 'NoneType' object has no attribute 'strip'

それが言う正確に何を意味しますurl.strip()は最初、すなわちurlstrip属性を見上げ、url.stripが何であるかを考え出す必要です。これは、url'NoneType' objectであるオブジェクト、つまりタイプがNoneTypeのオブジェクト、つまり特殊オブジェクトNoneであるため失敗しました。

おそらくurlstrであると予想されました。つまり、テキスト文字列はstrip属性を持つためです。

これは、File "C:\Python28\lib\urllib.py"のモジュール内で発生しました。すなわち、urllibモジュールです。これはあなたのコードではないので、私たちが書いたものが見つかるまで、例外トレースを振り返ります:request = urllib2.Request(new_url)urllib2モジュールに渡すnew_urlは、最終的にのどこかの変数urlになると推定できます。

だからnew_urlはどこから来たのですか?問題のコード行を調べると(例外トレースバックに行番号があることに気づく)、直前の行がnew_url = get_more_tweets(new_soup)であることがわかりますので、get_more_tweetsの結果を使用しています。

この関数を分析すると、いくつかのリンクを検索し、「more」というラベルの付いたものを見つけようとしていて、見つかった最初のリンクのURLを返します。私たちが考慮していないケースは、そのようなリンクがない場合です。この場合、関数はちょうど終わりに達し、暗黙的にNoneを返します(Pythonで戻り値の型が指定されておらず、常に値を返さなければならないため、Pythonは明示的な戻り値なしに関数を処理します)それはその価値がどこから来るのかです。

おそらく、「より多くの」リンクがない場合は、リンクをたどってみるべきではありません。したがって、このNoneの戻り値を明示的にチェックしてエラーを修正し、その場合はurllib2.Requestをスキップします。これに続くリンクがないためです。

ちなみに、このNoneの値は、現在使用しているFalseの値よりも未定義のcurrenttimeの慣用的な「プレースホルダ」の値になります。また、読みやすくするために、変数とメソッド名のアンダースコアで単語を区切ることについてもう少し一貫していると考えるかもしれません。 :)