«Hashtable» для Python Twitter Crawler - PullRequest
       12

«Hashtable» для Python Twitter Crawler

2 голосов
/ 11 августа 2011

Как часть создателя python-твиттера, который я создаю, я пытаюсь создать своего рода «хэш-таблицу», чтобы гарантировать, что я не сканирую ни одного пользователя более одного раза. Это ниже. Однако я сталкиваюсь с некоторыми проблемами. Когда я начинаю сканировать пользователя NYTimesKrugman, я, кажется, сканирую некоторых пользователей более одного раза. Когда я начинаю сканировать пользователя cleversallie (в другом полностью независимом сканировании), я не сканирую ни одного пользователя более одного раза. Любое понимание этого поведения будет с благодарностью!

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 ]

3 голосов
/ 11 августа 2011

У вас есть ошибка, когда вы устанавливаете L = len (L), а не len (U). Кроме того, у вас есть ошибка, из-за которой вы будете возвращать false, если первый пользователь не соответствует, а не если каждый пользователь не соответствует. В Python та же функция может быть написана как одно из следующих:

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

  return False

def user_crawled(user):
  return user in a

Функция test_users использует user_crawled в качестве переменной, на самом деле она ее не вызывает. Кроме того, кажется, что вы делаете обратное тому, что вы намерены, вы хотите, чтобы новые были заполнены непроверенными пользователями, а не проверенными. Это функция с исправленными ошибками:

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.")
3 голосов
/ 11 августа 2011

Пример кода, который вы дали просто, не работает для начинающих, но я полагаю, что ваша проблема связана с отсутствием создания хэш-таблицы (словарь? Set?).

Вы звоните L = len(L), когда я больше нигде не вижу, что L определено. Тогда у вас есть цикл,

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

, который будет фактически выполняться дважды, один раз с x = 0 и один раз с x = L, где L - это len (L). Само собой разумеется, когда вы пытаетесь проиндексировать в 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)

Вы можете заполнить детали того, что происходит в друзьях. Не проверял это, так что извините за любые синтаксические ошибки, но это должно стать сильным началом для вас.

1 голос
/ 11 августа 2011

Давайте начнем с того, что в этом коде есть много ошибок, множество из-не-python-символов.

Например:

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

Это повторяется только один раз в цикле ...Таким образом, вы действительно имеете в виду что-то вроде [добавление range () и возможность проверки всех пользователей.

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

Теперь, конечно, немного более питонским способом было бы пропустить диапазон и просто перебрать цикл.

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

Это довольно просто, но теперь в истинном python вы можете перейти к оператору "in" и написать:

def user_crawled(user) :
  return user in U

Еще несколько мыслей по питону - список пониманий

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

Что также может быть применено к turn_to_names () - оставлено в качестве упражнения для читателя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...