25.10.2025, 14:12
EPG a úpravy v xmltv souboru.
Občas máte k dispozici xmltv soubor, obvykle velmi rozsáhlý, a chcete z něj použít jen data pro určitý kanál nebo kanály. A občas se také stává, že identifikace kanálů je v tom konkrétním xmltv souboru jiná, než by se vám hodilo, resp. než má v sobě například playlist, na který se odkazujete. Možností, jak tohle řešit je více. Já jsem v průběhu doby narazil na několik situací, kdy jsem to řešil a vždy to bylo účelově vztažené jak ke konkrétnímu zdroji xmltv tak i ke konkrétnímu zdroji playlistu a způsobu jejich zpracování. Když jsem se nad tím zamyslel, uvědomil jsme si, že nejčastější řešení mělo následujcící atributy:
Definoval jsem si metodu (proceduru), která:
Její použití je možné např. v jednouchém (testovacím) python scriptu, který najdete v zip souboru na konci příspěvku. Všechny parametry jsou zadné v kódu, protože to je jen test!
Já metodu předpokládám použít jako součást cílového řešení scriptu, který bude peridodicky spouštěn na serveru, kde mi běží Tvheadend, ke získání EPG pro některé exotické kanály, které jsem našel v jednom existujícím xmltv. Script doplním o:
Občas máte k dispozici xmltv soubor, obvykle velmi rozsáhlý, a chcete z něj použít jen data pro určitý kanál nebo kanály. A občas se také stává, že identifikace kanálů je v tom konkrétním xmltv souboru jiná, než by se vám hodilo, resp. než má v sobě například playlist, na který se odkazujete. Možností, jak tohle řešit je více. Já jsem v průběhu doby narazil na několik situací, kdy jsem to řešil a vždy to bylo účelově vztažené jak ke konkrétnímu zdroji xmltv tak i ke konkrétnímu zdroji playlistu a způsobu jejich zpracování. Když jsem se nad tím zamyslel, uvědomil jsme si, že nejčastější řešení mělo následujcící atributy:
- ze staženého xmltv.xml souboru jsem potřeboval pouze epg pro část kanálů,
- ve staženém xmltv jsem potřeboval změnit id některých kanálů.
Definoval jsem si metodu (proceduru), která:
- načte soubor xmltv
- vybere z něj pouze ty kanály, které mě zajímají - použije se pro to seznam id kanálů a zvolí se metodoa filtrace, "include" nebo "exclude"
- podle předem definovaného slovníku (relace původní id - nové id) změní id těch kanálů, které ve slovníku najde (ostatní ponechá nezměněná)
- uloží xmltv do souboru
Kód:
from lxml import etree
def filter_xmltv(input_path, output_path, channel_ids, mode="include", replace_dict=None):
"""
Filtruje XMLTV soubor podle seznamu ID kanálů a volitelně nahrazuje ID.
:param input_path: cesta ke vstupnímu XMLTV souboru
:param output_path: cesta pro výstupní XMLTV soubor
:param channel_ids: seznam ID kanálů
:param mode: "include" nebo "exclude"
:param replace_dict: slovník pro nahrazení ID {původní_id: nové_id}, default None
"""
assert mode in ("include", "exclude"), "mode musí být 'include' nebo 'exclude'"
parser = etree.XMLParser(remove_blank_text=False)
tree = etree.parse(input_path, parser)
root = tree.getroot()
# Funkce rozhodující, zda kanál/program zůstanou
def keep_channel(cid):
if mode == "include":
return cid in channel_ids
else:
return cid not in channel_ids
# Filtruj <channel> a nahraď ID, pokud je ve slovníku
kept_channels = set() # uložení zachovaných ID po nahrazení
for ch in root.findall("channel"):
original_id = ch.get("id")
if not keep_channel(original_id):
root.remove(ch)
continue
new_id = replace_dict.get(original_id, original_id) if replace_dict else original_id
ch.set("id", new_id)
kept_channels.add(new_id)
# Filtruj <programme> a nahraď channel ID podle slovníku
for prog in root.findall("programme"):
original_id = prog.get("channel")
if not keep_channel(original_id):
root.remove(prog)
continue
new_id = replace_dict.get(original_id, original_id) if replace_dict else original_id
# pouze pokud nový ID stále patří mezi zachované kanály
if new_id in kept_channels:
prog.set("channel", new_id)
else:
root.remove(prog)
# Ulož XMLTV se zachováním formátování
tree.write(
output_path,
encoding="utf-8",
xml_declaration=True,
pretty_print=True
)Její použití je možné např. v jednouchém (testovacím) python scriptu, který najdete v zip souboru na konci příspěvku. Všechny parametry jsou zadné v kódu, protože to je jen test!
Já metodu předpokládám použít jako součást cílového řešení scriptu, který bude peridodicky spouštěn na serveru, kde mi běží Tvheadend, ke získání EPG pro některé exotické kanály, které jsem našel v jednom existujícím xmltv. Script doplním o:
- možnost zadání parametrů z příkazového řádku nebo z json souboru
- zadávané parametry budou tyto:
- vstupní soubor
- výstupní soubor
- seznam filtrovaných kanálů (volitelně jako přímo zadaný seznam nebo odkaz na soubor se seznamen)
- volba include/exclude
- slovník pro přejmenování id kanálů (volitelně jako přímo zadaný slovník nebo odkaz na soubor se slovníkem)
- vstupní soubor
- možnost načtení xmltv přímo z url adresy
- vložení výsledného xmltv do Tvheadend pomocí externího graberu
