Pythonの標準ライブラリであるreを使ったHTML文書からのHTMLタグの消去

:::note info
**`OpenCV`** の不調( **`cv2.imshow()`** が使えない症状が発生)により投稿が遅れてしまいました。
記事を楽しみにしていただいている方は、お待たせしてしまい大変申し訳ございませんでした:bow:
現在は、 **`cv2.imshow()`** が問題なく使えています。
今後は、このようなこと(**記事の投稿が遅れる**)が無いよう最善を尽くします。

策としては、
- <font color="red">**<ins>事前にプログラムデータを作成</ins>**</font>
- 記事を投稿する<ins>**直前**</ins>には<font color="red">**<ins>あまり環境をいじらない</ins>**</font>

ようにすることで**余裕をもって**記事を投稿できるようにします
:::

# 目次
[はじめに](#はじめに)
[作成した経緯](#作成した経緯)
[実行環境](#実行環境)
[テキストファイル生成時の日付の取得方法](#テキストファイル生成時の日付の取得方法)
[テキストファイルのパスの設定方法](#テキストファイルの名前の設定方法)
[メインウィンドウのサイズの設定方法](#メインウィンドウのサイズの設定方法)
[メインウィンドウのタイトルの設定方法](#メインウィンドウのタイトルの設定方法)
[テキストボックスの作成方法](#テキストボックスの作成方法)
[テキストボックスの位置の設定方法](#テキストボックスの位置の設定方法)
[テキストボックスからの文字列の取得方法](#テキストボックスからの文字列の取得方法)
[取得した文字列から`HTML`タグを削除する方法](#取得した文字列から`HTML`タグを削除する方法)
[テキストボックスのデータをテキストファイルに書き込む方法](#テキストボックスのデータをテキストファイルに書き込む方法)
[文字列の末尾の改行を削除する方法](#文字列の末尾の改行を削除する方法)
[ソースコード](#ソースコード)
[結果](#結果)
[まとめ](#まとめ)

# はじめに
今回は、[**前回のTwitter(X)のアンケート**](https://twitter.com/0ca00118726208m/status/1697546075236864130)でトップだった<font color="red"><ins>**ファイル操作**</ins></font>についての記事です。
そのジャンルの中から、<font color="red">**`HTML`**</font><ins>**で書かれた文字列から**</ins><font color="red">**`HTML`**</font><ins>**タグを取り除いて**</ins>**`Windows`** <ins>**のメモ帳に**</ins><font color="red">**`HTML`**</font><ins>**タグのない文章を書き込む**</ins><ins>(テキストファイル名には、**生成時の日付**が入っている)</ins>プログラムを作成したのでそれについて紹介したいと思います。

--------

<details><summary>マイページについて</summary>

:::note info
主に<ins>**Pythonについての記事**</ins>を投稿してます!!
:::

[<font color="blue"><ins>**マイページはこちら**</ins></font>](https://qiita.com/blueman "マイページ")

</details>

<details><summary>X(Twitter)について</summary>

:::note info
<ins>**Qiitaの新着記事の通知**</ins>や<ins>**おススメの理工学書の紹介**</ins>をツイートしてます!!
:::
[<font color="blue"><ins>**X(Twitter)はこちら**</ins></font>](https://twitter.com/0ca00118726208m "X(Twitter)")

</details>

<details><summary>Zennについて</summary>

:::note info
主に<ins>**自分の書いたQiitaの記事の転載**</ins>と<ins>**Pythonを使っていて遭遇したエラーの対処法のような記事**</ins>を投稿していく予定です!!
:::
[<font color="blue"><ins>**Zennはこちら**</ins></font>](https://zenn.dev/blueman "Zenn")

</details>

# 作成した経緯
**`Qiita`** と **`Zenn`** で記事を投稿しているときに<ins>**ある問題に直面**</ins>しました!!

- **直面した問題**

**`Qiita`** では、<font color="red">**`HTML`**</font>のタグが使えるが、 **`Zenn`** では、<font color="red">**`HTML`**</font>のタグが使えない
(一部例外あり(<font color="red">**`<br>`**</font>とか))

----------

そんな時にこんなアイデアを思いつきました!!

<details><summary>思いついたアイデア</summary>

**`Qiita`** で作成した記事の <font color="red">**`HTML`**</font>タグのみを削除し、その文字列を **`Zenn`** で投稿すればよいのではないか:thinking:

</details>

このアイデアをもとに今回紹介する<font color="red">**`HTML`**</font><ins>のタグを削除する</ins>プログラムを作成しました！！

# 実行環境
実行環境は次の通りです。

<details><summary>実行環境</summary>

- **環境**
    -  **`Windows10`**
    -  **`Python 3.10.5`**

:::note info
<font color="red"> **`tkinter`** </font>、<font color="red"> **`re`** </font>は、<font color="red"><ins>**標準ライブラリ**</ins></font>なので<font color="red">**特に気にしなくても大丈夫です!!**</font>
:::

</details>

**処理内容**と**ライブラリ**の対応を分かりやすく表にすると次の通りです。
<details><summary>説明</summary>

| <font color="red">処理内容</font> | <font color="red">モジュール<br>ライブラリ</font> |
|:-:|:-:|
|**テキストボックスの作成**|<font color="red">  **`tkinter`** </font>|
|**正規表現による文字列の操作<br>(文字列から特定の文字列を削除)**|<font color="red">  **`re`** </font>|

</details>

# テキストファイル生成時の日付の取得方法
こちらのソース

https://note.nkmk.me/python-datetime-now-today/#datetime-datetimedatetimenow

によると、<font color="red">**`datetime.now()`**</font>を使うことで<font color="red">**現在日時を取得**</font>できるそうです。
この方法で<ins>プログラム実行時の日付を取得</ins>しました。

ファイル生成時の日付を取得する手順は次の通りです!!

<details><summary>取得手順</summary>
プログラムを実行すると、

1. <font color="red">**`datetime.now()`**</font>が走る
1. 現在日時(**プログラム実行時の日時**)を取得(この処理で取得された日時が**ファイル生成時の日時**となります)
</details>

### 月のデータへのアクセス方法
<font color="red">**`datetime.now()`**</font>で取得されたデータの<font color="red">**`month`**</font>にアクセスすることで<ins>月のデータを取得</ins>しました。

### 日のデータへのアクセス方法
<font color="red">**`datetime.now()`**</font>で取得されたデータの<font color="red">**`day`**</font>にアクセスすることで<ins>日のデータを取得</ins>しました。

# テキストファイルのパスの設定方法
次の手順で<ins>テキストファイルのパスを設定</ins>しました。

<details><summary>手順</summary>

1. [テキストファイル生成時の日付の取得方法](#テキストファイル生成時の日付の取得方法)で取得した日付を文字列( **`str`** 型)に型変換
1. **`./変換後文章`** と **1. で型変換した文字列**と **`.txt`** を結合

</details>

# メインウィンドウのサイズの設定方法
[前回の記事](https://qiita.com/blueman/items/ebd7ff126704bcdbf93d#%E3%83%A1%E3%82%A4%E3%83%B3%E3%82%A6%E3%82%A3%E3%83%B3%E3%83%89%E3%82%A6%E3%81%AE%E3%82%B5%E3%82%A4%E3%82%BA%E3%81%AE%E8%A8%AD%E5%AE%9A%E6%96%B9%E6%B3%95)をもとに設定しました!!

# メインウィンドウのタイトルの設定方法
こちらのソース

https://little-movie.com/window-title/

によると、<font color="red">**`title`**</font>メソッドを使うことで**メインウィンドウのタイトル**を設定できるそうです。
このメソッドを使って、<ins>メインウィンドウのタイトル</ins>を設定しました。

# テキストボックスの作成方法
こちらのソース

https://kuroro.blog/python/bK6fWsP9LMqmER1CBz9E/

によると、<font color="red">**`Text`**</font>ウィジェットを使うことで<font color="red">**`tkinter`**</font>で**テキストボックスを作成**できるそうです。
このウィジェットを使って、<ins>テキストボックスを作成</ins>しました。

# テキストボックスの位置の設定方法
こちらのソース

https://daeudaeu.com/tkinter_place/#place

によると、<font color="red">**`place`**</font>メソッドを使うことで**指定した座標上にウィジェットを配置**できるそうです。

また、こちらのソース

https://daeudaeu.com/tkinter_place/#place-2

によると、<font color="red">**`place`**</font>メソッドの**原点は左上端**にあるそうです。

また、こちらのソース

https://daeudaeu.com/tkinter_place/#place-x-y

によると、<font color="red">**`place`**</font>メソッドの<font color="red">**`x`**</font>と<font color="red">**`y`**</font>という引数で**ウィジェットを配置する座標**を指定できるそうです。

また、こちらのソース

https://daeudaeu.com/tkinter_place/#place-width-height

によると、<font color="red">**`place`**</font>メソッドの<font color="red">**`width`**</font>という引数で**ウィジェットの幅**を<font color="red">**`height`**</font>という引数で**ウィジェットの高さ**を指定できるそうです。

# テキストボックスからの文字列の取得方法
こちらのソース

https://ossa2019.stars.ne.jp/Remember/tkinter/tk6.html#i6-2

によると、<font color="red">**`get()`**</font>を使うことで**テキスト**(<font color="red">**`Text`**</font>ウィジェットのこと)**から文字列を取得**できるそうです。また、<font color="red">**`get()`**</font>の
- <ins>**第1引数**</ins>で<ins>**文字列取得の開始位置**</ins>
- <ins>**第2引数**</ins>で<ins>**文字列取得の終了位置**</ins>

を設定できるそうです。
これらの方法で、<ins>テキストボックスの文字列を取得</ins>しました。

# 取得した文字列から`HTML`タグを削除する方法
[テキストボックスからの文字列の取得方法](#テキストボックスからの文字列の取得方法)で**文字列を取得**できました。
以降は、取得された文字列をもとに処理を実行していきます。

こちらのソース

https://note.nkmk.me/python-re-match-search-findall-etc/#sub-subn

によると、<font color="red">**`re`**</font>モジュールの<font color="red">**`sub()`**</font>を使うことで**正規表現を使った文字列の置換**ができるそうです。
この方法を使って、**文字列の**<font color="red">**`HTML`**</font>**タグを[空文字](https://www.zunouissiki.com/entry/null-zero-undefined-empty-space#i-3)に置換**することで<ins>文字列から</ins><font color="red">**`HTML`**</font><ins>タグを削除</ins>しました。(空文字とは、<font color="red">**長さが0**</font>の文字列のことです)

正規表現について詳しくは下のリンクより

https://qiita.com/hayate242/items/7106977b6460c5120fb4#%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE%E6%97%A9%E8%A6%8B%E8%A1%A8

<details><summary>使用したものリスト</summary>

今回は、この早見表の中から
- <font color="red">**`\w`**</font>
- <font color="red">**`*`**</font>
- <font color="red">**`|`**</font>
- <font color="red">**`\s`**</font>
- <font color="red">**`\`**</font>

を使いました。

</details>

# テキストボックスのデータをテキストファイルに書き込む方法
こちらのソース

https://rait-09-kts.hatenablog.jp/entry/2021/07/04/212916

によると、<font color="red">**`ウィジェット名.bind('<Return>',関数名)`**</font>とすることで<ins>**エンターキーの入力により関数を実行**</ins>できるそうです。
この方法を使って、<ins>エンターキーを用いてテキストボックスのデータをテキストファイルに送信するための関数を実行</ins>させました。

また、こちらのソース

https://note.nkmk.me/python-file-io-open-with/

によると、次の手順でテキストファイルへの書き込みができるそうです。

書き込みの手順は次の通りだそうです。

1. <font color="red">**`open()`**</font>を使うことでファイルを開く。
1. ファイルオブジェクトの<font color="red">**`write()`**</font>メソッドで書き込む。

<details><summary>補足</summary>

:::note info
- <font color="red">**`open()`**</font>の<ins>**第1引数**</ins>は<ins>**ファイルのパス**</ins>、<ins>**第2引数**</ins>は<ins>**読み込みか書き込みかのモードの指定**</ins>(<font color="red">**`'r'`**</font>が**読み込みモード**、<font color="red">**`'w'`**</font>が**書き込みモード**)だそうです。
- <font color="red">**`with`**</font>を使うことで、**処理終了と同時にファイルが自動的に閉じられるそうです**。

:::

</details>

# 文字列の末尾の改行を削除する方法
[テキストボックスのデータをテキストファイルに書き込む方法](#テキストボックスのデータをテキストファイルに書き込む方法)で**エンターキー**をキーイベントとして取得させました。この方法だと、エンターキーが押されたときに<ins>**改行された**</ins>と認識してしまい<ins>**文字列の末尾に余計な改行が**</ins>入ってしまいました。

こちらのソース

https://python-jp.dev/articles/2079

によると、<font color="red">**`rstrip()`**</font>メソッドを使うことで文字列の末尾の改行を削除できるそうです。
このメソッドを使うことで、<ins>文字列の末尾の改行を削除</ins>しました。

# ソースコード
下にソースコードを示します。おそらく[実行環境](#実行環境)で示した環境では動くはず。

<details><summary>ソースコード</summary>

```python:text_trans.py
import tkinter as tk                                                #テキストボックス作成(文字列の受け取り)
import re                                                           #正規表現での文字列操作
import datetime

now = datetime.datetime.now()                                                   #テキストファイル生成時の日付を取得

path = './変換後文章'+'('+str(now.year)+'_'+str(now.month)+'_'+str(now.day)+')'+'.txt'  #テキスト形式の指定

root = tk.Tk()                                                      #tkinterの初期化
root.geometry('300x300')                                            #tkinterで作ったGUI(rootの画面のサイズ指定)
root.title('文字列変換')                                            #GUIのタイトルの設定

def func(event):                                                    #GUIの関数定義
	text = entry.get(0.,tk.END)                                   #テキストボックスからの文字列の取得(第1引数は何文字目から開始するか(今回は、1文字目からなので"1.0"と指定)第2引数は
	                                                                #何文字目まで取得するか(今回は、最後までなので"end"と指定))
	text_trans = re.sub(r"<\w*>|</\w*>|<\w*\s\w*=\"\w*\">",'',text) #正規表現で文字列から<>で囲まれた文字列と</>が含まれている文字列を削除(第1引数で正規表現で指定、第2引数で置き換える文字列、第3引数で対象の文字列を指定)
	with open(path,mode='w') as file:                               #fileという名前で書き込みモード('w')のpath('./text.txt')を開く
		file.write(text_trans.rstrip())                             #text_transの文字列をpathのファイル(変換後文章.txt)に書き込む
	print("変換後:",text_trans)                                     #動作確認用(text_transの文字列をコマンドプロンプト上に出力)

entry = tk.Text()                                                   #テキストボックスの設定
entry.place(x=0,y=0,width=300,height=300)                           #テキストボックスをどの位置にどのくらいの大きさで表示するかを設定(第1引数にx座標(今回は、一番上なので0を指定)、
                                                                    #第2引数にy座標(今回は、一番上なので0を指定)、第3引数に幅(今回は、画面いっぱいに表示させたいのでgeometryで設定した値と
                                                                    #同値)、第4引数に高さ(今回は、画面いっぱいに表示させたいのでgeometryで設定した値と同値)

entry.bind('<Return>',func)                                         #エンターキーが押される(キーイベントが'<Return>'となる)と処理(funcの中身)を実行

root.mainloop()                                                     #GUIの表示(この処理がないと一瞬表示されて消えるので表示されていないように見える)
```

</details>

# 結果
下に結果を示します。
こちらの記事で実行しました。(<ins>記事の内容が短く実行結果が分かりやすい</ins>のでこちらにしました)

https://qiita.com/blueman/items/542064585cd44f894494

こちらのGUIに入力します。

<details><summary>入力用GUI</summary>

![文字列変換_テキストボックス.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3198998/19c34de6-b0b2-e5c2-b096-6fcfbf982618.jpeg)

</details>

確認用のCUI(コマンドプロンプト上での表示結果)は次の通りです。

<details><summary>確認用CUI</summary>

![実行結果_CUI.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3198998/e2a53c40-9252-56f4-ae29-ee279d58f797.jpeg)
![実行結果_CUI_2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3198998/2d740971-12b8-5c26-5eaa-50868f4f7461.jpeg)
![実行結果_CUI_3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3198998/d0f432ed-19eb-1aad-8421-8a3c23afb0fd.jpeg)
![実行結果_CUI_4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3198998/a8867fec-343f-af59-ab27-3202a88bbd9b.jpeg)
![実行結果_CUI_5.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3198998/4f4ca327-306d-d029-c4a9-e05b72d09371.jpeg)
![実行結果_CUI_6.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3198998/8c0865be-1e25-c569-b706-84a156154b68.jpeg)
![実行結果_CUI_7.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3198998/c8dde2c1-4ab6-72d1-b36d-4ec1da76a6d0.jpeg)
![実行結果_CUI_8.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3198998/d4bedd7d-4520-88ac-44cb-33e232254b1f.jpeg)
</details>

<details><summary>テキストファイルの存在確認</summary>

![テキストファイル.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3198998/e4c3ecee-0624-559b-3bbd-1fbb2c6aab55.jpeg)

</details>
この様にテキストファイルがデスクトップ上に生成されます。

<details><summary>テキストファイルの中身</summary>

![テキストファイル_中身.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3198998/be464013-f32f-f6db-0404-5d4c42a9e774.jpeg)
![テキストファイル_中身_2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3198998/cf89ac39-f5b6-e6aa-7052-e9c0fc3f6281.jpeg)
![テキストファイル_中身_3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3198998/0096bae6-4594-c327-0616-3f49f42e8e60.jpeg)
![テキストファイル_中身_4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3198998/448ec5bf-e57e-20c9-6838-d259bd544914.jpeg)
![テキストファイル_中身_5.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3198998/d63592e0-cf09-e824-cc08-c1dde9f0f0d9.jpeg)
![テキストファイル_中身_6.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3198998/7bb20e80-55c9-c6fb-6505-12d9f508ef27.jpeg)
![テキストファイル_中身_7.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3198998/702ea849-bd36-ed5c-50d5-b568c65eb64e.jpeg)
![テキストファイル_中身_8.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3198998/0de4f1ee-870f-dfd0-bce7-2579646b2b21.jpeg)

</details>

実行結果を見ると、<font color="red">**`<img src=...>`**</font>の部分が削除されていないことが分かります。しかし、この **`HTML`** タグは<font color="red">**画像挿入**</font>の **`HTML`** タグであり<font color="red">**`Qiita`**</font>の画像挿入の **`Markdown`** 記法である<font color="red">**`![..](..)`**</font>は<font color="red">**`Zenn`**</font>でも<ins>**使える**</ins>ので問題ないです。
今後は、<font color="red">**`![..](..)`**</font>を使って画像挿入をしていこうと思います。

# まとめ
今回は、[**前回のTwitter(X)のアンケート**](https://twitter.com/0ca00118726208m/status/1697546075236864130)でトップだった<font color="red"><ins>**ファイル操作**</ins></font>から **`HTML`** <ins>**で書かれた文字列から**</ins> **`HTML`** <ins>**タグを取り除いて**</ins> **`Windows`** <ins>**のメモ帳に**</ins> **`HTML`** <ins>**タグのない文章を書き込む**</ins><ins>(テキストファイル名には、**生成時の日付**が入っている)</ins>プログラムを紹介しました。(一部の **`HTML`** タグが削除できませんでした。申し訳ございませんでした。:bow_tone1:)
この記事が実際に役に立つかどうかは分かりませんが、誰かの役に立ってくれると嬉しいです。:smiley:
記事を執筆する余力があれば、<ins>次回も記事を投稿する予定</ins>です。
    次回の予定としては、[**今回のTwitter(X)のアンケート**](https://twitter.com/blueman_info/status/1700710603302830490)でトップだった<font color="red"><ins>**動画像処理**</ins></font>から<font color="red">**`OpenCV`**</font>の[**カスケード型分類器**](https://algorithm.joho.info/machine-learning/cascade-object-detector/)の一つである<font color="red">**`Haar Cascade`**</font>で[**`Haar-like` 特徴量**](https://kabaoh.hatenablog.com/entry/2016/08/18/112647)と[**`dlib`**](https://qiita.com/nonbiri15/items/9561c8194ba0b2041bd0)を使ったPythonの**顔認証**ライブラリの[**`Face Recognition`**](https://face-recognition.readthedocs.io/en/latest/readme.html)で[**`HoG` 特徴量**](https://algorithm.joho.info/image-processing/hog-feature-value/)を使い、<ins>**それぞれの特徴量について顔認識**</ins>をさせ認識結果から<ins>**顔の部分に画像を埋め込む**</ins>プログラムができたのでそれに関する記事を投稿予定です!!
(**特徴**の部分で「少しだけ<font color="red">**`Haar-like` 特徴量**</font>と<font color="red">**`HoG` 特徴量**</font>の<ins>**違い**</ins>についても簡単に紹介できればな:smiley:」と思います!!)