基于BeautifulSoup的递归维基百科爬虫问题:深度优先遍历未正常递归
我平时帮不少人排查过这类递归爬取的问题,咱们直接从最容易踩的几个坑入手:
递归终止条件逻辑错误
这是最常见的问题!你得确保当当前深度n降到0时,立刻终止递归。比如如果你的终止条件写成了n <= 0但没写return,或者不小心把n-1传成了n,要么递归会提前停,要么无限跑下去。检查下你的终止逻辑是不是类似这样:def crawl_wiki(url, current_depth): if current_depth == 0: return # 必须明确返回,终止当前递归分支 # 后续爬取解析逻辑链接过滤不严谨导致无效/重复递归
维基百科页面里混着大量非文章链接(比如讨论页/wiki/Talk:XXX、编辑页、分类页、非英文页面),如果没过滤干净,要么递归到无效页面白忙活,要么重复爬同一链接导致死循环或栈溢出。你需要:- 只保留以
/wiki/开头且不包含:的链接(这是维基百科英文文章的标准格式) - 维护一个全局或传入的
已访问集合,每次递归前检查链接是否已经爬过,避免重复调用
- 只保留以
递归调用的参数传递错误
循环里调用递归函数时,是不是把深度参数传错了?比如应该传current_depth - 1但传成了current_depth,这样深度永远不会递减,递归根本停不下来;还有要注意Python里没有current_depth--这种自减语法,必须用current_depth - 1。正确的调用示例:for valid_link in filtered_links: if valid_link not in visited: visited.add(valid_link) crawl_wiki(valid_link, current_depth - 1) # 一定要传递减后的深度相对链接未转绝对URL
维基百科页面里的链接大多是/wiki/XXX这种相对路径,如果直接传给递归函数,请求的是无效地址。得用urljoin把相对链接转成绝对URL:from urllib.parse import urljoin base_url = "https://en.wikipedia.org" relative_link = soup.find("a")["href"] absolute_link = urljoin(base_url, relative_link)递归深度触发Python限制
Python默认递归深度限制在1000左右,如果你的目标深度n超过这个值,会直接抛出RecursionError。如果需要爬很深的层级,要么手动调整递归深度(不推荐,容易栈溢出),要么改成用栈模拟的迭代式深度优先遍历。请求异常未捕获中断递归
如果请求页面时遇到网络超时、404等错误,没加异常处理的话会直接中断整个递归流程。可以用try-except包裹请求逻辑:import requests try: response = requests.get(url, timeout=10) response.raise_for_status() # 触发HTTP状态码错误 soup = BeautifulSoup(response.text, "html.parser") except requests.exceptions.RequestException as e: print(f"请求{url}失败: {str(e)}") return # 异常时终止当前递归分支
内容的提问来源于stack exchange,提问作者user42967

