You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Python爬虫递归重试需用return fetch_data(link)而非直接调用?

先给你点个赞,能自己调试找到解决方法已经超棒了!咱们来唠唠你这个核心疑问——为啥这里必须用return fetch_data(link),不能直接调用函数就行?

先快速回顾下你的场景:你需要遍历多个链接,每个链接如果提取的指定title为空,就重试4次,失败就切换到下一个链接。最后你通过两处修改搞定了问题:一是把直接调用改成带return的递归,二是在if语句内、while循环外重置counter。

先贴出你修正后的完整代码:

import time
import requests
from bs4 import BeautifulSoup

links = [
    "https://stackoverflow.com/questions/tagged/web-scraping?sort=newest&page=2",
    "https://stackoverflow.com/questions/tagged/web-scraping?sort=newest&page=3",
    "https://stackoverflow.com/questions/tagged/web-scraping?sort=newest&page=4"
]
counter = 0

def fetch_data(link):
    global counter
    res = requests.get(link)
    soup = BeautifulSoup(res.text,"lxml")
    try:
        title = soup.select_one("p.tcode").text
    except AttributeError:
        title = ""
    if not title:
        while counter<=3:
            time.sleep(1)
            print("trying {} times".format(counter))
            counter += 1
            return fetch_data(link) #First fix
        counter=0 #Second fix
    print("tried with this link:",link)

if __name__ == '__main__':
    for link in links:
        fetch_data(link)

现在拆解核心问题:直接调用fetch_data(link)和用return fetch_data(link)到底差在哪?

1. 直接调用会让函数执行流程彻底混乱

如果把return fetch_data(link)改成fetch_data(link),会发生什么?

假设第一次调用fetch_data(link)发现title为空,进入if块和while循环,打印trying 0 times,counter变成1,然后直接调用fetch_data(link)——这时候确实会发起新的递归调用,但原来的函数实例根本没终止!

当新的递归调用完成(不管重试成功还是失败),程序会回到原来的函数实例,继续执行while循环的下一次迭代(因为counter已经是1,依然满足<=3),这会导致:

  • 重试次数远远超过4次,甚至陷入无限递归
  • 同一个链接会被多次打印tried with this link
  • 全局的counter会被多个函数实例互相干扰,重置逻辑完全失效

简单说,直接调用就像你开了一个新窗口干活,但原来的窗口还在继续跑流程,整个逻辑直接乱套。

用return的话,当你发起递归调用时,当前的函数实例会立即停止执行,不会继续跑后面的while循环迭代和print语句。每次重试都是一个全新的函数实例,从res = requests.get(link)开始重新执行,这样:

  • 每次重试都是独立的检查流程,不会有残留的执行逻辑干扰
  • 当重试到第4次后,counter会被重置为0,当前函数实例正常结束,回到for循环处理下一个链接
  • 最终输出会严格按照你预期的那样,每个链接重试4次后只打印一次tried with this link

举个直观的例子:第一次重试(counter=0)没拿到title,return fetch_data(link)会让当前函数“退场”,进入新的fetch_data(link)调用;新调用再次检查title,为空就继续重试,直到counter到3,重置后函数结束,顺利切换到下一个链接。

总结

递归调用时,return的核心作用是终止当前函数的执行,并把递归调用的流程完全接管过来。如果不用return,当前函数会继续执行后续代码,导致重试次数失控、流程混乱,根本达不到你想要的“重试4次就换下一个链接”的效果。

内容的提问来源于stack exchange,提问作者robots.txt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:20:26