1

我正在用python开发一个简单的网络爬虫,我不想做一个简单的队列类,但我不太确定最好的开始方式。我想要只包含要处理的唯一项目的东西,以便爬虫在每次脚本运行时只爬取每个页面一次(只是为了避免无限循环)。任何人都可以给我或指向我可以运行的简单队列示例吗?

4

5 回答 5

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]
于 2009-02-14T18:48:41.027 回答
2

一个非常简单的示例是将每个项目的 URL 填充到一个字典中,但作为键,而不是作为值。如果它的 url 不在该字典的键中,则仅处理下一个项目:

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

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

于 2009-02-14T18:57:16.717 回答
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)

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

于 2009-02-14T19:10:31.583 回答
1

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

于 2009-02-14T18:54:19.140 回答
0

我将扩展列表类以将唯一测试代码添加到您正在使用的列表的任何方法中。这可以从简单地将 a 添加.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)
于 2009-02-14T21:17:40.890 回答