正規表現_パターン_html_patten_all_and_textContent


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つの文字列内に複数のマッチがある場合に対応できる



この方法で意図通り動作するはずです!


コメント