こんにちは
ちょっと長いですが、以下のようになるかなと思います。
XPath
1//*[self::h2 and not(.=preceding::h2) or self::h3 and not(.=preceding::h3) or self::h4 and not(.=preceding::h4)]
以下、サンプルです。
html
1<html><body>
2
3<h1 id="header11">AAA</h1>
4<h2 id="header21">BBB</h2>
5<h3 id="header31">CCC</h3>
6<h4 id="header41">DDD</h4>
7
8<h1 id="header12">AAA</h1>
9<h2 id="header22">BBB</h2>
10<h3 id="header32">EEE</h3>
11<h4 id="header42">FFF</h4>
12
13<h1 id="header13">AAA</h1>
14<h2 id="header23">GGG</h2>
15<h3 id="header33">EEE</h3>
16<h4 id="header43">HHH</h4>
17
18<h1 id="header14">AAA</h1>
19<h2 id="header24">GGG</h2>
20<h3 id="header34">III</h3>
21<h4 id="header44">HHH</h4>
22
23</body></html>
上記の HTML から、先のXPathで要素を取得し、タグ名および内容のテキストでソートした順に表示するプログラムをPythonで書きました。
python3
1import lxml.html
2
3
4html = '''<html><body>
5
6<h1 id="header11">AAA</h1>
7<h2 id="header21">BBB</h2>
8<h3 id="header31">CCC</h3>
9<h4 id="header41">DDD</h4>
10
11<h1 id="header12">AAA</h1>
12<h2 id="header22">BBB</h2>
13<h3 id="header32">EEE</h3>
14<h4 id="header42">FFF</h4>
15
16<h1 id="header13">AAA</h1>
17<h2 id="header23">GGG</h2>
18<h3 id="header33">EEE</h3>
19<h4 id="header43">HHH</h4>
20
21<h1 id="header14">AAA</h1>
22<h2 id="header24">GGG</h2>
23<h3 id="header34">III</h3>
24<h4 id="header44">HHH</h4>
25
26</body></html>'''
27
28
29dom = lxml.html.fromstring(html)
30
31h234s = dom.xpath(
32 '//*[self::h2 and not(.=preceding::h2) or self::h3 and not(.=preceding::h3) or self::h4 and not(.=preceding::h4)]'
33)
34
35for h in sorted(h234s, key=lambda e: f'{e.tag}#{e.text}'):
36 print(h.tag, h.text, h.attrib['id'])
37
上記を実行すると以下が出力されます。
h2 BBB header21
h2 GGG header23
h3 CCC header31
h3 EEE header32
h3 III header34
h4 DDD header41
h4 FFF header42
h4 HHH header43
以上、参考になれば幸いです。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/01/25 10:49
2020/01/25 11:26