import re
test_cases = [
"<div></div>",
"<section id='content'></section>",
'<div class="box" id="main" data-value="123"></div>',
"<div />",
"<section disabled></section>", # 属性値なし
"<p>Paragraph</p>",
"<a href='https://example.com'>Link</a>",
# セルフクローズ
"<br />",
# カスタムタグ
"<custom-tag data-x='123'></custom-tag>",
]
pattern_all = r"<([a-zA-Z0-9-]+)(\s+[a-zA-Z0-9-]+\s?=\s?(\"[^\"]*\"|'[^']*'))*\s*/?>"
for tag_str in test_cases:
match = re.search(pattern_all, tag_str)
if match:
print(f"Matched tag: {match.group(1)}")
上記のコードのうち、変数pattern_allには
htmlの任意の要素にマッチするためのパターン文字列が
格納されていますが、
それとは別に、html要素内のtext contentにマッチするためのパターンは
pattern = r'>([^<]+)<'
だということをchatGPTさんから教わったのですが、
そこで、この2つのうちのいずれかにマッチさせようとすれば、
pattern_all02 = r"<([a-zA-Z0-9-]+)(\s+[a-zA-Z0-9-]+\s?=\s?(\"[^\"]*\"|'[^']*'))*\s*/?>|>([^<]+)<"
という風に 論理演算の時に使う「|」で連結すれば
いいのでしょうか?
↓
はい、正規表現の論理和 (`|`) を使うことで、
`pattern_all` と `pattern`
の両方にマッチするパターンを作成できます。
修正後の `pattern_all02`:
```python
pattern_all02 = r"<([a-zA-Z0-9-]+)(\s+[a-zA-Z0-9-]+\s?=\s?(\"[^\"]*\"|'[^']*'))*\s*/?>|>([^<]+)<"
```
このパターンは、以下の2つの部分で構成されています:
1. `"<([a-zA-Z0-9-]+)(\s+[a-zA-Z0-9-]+\s?
=\s?(\"[^\"]*\"|'[^']*'))*\s*/?>"
`
→ HTMLのタグにマッチ(開くタグまたはセルフクローズタグ)
2. `">([^<]+)<"`
→ タグの間のテキストコンテンツにマッチ
### 確認:
試しに、以下のコードを実行して動作を確認してみましょう。
```python
import re
test_cases = [
"<div></div>",
"<section id='content'></section>",
'<div class="box" id="main" data-value="123"></div>',
"<div />",
"<section disabled></section>",
"<p>Paragraph</p>",
"<a href='https://example.com'>Link</a>",
"<br />",
"<custom-tag data-x='123'></custom-tag>",
]
pattern_all02 = r"<([a-zA-Z0-9-]+)(\s+[a-zA-Z0-9-]+\s?=\s?(\"[^\"]*\"|'[^']*'))*\s*/?>|>([^<]+)<"
for tag_str in test_cases:
matches = re.finditer(pattern_all02, tag_str)
for match in matches:
if match.group(1):
print(f"Matched tag: {match.group(1)}")
if match.group(4):
print(f"Matched text content: {match.group(4)}")
```
### 出力結果(期待されるもの):
```
Matched tag: div
Matched tag: section
Matched tag: div
Matched tag: div
Matched tag: section
Matched tag: p
Matched text content: Paragraph
Matched tag: a
Matched text content: Link
Matched tag: br
Matched tag: custom-tag
```
### まとめ:
- `|` を使うことで、タグとテキストの両方にマッチできます。
- `group(1)` はタグ名を取得
- `group(4)` はタグの間のテキストコンテンツを取得
- `re.finditer()` を使うと、
1つの文字列内に複数のマッチがある場合に対応できる
この方法で意図通り動作するはずです!
コメント
コメントを投稿