Я работаю над простым веб-искателем в python, и я не хочу создавать простой класс очереди, но я не совсем уверен, как лучше всего начать. Я хочу что-то, что содержит только уникальные элементы для обработки, так что искатель будет сканировать только одну страницу за один раз за script (просто чтобы избежать бесконечного цикла). Может ли кто-нибудь дать мне или указать на простой пример очереди, с которым я мог бы убежать?
Я бы просто использовал набор, он не поддерживает порядок, но он поможет вам сохранить уникальность:
>>> q = set([9, 8, 7, 7, 8, 5, 4, 1])
>>> q.pop()
1
>>> q.pop()
4
>>> q.pop()
5
>>> q.add(3)
>>> q.add(3)
>>> q.add(3)
>>> q.add(3)
>>> q
set([3, 7, 8, 9]
Очень простой пример - набить каждый элемент URL в dict, но как ключ, а не как значение. Затем обрабатывать только следующий элемент, если он не находится в этих ключах:
visited = {}
# grab next url from somewhere
if url not in visited.keys():
# process url
visited[url] = 1 # or whatever, the value is unimportant
# repeat with next url
Вы можете получить более эффективную, конечно, но это было бы просто.
Если я правильно понимаю, вы хотите посещать каждую страницу только один раз. Я думаю, что лучший способ сделать это - сохранить очередь страниц, которые еще нужно посетить, и набор посещенных страниц. Проблема с другим опубликованным решением заключается в том, что после того, как вы вытащите страницу из очереди, у вас больше нет записи о том, были ли вы там.
Я бы использовал комбинацию набора и списка:
visited = set()
to_visit = []
def queue_page(url):
if url not in visited:
to_visit.append(url)
def visit(url):
visited.add(url)
... # some processing
# Add all found links to the queue
for link in links:
queue_page(link)
def page_iterator(start_url):
visit(start_url)
try:
yield to_visit.pop(0)
except IndexError:
raise StopIteration
for page in page_iterator(start):
visit(page)
Конечно, это немного надуманный пример, и вы, вероятно, лучше всего инкапсулируете это каким-то образом, но это иллюстрирует концепцию.
Почему бы вам не использовать список, если вам нужен заказ (или даже heapq, как ранее предлагалось захатерами до того, как был предложен набор), а также использовать набор для проверки дубликатов?
Я бы расширил класс списка, чтобы добавить код уникального тестирования ко всем методам используемого вами списка. Это может варьироваться от простого добавления класса .append_unique(item)
к классу или переопределения всех append
, insert
, extend
, __setitem__
, __setslice__
и т.д., Для генерирования исключения (или молчания, если вы хотите) в случае неповторимого элемента.
Например, если вы просто хотели убедиться, что метод append поддерживает уникальность:
class UniqueList(list):
def append(self, item):
if item not in self:
list.append(self, item)