Co tedy má být výstupem? Seznam všech listů menu? A jenom jejich názvy/odkazy, nebo i cesta k nim v menu? Pokud vám stačí jenom ty elementy s odkazy, pak to řeší XPath výraz ul//a a nepotřebujete žádnou rekurzivní funkci.
Ukážu vám kousek z kódu jak jsem se to snažil řešit.
def extract_data(parent_depth, section, url_dirname, ul_obj, in_submenu=False):
submenu_level = 1
li_obj = []
if ul_obj:
# NE VŠECHNY li MAJÍ class !!!
class_name = ul_obj[0].get("class")
submenu_level = int(class_name.split("level-")[1])
# Create Alias for current article Title
title = section
# PROBLEMATICKÝ ŘÁDEK:
li_obj = ul_obj[0].xpath('.//li[not(.//ul[@class="level-3"]//ancestor::li[@class="wnd-with-submenu"])]//a')
for li in li_obj:
... toto byla jen zahřívačka kde jsem se díval co jsem vlastně obdržel
if li_obj:
for li in li_obj:
has_submenu = "wnd-with-submenu" in li.get("class", "")
link = li.xpath('.//a[@class="menu-item"]')[0]
if link is None:
print(f"li: {etree.tostring(li, pretty_print=True).decode()}")
print("link error: exit()")
exit()
# url a název článku, plus hloubka vnoření, jsou hlavní informace, které potřebuju připravit k zápisu
url = link.get("href").strip("/")
title = link.xpath('.//span[@class="menu-item-
#submenu_ul potřebuju předat do funkce pro rekurzivní volání, na další zpracování. Takže nějak se k němu musím dostat.
if has_submenu:
submenu_ul = li.xpath('.//ul[contains(@class, "level-")]')
if debug_level > 5:
print(f"link: {etree.tostring(li, pretty_print=True).decode()}")
else:
submenu_ul = []
Pak už jen nějaký chaotický kod s komentářema (je to rozdělané a v této fázi je podstatný ten kod výše...
in_submenu = len(submenu_ul) > 0
if in_submenu:
print("In submenu...")
if not has_submenu:
print("ERR: Weird thing happened")
exit()
# VE SMYČCE SE NEMÁ SUBMENU LEVEL ZJIŠŤOVAT
# JE UŽ ZJIŠTĚN MIMO SMYČKU!
# submenu_level = int(submenu_ul[0].get("class").split("level-")[1])
print(f"\"{title}\", \"{url}\", {submenu_level}")
if debug_level>2:
if has_submenu:
print ("DEBUG in_submenu:")
extract_data(parent_depth + 1, "IN wnd-with-submenu:"+section, url_dirname, submenu_ul, in_submenu=True)
else:
print ("(DEBUG in_submenu. None submenu found)")
# print(f"submenu_ul[0]: {etree.tostring(submenu_ul[0], pretty_print=True).decode()}")
# print(f"Aktuální submenu_ul[0] třída má level {submenu_level}")
# if parent_depth != submenu_level:
# print(f"Kontrola: Rodičovská parent_depth {parent_depth} se nerovná získané ul submenu_level {submenu_level}.")
# extract_data(submenu_level, section, url_dirname, submenu_ul, in_submenu=True)
else:
print(f"\"{title}\", \"{url}\", {submenu_level}")
Celé to spouštím takto:
Načti soubor
with open("temp.html", "r") as f:
html_content = f.read()
parser = etree.HTMLParser()
tree = etree.fromstring(html_content, parser)
menu_div = tree.xpath('//div[@id="menu-slider"]')[0]
menu_nav = menu_div.xpath('.//nav[@id="menu"]')[0]
# Vyber všechny prvky <li> na první úrovni menu
items = menu_nav.xpath('.//ul[@class="level-1"]//li')
# Vybere všechny prvky <li> na DRUHÉ úrovni menu, protože
# !!! třída wnd- je na druhé úrovni !!!
# items = menu_nav.xpath('.//ul[@class="level-1"]//li[contains(@class, "wnd-")]')
Hlavní smyčka pro načtení první úrovně.
parent_depth = 1
items_count = 0
# Získej adresu na objekt link což ve skutečnosti je list item <li>...</li>
for item in items:
if item.get("class"):
in_submenu = "wnd-with-submenu" in item.get("class")
else:
in_submenu = False
if debug_level >= 2:
print("class not present")
# Získej první odkaz <a>, kde je atribut href
tag_a = item.xpath('.//a[contains(@class, "menu-item")]')[0]
url_dirname = tag_a.get("href").strip("/")
section = tag_a.xpath('.//span[@class="menu-item-text"]/text()')[0]
# Získej objekt <ul> s třídou začínající na "level-2" (ZDE JE ASI STEJNÝ PROBLÉM JAKO VÝŠE)
ul_obj = item.xpath('.//ul[contains(@class, "level-2")]')
if ul_obj:
extract_data(parent_depth, section, url_dirname, ul_obj,