【Python】BeautifulSoupでのスクレイピング時の文字化けを解消する簡単な方法



みなさんどうもばーちゃるめがねです。
この間Pythonのライブラリの一つであるBeautifulSoupでスクレイピングする記事を書かせていただきました。
【Python】Pythonでtableをスクレイピングしてcsvファイルに出力する
この方法でいっぱい表をスクレイピングして遊んでいたのですが、突然それはやってきたのです…

[ÁóÀÀ·õ]¥ß¥å¥ë¥°¥ì¥¹,¿å,·õ,̸ɹ¤Î¹¶¿ÏIII




おま、なんやこれ…
機嫌よくスクレイピングしている時にこれは萎え萎え。これには聖人のわたしもプッツンです。今時文字化けとか見たことないわ…
で、これが起きた時の問題のコードがこちら。


from urllib.request import urlopen
from bs4 import BeautifulSoup
import csv
import requests
import chardet
import pandas as pd

url = "http://gbf-wiki.com/index.php?%BA%C7%BD%AA%BE%E5%B8%C2%B2%F2%CA%FC%C9%F0%B4%EF"
r = requests.get(url)
print(r.encoding)
soup = BeautifulSoup(r.content, "html.parser")
print(soup.original_encoding)
csvFile = open("test.csv", "wt", newline = '', encoding = "utf-8")
writer = csv.writer(csvFile)

for i in range(3, 31, 1):
    table = soup.findAll("table", {"class":"style_table"})[i]
    rows = table.findAll("tr")
    k=0

    for row in rows:
        k=k+1
        if (k <= 1 or i== 22 or i==25):
            continue

        csvRow = []
        for cell in row.findAll(["td", "th"]):
            csvRow.append(cell.get_text())
        if (i==3 or i==4):
            csvRow.pop(3)
        if (i>=26):
            csvRow.pop(0)
            if (i==27):
                csvRow.pop(2)
                csvRow.insert(1, "-")
            elif(i==26):
                csvRow.pop(3)
                csvRow.insert(4, "")
            else:
                csvRow.pop(3)
        writer.writerow(csvRow)


ちなみに前回の記事からコードは書き換えましたが、これはできるだけ文字化けがおきないとなんかしらんけどおススメされてたコードなのでなんで文字化けが起きるのかさっぱりでヤンす。


で、なんとかこの文字化けを解決しようとググりましたが全然対策が出てこず…
そんな中とりあえず試行錯誤することでなにが原因か突き止めることができました。



原因はおそらくこのsoup.original_encodingがwindows-1252になってしまっていることかと思います。文字化けせずに内容が取得できる場合はこの値がr.encodingと等しくなっていることもわかります。ってことはBeautifulSoupでhtmlの内容をencodeする時にr.encodingのコードでエンコードできるようにすればいいということです。

これでそのままエンコードの欄にエンコード言語を書くだけではエラーがでてきます。そのため、そのエラーを吐かないようにさせると文字化けせずにスクレイピングできると。
ってことで改修後のコードがこちら。


from urllib.request import urlopen
from bs4 import BeautifulSoup
import csv
import requests
import chardet
import pandas as pd

url = "http://gbf-wiki.com/index.php?%BA%C7%BD%AA%BE%E5%B8%C2%B2%F2%CA%FC%C9%F0%B4%EF"
r = requests.get(url)
print(r.encoding)
soup = BeautifulSoup(r.content, "html.parser")
soup = BeautifulSoup(r.content.decode("euc-jp", "ignore"), "html.parser")
print(soup.original_encoding)
csvFile = open("test.csv", "wt", newline = '', encoding = "utf-8")
writer = csv.writer(csvFile)

for i in range(3, 31, 1):
    table = soup.findAll("table", {"class":"style_table"})[i]
    rows = table.findAll("tr")
    k=0

    for row in rows:
        k=k+1
        if (k <= 1 or i== 22 or i==25):
            continue

        csvRow = []
        for cell in row.findAll(["td", "th"]):
            csvRow.append(cell.get_text())
        if (i==3 or i==4):
            csvRow.pop(3)
        if (i>=26):
            csvRow.pop(0)
            if (i==27):
                csvRow.pop(2)
                csvRow.insert(1, "-")
            elif(i==26):
                csvRow.pop(3)
                csvRow.insert(4, "")
            else:
                csvRow.pop(3)
        writer.writerow(csvRow)


このr.content.decode(“euc-jp”, “ignore”)の部分のignoreでPythonが吐く全てのエラーを無視します。
さて、こんな感じで文字化けを回避することができるようになりました。おすすめは先にr.encodingで使用言語を調べてからそれでエンコードすることですね。
ってな感じでBeautifulSoupを使った際の文字化けは解消されると思います。
では、最後まで読んでくださってありがとうございました。

0 件のコメント :

コメントを投稿