2011-08-10 11 views
2

私が作成しているpython twitterクローラーの一環として、私は複数のユーザーを何度もクロールしないようにするために "ハッシュテーブル"を作成しようとしています。それは以下の通りです。しかし、私はいくつかの問題にぶつかっています。ユーザーNYTimesKrugmanでクロールを開始すると、一部のユーザーを複数回クロールしているようです。私がユーザーcleversallie(別の完全に独立したクロールで)でクロールを開始するとき、私は何度もユーザーをクロールしません。この行動への洞察は非常に高く評価されるだろう!私は、次のようなコードを書き換えてきたご提案をもとに"Hashtable" for Python Twitter Crawler

from BeautifulSoup import BeautifulSoup 
import re 
import urllib2 
import twitter 

start_follower = "cleversallie" 
depth = 3 

U = list() 

api = twitter.Api() 

def add_to_U(user): 
    U.append(user) 

def user_crawled(user): 
    L = len(L) 
    for x in (0, L): 
     a = L[x] 
     if a != user: 
     return False 
     else: 
     return True 

def turn_to_names(users): 
    names = list() 
    for u in users: 
     x = u.screen_name 
     names.append(x) 
    return names 

def test_users(users): 
    new = list() 
    for u in users: 
     if (user_crawled): 
     new.append(u) 
    return new 

def crawl(follower,in_depth): #main method of sorts 
    if in_depth > 0: 
     add_to_U(follower) 
     users = api.GetFriends(follower) 
     names = turn_to_names(users) 
     select_users = test_users(names) 
     for u in select_users[0:5]: 
     crawl(u, in_depth - 1) 

crawl(start_follower, depth) 
for u in U: 
    print u 
print("Program done.") 

EDIT (ありがとうございました!):

import re 
import urllib2 
import twitter 

start_follower = "NYTimesKrugman" 
depth = 4 

searched = set() 

api = twitter.Api() 

def crawl(follower, in_depth): 
    if in_depth > 0: 
     searched.add(follower) 
     users = api.GetFriends(follower) 
     names = set([str(u.screen_name) for u in users]) 
     names -= searched 
     for name in list(names)[0:5]: 
      crawl(name, in_depth-1) 

crawl(start_follower, depth) 
for x in searched: 
    print x 
print "Program is completed." 

答えて

3

L =をlen(L)ではなくlen(U)に設定するバグがあります。また、,のユーザーが一致しない場合、最初のユーザーが一致しない場合はfalseを返すバグがあります。 Pythonでは、同機能は、次のいずれかのように書くことができる。test_users関数は変数としてuser_crawledを使用しています

def user_crawled(user): 
    for a in l: 
    if a == user: 
     return True 

    return False 

def user_crawled(user): 
    return user in a 

、それは実際にそれを呼び出すことはありません。また、あなたはあなたが意図したものとは逆のことをしているようですが、テストされたものではなく、テストされていないユーザーが新しいものであることを望みます。これは修正されたエラーとその関数です:

ジェネレータ関数を使用して
def test_users(users): 
    new = list() 
    for u in users: 
     if not user_crawled(u): 
     new.append(u) 
    return new 

、あなたはさらに(あなたが結果をループに意図して)機能を簡素化することができます。

def test_users(users): 
    for u in users: 
     if not user_crawled(u): 
     yield u 

ます。また、使用することができますフィルタ機能:

def test_users(users): 
    return filter(lambda u: not user_crawled(u), users) 

ハッシュベースの構造ではなく、ユーザーを格納するリストを使用しています。 Pythonは、重複することのないリスト形式の構造が必要な場合に、高速な存在テストを必要とするときに、セットを提供します。セットを減算して、あるセットのすべてのエレメントを他のセットから除去することもできます。

また、あなたのリスト(U)はユーザーのものですが、ユーザー名と照合しています。追加された各ユーザーのユーザー名だけを格納する必要があります。また、プログラムのある点でユーザーを表すためにuを使用し、別のユーザー名でユーザー名を表すためには、より意味のある変数名を使用する必要があります。

