Python解析未知深度HTML:避免嵌套循环及获取标签行号
HTML标签统计方案(基于Python标准库)
1. 指定文件路径读取并解析标签
xml.etree.ElementTree对非标准HTML兼容性有限,推荐使用Python标准库的html.parser模块处理——它能兼容HTML常见的非闭合标签、属性引号缺失等问题。以下是基础实现思路:
from html.parser import HTMLParser import os # 自定义解析器类,继承HTMLParser class TagCounterParser(HTMLParser): def __init__(self): super().__init__() # 存储统计结果:键为标签名,值为(出现次数, 行号列表) self.tag_stats = {} # 处理每个起始标签 def handle_starttag(self, tag, attrs): # 获取当前标签的行号 line_no = self.getpos()[0] # 更新统计数据 if tag not in self.tag_stats: self.tag_stats[tag] = (0, []) count, line_list = self.tag_stats[tag] self.tag_stats[tag] = (count + 1, line_list + [line_no]) # 读取并解析指定路径的HTML文件 def parse_html_file(file_path): if not os.path.isfile(file_path): raise FileNotFoundError(f"文件不存在:{file_path}") with open(file_path, 'r', encoding='utf-8') as f: html_content = f.read() parser = TagCounterParser() parser.feed(html_content) return parser.tag_stats
2. 递归处理未知嵌套深度
HTMLParser内部会自动遍历整个DOM结构,无论标签嵌套深度如何,无需手动写多层循环。如果一定要用显式递归(比如处理XML合规的HTML),可基于ElementTree实现:
import xml.etree.ElementTree as ET # 递归遍历元素并统计 def recursive_tag_count(element, tag_stats): # 统计当前标签 tag = element.tag line_no = element.sourceline # 获取行号(需解析时保留位置信息) if tag not in tag_stats: tag_stats[tag] = (0, []) count, line_list = tag_stats[tag] tag_stats[tag] = (count + 1, line_list + [line_no]) # 递归处理子元素 for child in element: recursive_tag_count(child, tag_stats) # 基于ElementTree的解析方法(仅支持XML合规的HTML) def parse_with_elementtree(file_path): # 解析时保留位置信息 parser = ET.XMLParser(target=ET.TreeBuilder(insert_comments=True)) tree = ET.parse(file_path, parser=parser) root = tree.getroot() tag_stats = {} recursive_tag_count(root, tag_stats) return tag_stats
注意:显式递归仅适用于严格符合XML规范的HTML,实际场景更推荐用HTMLParser。
3. 获取标签行号
- 用
HTMLParser时:直接调用self.getpos()[0]即可获取当前标签的起始行号,该方法返回元组(行号, 列号)。 - 用
ElementTree时:需在解析时指定XMLParser的target为带位置记录的TreeBuilder,之后通过元素的sourceline属性获取行号,但此方法对非标准HTML支持差。
完整使用示例
if __name__ == "__main__": target_file = "./your_html_file.html" # 替换为你的文件路径 try: stats = parse_html_file(target_file) # 打印统计结果 print("标签统计详情:") for tag, (count, lines) in sorted(stats.items()): print(f"{tag}: 出现{count}次,行号:{', '.join(map(str, lines))}") except Exception as e: print(f"处理出错:{str(e)}")
内容的提问来源于stack exchange,提问作者user3084383
相关产品推荐
相关产品推荐

