第二行的目的是什么?我们不是必须传入一个列表作为我们的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
Run Code Online (Sandbox Code Playgroud)
编辑:完整的脚本 - http://codepad.org/qxuzVkof
seed 不是列表,而是单个项目,很可能是要抓取的第一个页面的URL.
虽然可以更改函数的设计以允许多个种子URL,但这会使函数的签名复杂化- 几乎每个调用者都只想从一个URL进行爬网.使用函数修改调用者的变量也是不好的风格; 如果函数将采用参数tocrawl,则必须记录(并让每个调用者都知道):
tocrawl代表所有作为初始起点的网址tocrawl必须是list(或兼容的类型); 一个普通的迭代并不能支持pop.它还必须符合union预期的属性.这是严重的不和谐.tocrawl则将包含尚未爬网的URL快照.由于最后两点本质上意味着输入参数将被破坏,更好的设计是使参数成为任意可迭代,然后构造一个列表.这样,调用者就不必担心所有这些愚蠢的约定.
还有一件事:union您应该考虑set在两个实例中使用a ,而不是编写自己的实现并使用列表存储所有已爬网站,如下所示:
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
Run Code Online (Sandbox Code Playgroud)