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

如何用Selenium或BeautifulSoup循环解析多级嵌套导航标签元素

电商网站多级菜单解析问题:无法获取完整三级菜单数据

问题背景

已用BeautifulSoup成功抓取一级、二级菜单,但三级菜单只能拿到每个子菜单的第一个项;Selenium的XPATH解析也未成功,目标是生成包含所有层级的DataFrame。

HTML示例

<ul class="c-nav-menu ''">
    <li class="dropDown hoverFade topNav category-6 c-furniture ">
        <a class="c-nav-category_link topnav-furniture" href="xx">
            <span>Furniture</span>
        </a>
        <div class="c-nav-columns hoverFadeTarget c-nav-columns-furniture "> 
            <div class="c-nav-columns_group columns_group-size--5">
                <div class="col col-0"> 
                    <div class="nav-columns-section-heading living-room-furniture">Living Room Furniture</div>
                        <ul>
                            <li>
                                <a href="xx2"> Sofa &amp; Sectional Collections

期望的DataFrame结构

Category 1Category 2Category 3Category 3 Link Path
FurnitureLiving Room FurnitureSofas & Sectionalshttps://www.xx./furniture/living_room/sofa
FurnitureLiving Room FurnitureChairshttps://www.xx./furniture/living_room/chairs
FurnitureLiving Room FurnitureCoffee Tableshttps://www.xx./furniture/living_room/coffee_table

已尝试的代码及问题

1. 一级菜单(成功)

nav = soup.find_all("a", {"class" : lambda L: L and L.startswith('c-nav-category_link topnav')})
for item in nav:
    level1 = {
        'cat_1': item.find("span").text}
    print(level1)

输出:

{'cat_1': 'Furniture'}
{'cat_1': 'Outdoor & Garden'}
{'cat_1': 'Rugs'}...

2. 三级菜单(仅返回每个子菜单第一个项)

final_link = soup.find_all("div", {"class" : lambda L: L and L.startswith('col col-')},"li")
for final_item in final_link:
    level3 = {
        'cat_3': final_item.find("a").text.replace('\n','')}
    print(level3)

输出:

{'cat_3': 'Sofa & Sectional Collections'}
{'cat_3': 'Bedroom Collections'}
{'cat_3': 'Dining Collections'}...

问题:只能拿到每个二级菜单下的第一个三级项,无法获取所有子项。

3. Selenium尝试(未成功)

from selenium.webdriver.common.by import By
title = driver.find_elements(by=By.XPATH, value='//*[@id="topnav-container"]/ul/li')
for li in title:
    product_data = {'title': li.text}
print(product_data)

问题:仅输出最后一个一级菜单的文本,未遍历所有层级。

解决方案

方法一:使用BeautifulSoup完整遍历层级

核心思路:从一级菜单的父节点开始,逐层遍历二级、三级菜单,确保每个层级的所有子项都被抓取。

import pandas as pd
from bs4 import BeautifulSoup

# 假设已获取完整页面HTML内容并存入html变量
soup = BeautifulSoup(html, 'html.parser')

menu_data = []

# 遍历每个一级菜单的li节点
for top_li in soup.select('ul.c-nav-menu li.dropDown'):
    # 获取一级菜单名称
    cat1 = top_li.select_one('a.c-nav-category_link span').text.strip()
    
    # 找到当前一级菜单对应的下拉列表层
    columns_container = top_li.select_one('div.c-nav-columns')
    if not columns_container:
        continue
    
    # 遍历每个二级菜单所在的col容器
    for col in columns_container.select('div.col[class^="col col-"]'):
        # 获取二级菜单名称
        cat2 = col.select_one('div.nav-columns-section-heading').text.strip()
        
        # 遍历当前二级菜单下的所有三级菜单项
        for li in col.select('ul li'):
            a_tag = li.select_one('a')
            if not a_tag:
                continue
            # 获取三级菜单名称和链接
            cat3 = a_tag.text.strip()
            cat3_link = a_tag['href']
            # 若需转为绝对链接,可取消下方注释
            # cat3_link = 'https://www.xx.com' + cat3_link
            
            # 添加到数据列表
            menu_data.append({
                'Category 1': cat1,
                'Category 2': cat2,
                'Category 3': cat3,
                'Category 3 Link Path': cat3_link
            })

# 转换为DataFrame
df = pd.DataFrame(menu_data)
print(df.head())

方法二:使用Selenium正确遍历多级菜单

核心思路:模拟鼠标悬停触发下拉菜单,逐层定位每个层级的元素,确保所有子项加载并被抓取。

import pandas as pd
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.get('你的电商网站URL')
wait = WebDriverWait(driver, 10)

menu_data = []

# 遍历所有一级菜单
top_menu_items = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, 'ul.c-nav-menu li.dropDown')))

for item in top_menu_items:
    # 鼠标悬停触发下拉菜单
    ActionChains(driver).move_to_element(item).perform()
    
    # 获取一级菜单名称
    cat1 = item.find_element(By.CSS_SELECTOR, 'a.c-nav-category_link span').text.strip()
    
    # 找到当前一级菜单的下拉容器
    columns_container = item.find_element(By.CSS_SELECTOR, 'div.c-nav-columns')
    
    # 遍历所有二级菜单容器
    col_elements = columns_container.find_elements(By.CSS_SELECTOR, 'div.col[class^="col col-"]')
    for col in col_elements:
        # 获取二级菜单名称
        cat2 = col.find_element(By.CSS_SELECTOR, 'div.nav-columns-section-heading').text.strip()
        
        # 遍历所有三级菜单项
        li_elements = col.find_elements(By.CSS_SELECTOR, 'ul li')
        for li in li_elements:
            a_tag = li.find_element(By.TAG_NAME, 'a')
            cat3 = a_tag.text.strip()
            cat3_link = a_tag.get_attribute('href')
            
            menu_data.append({
                'Category 1': cat1,
                'Category 2': cat2,
                'Category 3': cat3,
                'Category 3 Link Path': cat3_link
            })

driver.quit()

# 转换为DataFrame
df = pd.DataFrame(menu_data)
print(df.head())

内容的提问来源于stack exchange,提问作者newdev657

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 12:51:56