MENU

スクレイピングで文字化けしたときの直し方|encoding確認の基本

当ページのリンクには広告(PR)が含まれていることがあります。
スクレイピングで文字化けしたときの直し方|encoding確認の基本のアイキャッチ

ブラウザーでは日本語が読めるのに、Pythonで取り出したタイトルだけが文字化けすることがあります。取得したバイト列、文字列への変換、保存したファイルの表示という三つの段階を分けて調べると、設定を変える場所が見えてきます。

文字コードを推測して上書きする前に、HTTPヘッダーとHTML内の指定を確認します。UTF-8でないページへ一律にUTF-8を指定しても、解決にはなりません。

目次

contentとtextの違い

Requestsのresponse.contentは、応答本文のバイト列です。response.textは、Requestsが選んだ文字コードでそのバイト列をデコードした文字列です。使用する文字コードはresponse.encodingで確認・変更できます。

HTTPヘッダーに適切なcharsetがない場合など、HTMLの中にある指定とRequestsが選ぶ値が食い違うことがあります。BeautifulSoupへバイト列を渡すと、HTML内の指定を含めて文字コードを推測できます。ただし推測が常に正しいとは限りません。

架空のUTF-8ページで確認する

次のencoding-example.htmlをUTF-8で保存します。ここではHTMLのmeta要素にUTF-8の指定があることが、入力の前提です。

<!doctype html>
<html lang="ja">
<head><meta charset="utf-8"><title>架空の請求資料</title></head>
<body><p>金額を確認します。</p></body>
</html>

練習用フォルダーでHTTPサーバーを起動し、別のターミナルからPythonを動かします。サーバーのContent-Typeにcharsetが付かない条件を想定した例です。

py -m http.server 8000 --bind 127.0.0.1
from pathlib import Path
import requests
from bs4 import BeautifulSoup

response = requests.get("http://127.0.0.1:8000/encoding-example.html", timeout=(3, 10))
response.raise_for_status()
print("HTTP:", response.headers.get("Content-Type"))
print("Requests:", response.encoding)

soup = BeautifulSoup(response.content, "html.parser")
print("BeautifulSoup:", soup.original_encoding)
print("title:", soup.title.get_text() if soup.title else "なし")

# この入力は自分でUTF-8として保存したHTMLです。
response.encoding = "utf-8"
with Path("decoded.html").open("x", encoding="utf-8") as f:
    f.write(response.text)

タイトルに「架空の請求資料」が出るかを見ます。Requestsの表示値はサーバーの応答によって変わるため、期待するコード名だけを固定して成功と判定しません。出力先のdecoded.htmlは、新規作成で保存します。

この例でresponse.encodingをUTF-8にする根拠は、自分で作った入力の保存形式です。実サイトなら、ヘッダー、meta要素、配布元の仕様、読めるはずの文字を照合して選びます。soup.original_encodingの結果を無条件に正解とする処理にもしていません。

どこで文字が変わったかを追う

取得直後のHTMLでは読めていて、CSVやテキストファイルだけがおかしい場合は、保存時と開く側の文字コードを確認します。保存形式をUTF-8にしただけで、開く側が同じ形式を使うとは限りません。

反対に、デコードした時点で文字が置換記号になっていれば、保存方法だけ変えても元の文字には戻りません。取得したバイト列を残せる条件なら、そこへ戻って変換をやり直します。errors="ignore"で読めない部分を捨てる方法は、原因を隠すことがあるため、文字を正しく取得できた確認の代わりにはなりません。

文字化けに見えても、端末のフォントや出力の表示設定の問題という場合もあります。同じ文字列をUTF-8で保存して別の表示手段で確認し、取得・デコード・保存・表示のどこから違うかを順に絞ります。

関連する作業

HTML取得の最小例と、CSVへ保存するときの文字コードは次の記事に続きます。

参考資料

この記事を書いた人

Watanabeのアバター Watanabe サイト運営者

2020年よりブログ開始。
SEOが思いのほか性にあっていたようで現在に至る。
モットーは「勝率の高い選択をする」
AIは活用するが吉、最後は人間が息を吹き込む。
アートと科学を追求し、日々精進。
―――
収益:6~7桁をウゴウゴ。
サイト:ペラサイト~中規模サイトまで運営中。
案件:1000円以上の案件をメインに取組中。
打ち手:ブラックSEO~ホワイトSEOまで
―――

目次