Pythonの構文上の砂糖は、すべての機能が不要になります。うわー...それは信じられないほど愚かな/ケアレスミスだ

import twitter 

start_follower = "cleversallie" 
MAX_DEPTH = 3 

searched = set() 

api = twitter.Api() 

def crawl(follower, in_depth=MAX_DEPTH): 
    if in_depth > 0: 
     searched.add(follower['screen_name']) 

     users = api.GetFriends(follower) 
     names = set([u['screen_name'] for u in users]) 

     names -= searched 
     for name in list(names)[:5]: 
     crawl(name, in_depth - 1) 

crawl(start_follower) 

print "\n".join(searched) 
print("Program done.") 
+0

Uは設定されていませんが、かなりクールに見えます。あなたはおそらく最後に "\ n" .join(検索)してください。 – koblas

+0

あなたが少し提案したものを修正した後、上記の編集を思いついた。これまでに試したいくつかのテストケースで動作しているようです。 – snehoozle

+0

@koblasうん、ありがとう。 –

3

あなたは「単なるdoesnの与えてくれたコードサンプル初心者のための仕事ですが、私はあなたの問題がハッシュテーブル(辞書?セット?)を作っていないことと関係があると思います。

Lが定義されている他の場所を見ることができない場合はL = len(L)を呼び出します。あなたは、その後、ループを持って実際にはLがlen(L)はx = Lで2回、一回のx = 0とし、1回実行されます

for x in (0, L): 
     a = L[x] 
     if a != user: 
     return False 
     else: 
     return True 

。言うまでもなく、 Lにインデックスを作成しようとすると、ループは失敗します。それはどちらの方法でも返されるif-elseを持ち、Lはどこにも定義されていないために起こることさえありません。

あなたが探している可能性が高いのは、ユーザーのチェックが付いたセットです。不在の場合は作業を行い、次にユーザーを追加します。これは次のようになります:

first_user = 'cleversallie' 
crawled_users = {first_user} #set literal 

def crawl(user, depth, max_depth): 
    friends = get_friends(first_user) 
    for friend in friends: 
     if friend not in crawled_users and depth < max_depth: 
      crawled_users.add(friend) 
      crawl(friend, depth + 1, max_depth) 

crawl(first_user, 0, 5) 

get friendsで起こることの詳細を記入することができます。これをテストしていないので構文エラーは許されませんが、それはあなたのための強力なスタートでなければなりません。

+0

:これは私がプログラム全体を書き換えるだろうかです。 L = len(U) – snehoozle

+0

私がこれを行うとき、私がcleversallieで始めるとき、私はユーザーの繰り返しがクロールされていないと思います。しかし、NYTimesKrugmanを使い始めると、2人のユーザーを再クロールします。私のコードは間違っていると言いました。あなたは、リストを使用し、指定されたユーザがリストに含まれているかどうかを調べる代わりに、辞書を使うべきであると提案しますか? – snehoozle

+0

よろしくお願いします。私はあなたの提案を考慮して、あなたに戻ってきます! – snehoozle

1

まず、このコードに多くの非python ismsというエラーがあるとしましょう。例えば

:だからあなたが本当に好きなもの[追加範囲()とすべてのユーザーをチェックする機能をメンター

def user_crawled(user): 
    L = len(U) 
    for x in (0, L): 
    a = L[x] 
    if a != user: 
     return False 
    else: 
     return True 

一度だけループを通るこの繰り返し処理...。

def user_crawled(user) : 
    L = len(U) 
    for x in range(0, L) : 
    a = L[x] 
    if a == user : 
     return True 
    return False 

もちろん、もう少しPythonの方法は、範囲をスキップしてループを反復することです。

シンプルいいですが、今は本当のPythonであなたがオペレーターと書き込み「の」にジャンプします
def user_crawled(user) : 
    for a in U : 
    if a == user : 
     return True 
    return False 

def user_crawled(user) : 
    return user in U 

さらにいくつかのPythonの思考 - リストの内包。

def test_user(users) : 
    return [u for u in users if user_crawled(u)] 

turn_to_names()にも適用できますが、これは読者の練習問題です。

関連する問題