如何使用Beautiful Soup爬取网站菜单栏的多层级结构?
解决导航栏层级爬取问题
原代码的问题很明确:它直接把每个一级菜单项下的所有文本一股脑塞进同一个列表,完全没处理导航栏的嵌套结构——那些带下拉子菜单的项,子菜单文本被和一级标题的附属文本混在一起,自然会出现重复、层级丢失的问题。
要保留导航栏的层级结构,得用递归方式遍历每个菜单项,识别子菜单并逐层构建嵌套字典/列表,改进后的代码如下:
from bs4 import BeautifulSoup as bs import requests import json def parse_menu_item(li): # 获取当前菜单项的标题文本 title = next(li.stripped_strings) # 查找当前项的直接子菜单(不递归查找深层) sub_menu = li.find('ul', recursive=False) if sub_menu: sub_items = {} # 遍历子菜单里的每个菜单项 for sub_li in sub_menu.find_all('li', recursive=False): sub_title, sub_content = parse_menu_item(sub_li) # 根据子项类型整理结构 if sub_content: sub_items[sub_title] = sub_content else: # 处理无下级子菜单的单个项 sub_items[sub_title] = [] return title, sub_items else: # 当前项没有子菜单,返回标题和空列表标记 return title, [] url = 'https://www.trumpf.com/en_IN/' html_text = requests.get(url).text soup = bs(html_text, 'html.parser') # 定位导航栏的根菜单 nav_root = soup.select_one('nav > ul') final_menu = {} # 遍历根菜单的每个一级项 for li in nav_root.find_all('li', recursive=False): item_title, item_content = parse_menu_item(li) final_menu[item_title] = item_content # 格式化输出结果 print(json.dumps(final_menu, indent=2))
代码说明
- 核心是
parse_menu_item递归函数:每个菜单项先提取标题,再检查是否存在直接子菜单; - 若有子菜单,就递归处理每个子项,把结果整理成嵌套字典;若无子菜单,则标记为叶子节点;
- 这样能完整还原导航栏的层级关系,不会出现文本混杂、重复的问题。
内容的提问来源于stack exchange,提问作者Rovsh
相关产品推荐
相关产品推荐

