【问题标题】:Queue datastruct -- find first element in queue that has not previously been queued队列数据结构——查找队列中先前未排队的第一个元素
【发布时间】:2015-01-13 11:23:58
【问题描述】:

我正在编写一个网络爬虫。当它访问一个页面时,它会拉出该页面上的所有链接(满足条件,等等)并将它们添加到要访问的页面队列中。我不希望爬虫两次访问同一页面。我当前的解决方案很笨拙:当访问一个页面时,我将 URL 添加到访问过的页面列表中(因此从队列移动到列表)。然后,当我去访问下一页时,我递归地从队列中“弹出”链接,直到我得到一个不在以前访问过的页面列表中的链接。就像我说的那样,这似乎笨拙且效率低下,必须有更好的方法。

这是我从队列中返回第一个未访问页面的代码:

def first_new_page(queue, visited): 
    ''' 
    Given a queue and list of visited pages, returns the first unvisited URL in the queue 
    '''
    if queue.empty(): 
        return -1 
    rv = queue.get()
    if rv not in visited: 
        return rv 
    else: 
        return first_new_page(queue, visited)

【问题讨论】:

  • 您没有使用scrapy,这是当今最优秀的 Python 网络爬虫框架,有什么具体原因吗?
  • 呃,没有充分的理由。事后看来,是的,我可能应该有。在这一点上,我想我会坚持我目前的设置并尝试让它变得更好(它现在可以工作,只是在寻找优化的方法)

标签: python web-scraping beautifulsoup web-crawler


【解决方案1】:

您可以简单地使用 set()

更新

好吧,在那之前我并没有真正给你一个解决方案,而是你应该如何使用 set() 的技术而不是弹出你的列表,为了完整起见,这就是你所追求的:

visited = set()

queue = ['www.google.com', 'www.yahoo.com', 'www.microsfot.com']

def crawl_the_page(link):
    # ...crawling...
    visited.add(link)
    return


# you just for through the queue list
# no need to pop the list, use the set() to compare instead
for url in queue:
    if url not in visited:
        #... do your stuff ...
        #... crawl your pages ...
        crawl_the_page(url)

【讨论】:

  • 他们说“microsfot”将成为下一个大公司 :)
  • 感谢您的回答。这样做的主要缺点是集合不保留顺序,我想按照将它们添加到队列中的顺序访问这些站点。
  • @Craig,urls 列表已按顺序排列。您只需要检查您要访问的 url(按顺序)是否在您的 set()... 中并做您的事情。 ..你明白我的意思吗?
  • 啊,是的,这是有道理的。好的,新的主要缺点是在我的情况下这将是低效的——我访问的每个页面都有大约 60 个链接,并且页面之间有很多重复。在您的解决方案中,在将页面添加到队列之前,我必须检查页面上的每个链接是否与访问过的链接相对应。在实践中,我将添加访问的最大数量,这样即使我的队列爆炸到数千个链接(重复),我也只需要减少几百个。除非有人想出更好的答案,否则我现在会给你的答案打勾:)
  • 我也可能只是误解了你的回答,所以如果我只是错过了什么,请随时将我击落!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多