在列表中列出

时间:2012-03-13 23:56:25

标签: python list

第二行的目的是什么?我们不必将列表作为seed参数传入吗?我认为您可以在我们拥有tocrawl变量的所有区域中使用种子,而不是在列表中包含列表。

def crawl_web(seed):
    tocrawl = [seed]
    crawled = []
    while tocrawl:
        page = tocrawl.pop()
        if page not in crawled:
            union(tocrawl, get_all_links(get_page(page)))
            crawled.append(page)
    return crawled

编辑:完整脚本 - http://codepad.org/qxuzVkof

3 个答案:

答案 0 :(得分:6)

seed不是列表,而是单个项目,很可能是要抓取的第一个页面的网址。

虽然可以更改函数的设计以允许多个种子URL,这会使函数的签名复杂化 - 几乎每个调用者都只想从一个URL抓取。使用函数修改调用者的变量也是不好的风格;如果函数采用参数tocrawl,则必须记录(并让每个调用者都知道):

  • tocrawl表示用作初始起点的所有网址
  • tocrawl必须是list(或兼容类型);普通的可迭代支持pop。它还必须符合union期望的属性。这是非常不合理的。
  • 如果函数退出,则参数列表将为空。这意味着几乎所有调用者都希望传递列表的副本。
  • 如果函数以异常退出,tocrawl将包含尚待抓取的网址的快照。

由于最后两点基本上意味着输入参数被破坏,更好的设计是使参数成为任意可迭代的,然后然后构造一个列表。这样,调用者就不必担心所有这些愚蠢的约定。

还有一件事:您应该考虑在两个实例中使用set,而不是编写自己的union实现并使用列表存储所有已抓取的网站,如下所示:

def crawl_web(seed):
    tocrawl = set([seed])
    crawled = set()
    while tocrawl:
        page = tocrawl.pop()
        if page not in crawled:
            tocrawl.update(get_all_links(get_page(page)))
            crawled.add(page)
    return crawled

答案 1 :(得分:2)

tl; dr你的种子值不是一个列表,tocrawl不应该是一个(它应该是一个支持联合的数据结构,比如一个集合)

这是您的基本图遍历算法。如果不理解其中的上下文,很难解释一个变量的重要性,所以请允许我过度放纵你。 >:)

网络是数学家喜欢称之为图表的网站。网络上的每个地址都是图表中的节点,链接(连接两个地址)称为边缘。因此,“抓取网络”只是沿着链接边缘找到网络图中不同地址节点的路径。

def crawl_web(seed):

在每个节点,您将不得不检查要访问的新节点,您可以从当前节点访问这些节点。但你必须从某个地方开始;这里的代码通过将已知的,未访问的节点列表初始化为seed来说明从节点seed开始:

    tocrawl = [seed]

您还希望跟踪已访问的节点,这样您就不会继续绕圈:

    crawled = []

然后你必须开始你的遍历。继续爬行,直到没有更多节点要爬网。 :

    while tocrawl:

循环的每次迭代都将访问另一个节点,我们从列表中获取该节点(最初只是seed节点),方法是从末尾弹出一个值:

        page = tocrawl.pop()

不要访问以前抓取过的节点;继续:

        if page not in crawled:

我一般认为你不能在python中的列表上做联合,你可能不得不做一套这样的事情:

            # union(tocrawl, get_all_links(get_page(page)))

但它的要点是你从当前节点收集所有边缘并将它们的节点添加到已知的未抓取地址的列表(设置?)中。您可以通过以下方式定义列表并集函数,注意它没有保留顺序:

def list_union(a, b):
    # "|" is the set union operator
    return list(set(a) | set(b))

最后请记住,您已经访问过当前地址了!在链接圈中点击(周期是技术术语,循环,如果节点有自己的边缘)

     crawled.append(page)

完成所有操作后,请按照以下链接(您去过的地方)从起始地址返回 可到达 的完整地址列表。< / p>

    return crawled

现在让我们在上下文中看到整个事情:

def crawl_web(seed):
    tocrawl = [seed]
    crawled = []
    while tocrawl:
        page = tocrawl.pop()
        if page not in crawled:
            list_union(tocrawl, get_all_links(get_page(page)))
            crawled.append(page)
    return crawled

答案 2 :(得分:1)

在此算法中,种子是页面,而不是列表。

tocrawl是一个堆栈,您可以在其中收集要访问的链接页面,以便查找更多链接。