2016年8月24日水曜日

Pythonでのスクレイピングで文字化けするときの対処

Raspberry Piで、Python3とBeautiful Soup4を使ってスクレイピングしていて、文字化けすることがあったので、そのときの対処をまとめておく。

通常は、以下のようなコードでHTMLをBeautiful Soupが解析した内容を出力できる。もちろん文字化けしない。Beautiful Soupが渡されたデータのデコードをやってくれる。
# ライブラリの読み込み
from urllib.request import urlopen
from bs4 import BeautifulSoup
 
# スクレイピングするページのurl 
url = 'http://sample.com/test.index'
 
# 指定したurlからデータを読み込む
htmlData = urlopen( url ).read()
# パーサーに「html.parser」を指定してデータを解析
htmlParsed = BeautifulSoup( htmlData, 'html.parser' )
# タグの対応がわかりやすいように整形したフォーマットで出力
print( htmlParsed.prettify() )
しかし、以下のように文字化けしてしまうケースがある。


そこで、とりあえすurllibで取得したHTMLデータの文字コードを確認してみる。文字コードを確認する方法はいくつかあるが、ここでは手っ取り早くできるのでchardetライブラリを使う(ただし遅い)。
# ライブラリの読み込み
from urllib.request import urlopen
from bs4 import BeautifulSoup
# chardetライブラリ読み込み
import chardet
 
# スクレイピングするページのurl 
url = 'http://sample.com/test.index'
 
# 指定したurlからデータを読み込む
htmlData = urlopen( url ).read()
# 文字コードの確認
result = chardet.detect( htmlData )
# 文字コード出力
print( result['encoding'] )
結果は、ISO-8859-2という聞き慣れない文字コードと判定される。


このISO-8859-2は、中央ヨーロッパの言語のための文字コードらしい。でも、スクレイピングしようとしているのは日本語のページ。念のためurllibで取得したHTMLデータをISO-8859-2でデコードしてみるが、やはり文字化けする。

そこで、おそらく本来の文字コードであろうutf-8でデコードしてみる。
# ライブラリの読み込み
from urllib.request import urlopen
from bs4 import BeautifulSoup
 
# スクレイピングするページのurl 
url = 'http://sample.com/test.index'
 
# 指定したurlからデータを読み込む
htmlData = urlopen( url ).read()
# utf-8でデコード
htmlData = htmlData.decode('utf-8')
# パーサーに「html.parser」を指定してデータを解析
htmlParsed = BeautifulSoup( htmlData, 'html.parser' )
# タグの対応がわかりやすいように整形したフォーマットで出力
print( htmlParsed.prettify() )
しかし、以下のようなエラーになってしまう。


それならばと、エラーを無視してみる。decodeメソッドの第2引数にignoreオプションを追加。
# ライブラリの読み込み
from urllib.request import urlopen
from bs4 import BeautifulSoup
 
# スクレイピングするページのurl 
url = 'http://sample.com/test.index'
 
# 指定したurlからデータを読み込む
htmlData = urlopen( url ).read()
# utf-8でデコード
htmlData = htmlData.decode('utf-8', 'ignore')
# パーサーに「html.parser」を指定してデータを解析
htmlParsed = BeautifulSoup( htmlData, 'html.parser' )
# タグの対応がわかりやすいように整形したフォーマットで出力
print( htmlParsed.prettify() )
これでやっと文字化けもエラーもなくなった。

0 件のコメント:

コメントを投稿