先日投稿したPythonでアクセスしたWebページのテキストのみの取り出し(Selenium, Beautiful Soup)で取り出したテキストに不要な空白が多く見られた。
そこで、Pythonで英単語間の空白を残したまま、日本語間の空白の除去をやってみたので備忘録。
OS : macOS Sierra(10.12.3)
Python : 3.5.1
コード
入力は日本語版wilipediaのトップページのテキストを抽出したときに見られた不要な空白を含む文章です。
import re
str = "ウィキペディア へようこそ ウィキペディアは 誰でも編集できる フリー 百科事典 です。"
result = re.sub('([あ-んア-ン一-龥ー])\s+((?=[あ-んア-ン一-龥ー]))',r'\1\2', str)
print(str)
print(result)
ウィキペディア へようこそ ウィキペディアは 誰でも編集できる フリー 百科事典 です。
ウィキペディアへようこそウィキペディアは誰でも編集できるフリー百科事典です。
簡単な解説
文字列の置換の手法
Pythonでは文字列の置換の方法は2種類あるようです。今回は正規表現を使いたいので、re.subを用います。
- replace(正規表現なし)
置換後の文字列 = 対象の文字列.replace(置換される文字列, 置換する文字列 [, 回数])
- re.sub(正規表現あり)
置換後の文字列 = re.sub(正規表現パターン, 置換する文字列, 置換される文字列 [, 回数])
正規表現
([あ-んア-ン一-龥ー])\s+((?=[あ-んア-ン一-龥ー]))
- [あ-んア-ン一-龥ー]
[]が集合を表しますので、上記の正規表現は「ひらがな、カタカナ、漢字、長音」のいずれか一文字にマッチします。
- \s+
\sが空白を、+が1回以上の繰り返しを表すので、1回以上の空白にマッチします。
- ?=
Pythonでの肯定先読みの表現です。「xx(?=oo)」で、「ooが後に付くxx」にマッチします。ですので、今回は「日本語が後に付く、日本語+一文字以上の空白」にマッチします。
なぜこのようなことをしているのかと言うと、例えば、「日 本 語」という文字列の空白を除去しようと考えた場合、肯定先読みを用いず、日本語の間の空白を除去しようとするとします。すると、まず「日 本」にマッチして置換します。そしてその後、既に「本」にはマッチしていますので、「 語」にはマッチせず、最終的に「日本 語」と言う置換のされ方になってしまいます。
しかし、肯定先読みを使っていると、「日本語が後に付く、日本語+一文字以上の空白」にマッチするので、まず「日 」にマッチし、次に「本 」にマッチするので、最終的には「日本語」という結果が得られます。
- r'\1\2'
かっこで指定したマッチした部分の一つ目と二つ目を繋げるように置換します。これで空白を取り除いています。ここでもし、r'\1-\2'と記述した場合は、日本語に挟まれた空白が-に置き替わります。
まとめ
以上です。
間違いや改善点等があったらコメントで指摘して頂ければ幸いです。