如何实现递归函数提取Beautiful Soup列表标签下的直接文本?
如何实现递归函数提取Beautiful Soup列表标签下的直接文本?
嘿,我来帮你把这个递归函数的蓝图打磨成可用的代码!你想要处理嵌套的<ul>/<ol>标签,提取每个<li>里的文本并保留嵌套结构对吧?先梳理下你原思路里的小问题,再给出调整后的完整实现:
先修正原蓝图里的几个小问题
list是Python内置关键字,不能用作变量名,得换成current_list这类合法名称- 循环遍历要精准定位当前列表的直接子
<li>,避免深层嵌套元素干扰 - 判断元素是否包含子列表,要通过Beautiful Soup的查找方法,而非直接判断类型
- 提取文本时要过滤掉子列表里的内容,只保留当前
<li>的直接文本节点
完整实现代码
from bs4 import BeautifulSoup def extract_list_items(current_list): items = [] # 只遍历当前列表的直接子li标签,不递归查找深层li for li in current_list.find_all('li', recursive=False): # 提取当前li下的直接文本(排除子列表里的文本),清理多余空格换行 direct_text = ''.join([text.strip() for text in li.find_all(text=True, recursive=False)]).strip() # 检查当前li是否包含嵌套的ul/ol列表 nested_list = li.find(['ul', 'ol']) if nested_list: # 既有直接文本又有嵌套列表:将文本与递归结果组合 if direct_text: items.append([direct_text, extract_list_items(nested_list)]) # 只有嵌套列表无直接文本:直接添加递归结果 else: items.append(extract_list_items(nested_list)) else: # 无嵌套列表:清理后文本非空才添加 if direct_text: items.append(direct_text) return items
代码关键逻辑说明
recursive=False:这个参数是核心,不管是查找<li>还是文本节点,都只处理当前节点的直接子元素,避免提前提取深层嵌套内容- 文本清理:通过列表推导式拼接所有直接文本节点,再用
strip()去除多余空格和换行,保证输出文本整洁 - 嵌套处理:遇到子列表时递归调用函数,根据当前
<li>是否有直接文本,决定是组合文本与子列表结果,还是单独添加子列表结果
用你的示例测试
拿你给出的HTML列表测试:
<ul> <li>Item 1</li> <li>Item 2</li> <li> Item 3 <ul> <li>Subitem 1</li> <li>Subitem 2</li> </ul> Item 3.1 </li> </ul>
测试代码:
html = """ <ul> <li>Item 1</li> <li>Item 2</li> <li> Item 3 <ul> <li>Subitem 1</li> <li>Subitem 2</li> </ul> Item 3.1 </li> </ul> """ soup = BeautifulSoup(html, 'html.parser') main_list = soup.find('ul') result = extract_list_items(main_list) print(result)
输出结果:
['Item 1', 'Item 2', ['Item 3Item 3.1', ['Subitem 1', 'Subitem 2']]]
额外说明
- 代码同时支持
<ul>和<ol>标签,无需额外修改 - 如果需要保留
<li>中子列表前后文本的分隔(比如把Item 3和Item 3.1分开),可以调整direct_text的生成逻辑,改成收集非空文本片段的列表 - 空的
<li>(无文本也无子列表)会被自动跳过,不会出现在结果里
备注:内容来源于stack exchange,提问作者Amjuks
相关产品推荐
相关产品推荐

