Tiny HTML structural counter using the standard library parser.
| 85 | |
| 86 | |
| 87 | class TagCounter(HTMLParser): |
| 88 | """Tiny HTML structural counter using the standard library parser.""" |
| 89 | |
| 90 | def __init__(self) -> None: |
| 91 | super().__init__(convert_charrefs=True) |
| 92 | self.tags: Counter[str] = Counter() |
| 93 | self.data_chars = 0 |
| 94 | self.char_hist: Counter[str] = Counter() |
| 95 | self.max_depth = 0 |
| 96 | self._depth = 0 |
| 97 | |
| 98 | def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None: |
| 99 | self.tags[tag] += 1 |
| 100 | self._depth += 1 |
| 101 | self.max_depth = max(self.max_depth, self._depth) |
| 102 | |
| 103 | def handle_startendtag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None: |
| 104 | self.tags[tag] += 1 |
| 105 | |
| 106 | def handle_endtag(self, tag: str) -> None: |
| 107 | self._depth = max(self._depth - 1, 0) |
| 108 | |
| 109 | def handle_data(self, data: str) -> None: |
| 110 | self.data_chars += len(data) |
| 111 | for ch in data: |
| 112 | if ch in _SENSITIVE_CHARS: |
| 113 | self.char_hist[ch] += 1 |
| 114 | |
| 115 | |
| 116 | @dataclass(frozen=True) |