Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何将其包装为递归调用_Python - Fatal编程技术网

Python 如何将其包装为递归调用

Python 如何将其包装为递归调用,python,Python,我正在用python写一只小蜘蛛。它点击一个页面,根据一个模式获取页面上的所有链接,转到每个页面,然后重复 我需要以某种方式使它递归。以下是url模式: www.example.com 然后我得到基于正则表达式的所有链接,然后我访问每个页面 递归部分: 假设我正在访问一个url如下的页面: www.example.com/category/1 www.example.com/category/1_234_4232 现在,如果此页面包含以下链接: www.example.com/catego

我正在用python写一只小蜘蛛。它点击一个页面,根据一个模式获取页面上的所有链接,转到每个页面,然后重复

我需要以某种方式使它递归。以下是url模式:

www.example.com
然后我得到基于正则表达式的所有链接,然后我访问每个页面

递归部分:

假设我正在访问一个url如下的页面:

www.example.com/category/1
www.example.com/category/1_234_4232
现在,如果此页面包含以下链接:

www.example.com/category/1_234
(基本上相同的url,只是它有一个额外的“_234234”)

我访问该页面,然后检查url,如:

www.example.com/category/1
www.example.com/category/1_234_4232
(同样,相同的url加上下划线和数字)

我一直这样做,直到没有更多的链接适合这个模式

1. visit a category page
2. does it contain links with the same url + "_dddd" if yes, visit that page
3. back to #2 unless no links

我不需要正则表达式,我只需要构造递归调用的帮助。

按照您要求的方式,仅仅递归可能不是最好的方法

首先,如果要索引的页面超过1000页,则可能会“从最底层”调用堆栈并崩溃。另一方面,如果在递归过程中不小心释放变量,它可能会消耗相当多的内存

我想推荐一些更像:

visit_next = set(['www.example.com'])
visited = set()

while len(visit_next):
    next_link = visit_next.pop()
    if next_link not in visited:
        visited.add(next_link)
        for link in find_all_links_from(next_link):
            if link not in visited:
                visit_next.add(link)
编辑:


正如我所建议的,我已经用集合重写了这个;这应该使用更少的内存(在长时间的遍历中,几乎可以肯定访问下一个列表会收集许多重复的链接)。

按照您要求的方式,仅仅递归可能不是最好的方法

首先,如果要索引的页面超过1000页,则可能会“从最底层”调用堆栈并崩溃。另一方面,如果在递归过程中不小心释放变量,它可能会消耗相当多的内存

我想推荐一些更像:

visit_next = set(['www.example.com'])
visited = set()

while len(visit_next):
    next_link = visit_next.pop()
    if next_link not in visited:
        visited.add(next_link)
        for link in find_all_links_from(next_link):
            if link not in visited:
                visit_next.add(link)
编辑:


正如我所建议的,我已经用集合重写了这个;这应该使用更少的内存(在长时间的遍历中,下一次访问列表几乎肯定会收集到许多重复的链接)。

基本上,您会像其他人一样进行此操作(有缺陷):

然而(正如也指出的那样),你必须跟踪你已经访问过的网站。一种简单(但有点有效)的方法是存储它们(可能是在“规范化”它们之后,以捕获写得不同的几乎相同的链接-例如,strip
/.*$/
)。例如:

visited = set()
def visit(url):
    content = get_content(url)
    links = extract_and_normalize_links(content)
    for link in links:
        if link not in visited:
            visited.add(link)
            visit(link)
堆栈溢出可能会成为一个问题,这取决于有多少链接(另一方面,如果达到1000次调用,脚本将运行很长时间)。如果您确实有那么多间接操作,那么应该删除递归,如另一个答案所示。或者使用堆栈(一个列表),如果您希望按照递归的顺序进行刮取:

while link_stack:
    current_page = link_stack.pop()
    # get links
    link_stack.extend(links_from_current_page)

基本上,你会像其他人那样做(有缺陷):

然而(正如也指出的那样),你必须跟踪你已经访问过的网站。一种简单(但有点有效)的方法是存储它们(可能是在“规范化”它们之后,以捕获写得不同的几乎相同的链接-例如,strip
/.*$/
)。例如:

visited = set()
def visit(url):
    content = get_content(url)
    links = extract_and_normalize_links(content)
    for link in links:
        if link not in visited:
            visited.add(link)
            visit(link)
堆栈溢出可能会成为一个问题,这取决于有多少链接(另一方面,如果达到1000次调用,脚本将运行很长时间)。如果您确实有那么多间接操作,那么应该删除递归,如另一个答案所示。或者使用堆栈(一个列表),如果您希望按照递归的顺序进行刮取:

while link_stack:
    current_page = link_stack.pop()
    # get links
    link_stack.extend(links_from_current_page)

已访问
可以是一个简单存在的集合,表示链接已被访问。最后一行中的列表
visit_next
需要
append
,而不是
add
。递归与线程一样,在适合作业的时候使用非常好,但并不总是适合作业的工具。这是一个很好的解决方案。@eumiro是对的,您应该使用一个集合,而不是带有虚假值的dict。如果你打算使用
visit_next
作为堆栈,请弹出最后一个元素,而不是第一个元素(简单的
.pop
,这是默认值)。@delnan:我认为它更像是一个队列;无论如何,集合可能是一个更好的解决方案(自动处理多次插入的值)。如果集合是重复的,则不会插入?
已访问的
可能是一个简单存在的集合,表示链接已访问。最后一行中的列表
visit_next
需要
append
,而不是
add
。递归与线程一样,在适合作业的时候使用非常好,但并不总是适合作业的工具。这是一个很好的解决方案。@eumiro是对的,您应该使用一个集合,而不是带有虚假值的dict。如果你打算使用
visit_next
作为堆栈,请弹出最后一个元素,而不是第一个元素(简单的
.pop
,这是默认值)。@delnan:我认为它更像是一个队列;无论如何,集合可能是更好的解决方案(自动处理多重插入值)。如果集合是重复的,它不会插入?