Webスクレイピングを行っていると、取得したテキストの中に全角文字と半角文字が混在しているケースに頻繁に遭遇します。
Webサイトの運営方針や入力者の癖によって、数字が全角だったりカタカナが半角だったりと、データの形式がバラバラなことは珍しくありません。
そのままデータベースに保存したり分析に使用したりすると、検索の不一致や集計ミスを招く原因となります。
本記事では、PythonのBeautifulSoupで抽出した文字列を、効率的に全角・半角変換して正規化する方法について詳しく解説します。
スクレイピングにおける文字列正規化の重要性
Webサイトから取得したデータは、必ずしも私たちが望む形式で整えられているわけではありません。
例えば、あるサイトでは商品価格が「1,980円」と全角で表記され、別のサイトでは「1,980円」と半角で表記されていることがあります。
このような表記揺れを放置すると、数値計算やフィルタリング処理が正しく動作しなくなるリスクがあります。
特に日本語のWebサイトでは、「カタカナ」「英数字」「記号」の全角・半角が混在しやすいため、前処理としての文字変換が不可欠です。
BeautifulSoupでテキストを取得した直後に変換処理を挟むことで、一貫性のあるクリーンなデータセットを作成できます。
変換に必要なライブラリの準備
Pythonで全角・半角変換を行うには、標準ライブラリのunicodedataを使用する方法と、サードパーティ製のjaconvを使用する方法があります。
今回は、より直感的で多機能な「jaconv」ライブラリを使用する方法を推奨します。
jaconvは、ひらがな・カタカナの変換や、全角・半角の相互変換を非常にシンプルに記述できるライブラリです。
まずは、BeautifulSoupとjaconvをインストールしていない場合は、以下のコマンドでインストールを行いましょう。
pip install beautifulsoup4 jaconv
これで準備は完了です。
次に、実際にBeautifulSoupで取得したテキストを変換する具体的なコードを見ていきましょう。
BeautifulSoupで取得したテキストを変換する基本手順
BeautifulSoupで抽出したテキストデータに対して、jaconvを適用する基本的な流れを解説します。
まずは、HTMLからテキストを抽出し、その文字列を全角から半角へ、または半角から全角へ変換するコード例を紹介します。
from bs4 import BeautifulSoup
import jaconv
# サンプルHTML
html_doc = """
<div id="product">
<h1>アイフォン最新モデル</h1>
<p class="price">価格:128,000円</p>
<p class="note">カラー:シルバー</p>
</div>
"""
soup = BeautifulSoup(html_doc, 'html.parser')
# 価格部分(全角数字)を取得
price_text = soup.find('p', class_='price').get_text()
# 全角を半角に変換(英数字と記号)
normalized_price = jaconv.z2h(price_text, kana=False, digit=True, ascii=True)
# 備考部分(半角カナ)を取得
note_text = soup.find('p', class_='note').get_text()
# 半角カナを全角カナに変換
normalized_note = jaconv.h2z(note_text, kana=True, digit=False, ascii=False)
print(f"元の価格: {price_text}")
print(f"変換後の価格: {normalized_price}")
print(f"元の備考: {note_text}")
print(f"変換後の備考: {normalized_note}")
元の価格: 価格:128,000円
変換後の価格: 価格:128,000円
元の備考: カラー:シルバー
変換後の備考: カラー:シルバー
このように、jaconv.z2h(Zen to Han)やjaconv.h2z(Han to Zen)を使用することで、特定の文字種だけを指定して変換することが可能です。
jaconvの主要な引数と変換オプション
jaconvの関数では、どの文字種を変換対象にするかを引数で細かく制御できます。
以下の表は、よく使われる変換オプションをまとめたものです。
| 引数名 | 説明 | デフォルト値 |
|---|---|---|
kana | カタカナの全角・半角を変換するか | True |
digit | 数字の全角・半角を変換するか | True |
ascii | 英字・記号の全角・半角を変換するか | True |
スクレイピング対象のサイトに合わせて、これらのオプションを適切に設定することが重要です。
実用的な応用:リスト内の一括変換
実際の開発では、単一の要素だけでなく、リスト形式で取得した複数の要素を一括で変換したい場面が多いでしょう。
そのような場合は、リスト内包表記を活用するとコードを簡潔に保つことができます。
from bs4 import BeautifulSoup
import jaconv
html_list = """
<ul>
<li>商品A:価格 500円</li>
<li>商品B:価格 1,200円</li>
<li>商品C:価格 8,500円</li>
</ul>
"""
soup = BeautifulSoup(html_list, 'html.parser')
items = soup.find_all('li')
# すべてのliタグ内のテキストを抽出し、全角数字を半角に変換したリストを作成
clean_items = [jaconv.z2h(item.get_text(), kana=False, digit=True, ascii=True) for item in items]
for clean_item in clean_items:
print(clean_item)
商品A:価格 500円
商品B:価格 1,200円
商品C:価格 8,500円
このように、BeautifulSoupの抽出とjaconvの変換を組み合わせることで、データクレンジングの効率が劇的に向上します。
unicodedataを使用した標準ライブラリでの変換
外部ライブラリをインストールできない環境では、Python標準のunicodedataモジュールを利用する方法もあります。
unicodedata.normalize関数を使用することで、文字の正規化を行うことが可能です。
import unicodedata
text = "Pythonプログラミング123"
# 全角英数字を半角に変換(NFKC正規化)
normalized_text = unicodedata.normalize('NFKC', text)
print(normalized_text)
Pythonプログラミング123
NFKC(Normalization Form Compatibility Composition)は、互換性に基づく分解と再合成を行う正規化形式です。
ただし、unicodedata.normalizeは「カタカナは全角のままにしたいが、数字だけは半角にしたい」といった細かな制御が難しいため、基本的にはjaconvの使用を第一選択肢にすることをおすすめします。
よくある課題と注意点
変換処理を行う際には、意図しない文字まで変換されないよう注意が必要です。
例えば、全角スペースを半角スペースに変換したくない場合や、特定の記号だけは維持したい場合などがあります。
そのような場合は、変換前にreplace()メソッドで特定の文字を退避させるか、正規表現を組み合わせて対象を絞り込む工夫が必要です。
また、スクレイピング先のサイトが提供するデータが、すでに一部だけ半角になっているような不規則な状態であっても、jaconvは一貫性を持った変換を保証してくれるため、積極的に活用しましょう。
まとめ
PythonでBeautifulSoupを使用してスクレイピングを行う際、取得データの全角・半角変換はデータ品質を保つために非常に重要な工程です。
jaconvライブラリを活用すれば、数字、カタカナ、英字といった文字種ごとに細かく制御しながら、簡単に正規化を行うことができます。
「データの表記揺れ」は分析の精度を下げる大きな要因となります。
本記事で紹介した手法を取り入れ、後続の処理がしやすい綺麗なデータを効率的に取得しましょう。
適切な正規化処理を行うことで、より高度なデータ分析や自動化システムの構築が可能になります。
