PythonでRequestsモジュールを使ってWEBページのデータを取得して、Windowsパソコンに保存したら、文字化けは起こるし、文字エンコードエラーを吐くし、やっと保存できたと思ったら改行コードが違うし。。。
自己解決したので備忘録として記録しておく。
実行環境
OS:Windows 10 Pro 1909 64bit
ブラウザ:Google Chrome 88.0.4324.104 64bit
python:3.7.4
requests:2.25.1
RequestsでWebページを取得する
まずは、RequestsモジュールでWebページを取得する
import requests url = "https://arucamo.jp/" # Webページを取得する response = requests.get(url)
このまま取得したデータを表示してみると、日本語ページの場合文字化けが起こっている時がある。
################################# # 取得した文字列データを表示 ################################# # .text 文字列データ print(response.text) # .content バイナリーデータ print(response.content) # .url アクセスしたURL print(f"URL:{response.url}") # .apparent_encoding 推測されるエンコーディング方式 print(f"エンコーディング方式:{response.apparent_encoding}") # .status_code HTTPステータスコード(200ならOK、404はページが見つからなかった等) print(f"HTTPステータスコード:{response.status_code}") # .headers レスポンスヘッダー print(f"レスポンスヘッダー:{response.headers}")
そのような場合は、requests.get()の後に次の一行を加えればほとんどの場合解決する。
import requests url = "https://arucamo.jp/" # Webページを取得する response = requests.get(url) # 文字化け防止 response.encoding = response.apparent_encoding
requestsで取得したデータをwindowsパソコンに保存
取得したデータの文字化けは上記で解決するが、そのデータをWindowsパソコンにテキストファイルとして保存すると新たな問題が起こる。
通常、Requestsモジュールで取得したデータをファイルに書き込んで保存する場合、open()でファイルを開いて、write()で書き込めば良い。
import requests url = "https://arucamo.jp/" # Webページを取得する response = requests.get(url) # 文字化け防止 response.encoding = response.apparent_encoding # 書き込むファイルを指定 filename = "download.txt" # ファイルを書き込みモードで開く f = open(filename, mode="w") # get(url)で取得したデータを書き込む f.write(response.text) # ファイルを閉じる f.close()
しかしこれを実行すると、下記のようなエラーがでる。
UnicodeEncodeError: 'cp932' codec can't encode character '\u2728' in position 74922: illegal multibyte sequence
Windowsの標準出力は、「CP932」というエンコーディングが採用されているみたい。そのためPythonのstr型(内部エンコーディングはUTF-8)のデータを標準出力したりファイルに書き込むと、CP932への変換が自動的に行われるため、CP932に変換出来ない文字がある場合はUnicodeEncodeError例外が発生する。
それを回避する方法は簡単で、ファイルを開く時のopen()に文字エンコードを指定してあげる。
# 文字エンコーディング(encoding="UTF-8")を指定 f = open(filename, mode="w", encoding="UTF-8")
これでエラーなく、utf-8で保存できるが、もう一つ問題が。。。
保存した「download.txt」ファイルを開いてみると、改行コードが「Windows(CRLF)」になっている。
これを解決する方法も先程と同じで、open()に「newline=”\n”」パラメータを追加する。
# ※windowsの場合は「encoding="UTF-8"」が必須 # これがないと「UnicodeEncodeError」エラーがでる # newline="\n"は改行コードをLFに指定 f = open(filename, mode="w" ,newline="\n", encoding="UTF-8")
まとめ
今回のコードをまとめると以下のような感じになる。
import requests url = "https://arucamo.jp/" # Webページを取得する response = requests.get(url) # 文字化け防止 response.encoding = response.apparent_encoding ################################# # 取得した文字列データを表示 ################################# # .text 文字列データ # print(response.text) # .content バイナリーデータ # print(response.content) # .url アクセスしたURL # print(f"URL:{response.url}") # .apparent_encoding 推測されるエンコーディング方式 # print(f"エンコーディング方式:{response.apparent_encoding}") # .status_code HTTPステータスコード(200ならOK、404はページが見つからなかった等) # print(f"HTTPステータスコード:{response.status_code}") # .headers レスポンスヘッダー # print(f"レスポンスヘッダー:{response.headers}") ################################# # 取得したデータをファイルに書き込む ################################# # 書き込むファイルを指定 filename = "download.txt" # ファイルを書き込みモードで開く # ※windowsの場合は「encoding="UTF-8"」が必須 # これがないと「UnicodeEncodeError」エラーがでる # newline="\n"は改行コードをLFに指定 # mode="r" 読み込み用(デフォルト) # mode="w" 書き込み用 # mode="a" 追加書き込み用 # mode="t" テキストモード(デフォルト) # mode="b" バイナリーモード f = open(filename, mode="w" ,newline="\n", encoding="UTF-8") # get(url)で取得したデータを書き込む f.write(response.text) # ファイルを閉じる f.close() # ちなみに.close()を省略できる書き方 with as # with open(filename, mode="w" ,newline="\n", encoding="UTF-8") as f: # f.write(response.text)
以上、PythonでRequestsモジュールを使ってWebページを取得したデータをWindowsパソコンに保存する場合の、文字化け、文字エンコード、改行コード対策でした。