今回は、Pythonを使ってテキストファイルからメールを抽出する方法を紹介します。
より簡単にするために、正規表現を使用することにします。
正規表現とは、コンピュータが登場する以前から、文字列操作のために使われてきた特殊な文字列のことです。
PythonでRegExを使う
正規表現という言葉は、文字列を操作し、出力のための良いフォーマットを作成するために徹底的なアプローチを行う必要があるときに、多くの意味を持ちます。
re」モジュールはPythonの組み込みモジュールです。
サブセクションでは、基本的な操作を見てから、本題に移ります。
正規表現の応用
より明確なイメージを得るために、いくつかの応用例を紹介します。
-
- 文字列の中から特定のパターンを見つける。
-
- 文中の特定のキーワードやアルファベットにマッチさせる。
- 長い文章から有用な記号やパターンを抽出します。
- 複雑な文字列操作
RegEx Python ライブラリに関する小さなチュートリアル
正規表現を使うと、与えられたテキストの中の特定のパターンにマッチさせることができます。
そこで、このトピックのために正規表現について知っておこうと思います。
メールの抽出だけでなく、BigDataのテキストのETL(Extract Transform and Load)処理でも、長い間使われてきました。
文字列に対して4つの基本的な操作を行うための関数があります。
- match()。文字列の先頭にある特定の文字列パターンにマッチさせる。
- find(): 与えられたテキストから、ある文字列パターンを見つける。
findall()。テキスト全体の中からマッチする文字列を全て探し出す。 - finditer(): マッチするパターンを見つけ、イテラブルとして返す。
特殊文字に対するマッチングの制限
特殊文字には、文字列の複雑なパターンを見つけるのに役立つ、マッチングに関与しないものがあります。
以下はそのリストです。
- 角の中括弧。[ ]
- 丸括弧:( )
- カーリーブレース。{ }
- パイプ |
- バックスラッシュ
- クエスチョンマーク。?
- プラス記号。+
- ドット演算子。”.”
- 排他的論理和(XOR)演算子。^
- アンパサンド(Ampersand):$。
- アスタリスクまたはスター演算子。*
注意点 また、パターンをマッチングするときは、文字列を宣言する前に、”r “アルファベットを使って生の文字列として指定しなければならないことに注意してください。
これにより、PythonのRegExエンジンはあらゆる種類のエラーを回避することができます。
正規表現のコンパイル
文字列操作を始めるには、まず、式をシステムにコンパイルする必要があります。
これは、上記の4つの関数を呼び出すのに役立つオブジェクトを作成することになります。
式をコンパイルするには re.compile() 関数を使用し、その関数内にパターンを挿入します。
フラグを re.UNICODE に設定します。
コード
import re
myPattern = re.compile("python", flags = re.UNICODE)
print(type(myPattern))
|
結果は、以下の通りになります。
<class 're.Pattern'>
|
これで、パターン・オブジェクトの作成に成功しました。
これを使って、関数を呼び出し、すべての操作を行います。
マッチ()関数
この関数は、文字列の開始文字がパターンにマッチした場合、オブジェクトを生成します。
コード
match = myPattern.match("python")
print(match.group())
|
結果は以下の通りです。
出力:
python |
グループ関数が呼ばれたときに、パターンにマッチするかどうかを指定することができます。
このように、パターンがサンプルの文字列と一致すると、オブジェクトが生成されます。
span()関数を使えば、マッチしたインデックスを確認することができます。
print("The pattern matches upto {0}".format(match.span()))
|
The pattern matches upto (0, 6)
|
この関数がマッチしない場合、オブジェクトは生成されないことを覚えておいてください。
返り値として NoneType が得られます。
関数 `match()’ は、マッチした文字列のインデックス位置をタプルの形で返します。
また、次の2つのパラメータも持っています。
- pos: pos: マッチするテキスト/文字列の開始位置/インデックス。
- endpos: 開始テキストの終了位置/インデックス。
例えば、以下の様になります。
match = myPattern.match("hello python", pos = 6)
print(match.group())
print("The pattern matches upto {0}".format(match.span()))
# outputpythonThe pattern matches upto (6, 12)
|
アドバンスマッチングエンティティ
文字列には、数字や空白、英数字などが含まれることがあります。
そこで、より信頼性を高めるために、文字列にはいくつかのシグネチャがある。
そこで、信頼性を高めるために、reにはいくつかの署名がある。
- d: 0から9までの整数文字にマッチするようにします。
- 2. Ⓐ:0〜9の非整数文字にマッチします。
- s: 空白文字に対応します。”ⅳ”、”ⅳt”、”ⅷ”。
- S: 空白文字以外の文字に対応します。
- w: 英数字にマッチングします。
- ⑭英数字以外の文字にマッチングします。
マッチ機能のフラグ
フラグは、ある種の複雑なテキスト解析を行う際に、特別な助け舟となる。
そこで、以下にいくつかのフラグを列挙しておく。
re.ASCII or re.A: 全てのASCIIコード文字に対応します。
1. re.ASCII or re.A: 全ての ASCII コード文字に対応: w, W, b, d, D, s, S .
2. re.DEBUG.デバッグ情報を表示します。
2. re.DEBUG:デバッグ情報を全て表示します。
re.IGNORECASE or re.I: 大文字小文字を区別しないマッチングを行います。
re.MULTILINE または re.M: 開始または終了パターンにマッチした後、直ちに改行に進みます。
フラグの詳細については、次のリンクを参照してください: https://docs.python.org/3/library/re.html#flags
search() 関数
search 関数は、文字列の中から特定のパターン/単語/アルファベット/文字を検索し、パターンが見つかればそのオブジェクトを返します。
import re
pattern = r"rain rain come soon, come fast, make the land green";
mySearch = re.search("rain", pattern, re.IGNORECASE))
print("Successfully found, ", mySearch.group(), " from", mySearch.start(), " to ",mySearch.end())
#outputSuccessfully found "rain" from 0 to 4
|
RegExモジュールを使ってメールを抽出する
基本的なことはすべて勉強したので、次はもっと大きな挑戦の番です。
ファイル読み込みと正規表現の知識を1つのコードに実装し、そのファイルからいくつかの電子メールアドレスを抽出してみましょう。
サンプルファイル
Hello my name is Tom the cat.I like to play and work with my dear friend jerry mouse. We both have our office and email addresses also. They are tomcat@gmail.com, jerrymouse@gmail.com. Our friend spike has also joined us in our company.His email address is spikethedog@gmail.com. We all entertaint the children through our show. |
ここに3つのメールアドレスを含む簡単なファイルがあります。
これもまた複雑なのですが、このコードではもっと単純にすることができます。
上記の正規表現に関する知識を使って、実装してみましょう。
このための正規表現は “[0-9a-zA-z]+@[0-9a-zA-z]+.[0-9a-zA-z]+”
コードです。
import re
try:
file = open("data.txt")
for line in file:
line = line.strip()
emails = re.findall("[0-9a-zA-z]+@[0-9a-zA-z]+.[0-9a-zA-z]+", line)
if(len(emails) > 0):
print(emails)
except FileNotFoundError as e:
print(e)
|
説明
- 英数字で始まり、”@”記号の後に再び英数字とドット”. “があり、ドットの後に再び同じ種類の文字があるテキストを抽出する、というパターンです。
- 2.ドットは直接取らず、バックスラッシュ” . “と一緒に入れることで、pythonの正規表現エンジンにドットを使うことを指定します。そのまま使用すると、改行以外の各文字をパターンに取り込むことを指定します。
- 3.次に、サンプルテキストをファイルに含めます。
-
- ファイルを読み込みモードで開く。
-
- 行変数を使ったforループを実装します。テキストを一行ずつ読み込む。
-
- 次に、テキスト内の各部を抽出するために行を切り取る。
-
- findall()関数のオブジェクトを作り、その中にパターン表記を入れ、さらにline変数を入れる。このコードでは、テキストの各ストリップをパターンと照合します。
-
- パターンがマッチしたら、それをプリントします。
-
- 外側のコードは、エラーを処理するための try-catch ブロックです。
結果は、以下の通りになります。
['tomcat@gmail.com', 'jerrymouse@gmail.com']['spikethedog@gmail.com'] |
まとめ
以上、数行のコードで、与えられたテキストからメールを抽出するスマートスクリプトを実装してみました。