简单唯一的非优先级队列系统

时间:2009-02-14 18:44:54

标签: python queue

我正在使用python中的一个简单的Web爬虫,我不想创建一个简单的队列类,但我不太确定最好的启动方式。我想要的东西只包含要处理的唯一项目,因此爬虫只会在每个脚本运行时抓取每个页面一次(只是为了避免无限循环)。任何人都可以给我或指向一个我可以逃避的简单队列示例吗?

5 个答案:

答案 0 :(得分:4)

我只是使用一套,它不维持秩序,但它会帮助你保持唯一性:

>>> 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]

答案 1 :(得分:2)

一个非常简单的例子是将每个项目的URL填充到一个dict中,但作为键,而不是值。然后只处理下一个项目,如果它的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

当然,你可以提高效率,但这很简单。

答案 2 :(得分:2)

如果我理解正确,您只想访问每个页面一次。我认为最好的方法是保持一个页面队列仍然可以访问,以及一组访问过的页面。另一个发布的解决方案的问题是,一旦你从队列中弹出一个页面,你就不再记录你是否去过那里。

我会使用集合和列表的组合:

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)

当然这是一个人为的例子,你可能最好以某种方式封装它,但它说明了这个概念。

答案 3 :(得分:1)

为什么不使用列表如果你需要订单(甚至是一个heapq,就像zacherates之前建议的那样在建议集合之前)并且还使用一个集来检查重复项?

答案 4 :(得分:0)

我会扩展list类,将唯一测试代码添加到您正在使用的列表的任何方法中。这可以是简单地将.append_unique(item)添加到班级,或覆盖所有appendinsertextend__setitem____setslice__,等,在非唯一项目的情况下抛出异常(或者如果你愿意,则保持沉默)。

例如,如果您只是想确保append方法保持唯一性:

class UniqueList(list):
    def append(self, item):
        if item not in self:
            list.append(self, item)