13

HTMLページを読み込んでテキストを出力しようとしていますが、Webページを正しく取得しているにもかかわらず、BeautifulSoupが何らかの形でエンコーディングを破壊しています。

ソース:

# -*- coding: utf-8 -*-
import requests
from BeautifulSoup import BeautifulSoup

url = "http://www.columbia.edu/~fdc/utf8/"
r = requests.get(url)

encodedText = r.text.encode("utf-8")
soup = BeautifulSoup(encodedText)
text =  str(soup.findAll(text=True))
print text.decode("utf-8")

抜粋出力:

...Odenw\xc3\xa4lderisch...

これはOdenwälderischであるべきです

4

3 に答える 3

6

BeautifulSoup のせいではありません。これは、BeautifulSoup を使用する前に を印刷することencodedTextで確認できます。非 ASCII 文字はすでに意味不明です。

ここでの問題は、バイトと文字を混同していることです。違いの概要については、Joel の記事の 1 つをお読みください。ただし、要点は、バイトはバイト (それ以上の意味を持たない 8 ビットのグループ) であり、文字はテキストの文字列を構成するものです。エンコードは文字をバイトに変換し、デコードはバイトを文字に戻します。

requestsドキュメントを見ると、バイトではなく文字で構成されていることr.textがわかります。エンコードしてはいけません。そうしようとするとバイト列になってしまい、それを文字として扱おうとするとまずいことが起きます。

これを回避するには、次の 2 つの方法があります。

  1. Martijn が提案しr.contentたように、に格納されている生のデコードされていないバイトを使用します。その後、それらを自分でデコードして文字に変換できます。
  2. requestsデコードを行いますが、正しいコーデックが使用されていることを確認してください。この場合は UTF-8 であることがわかっているので、 を設定できますr.encoding = 'utf-8'。にアクセスする前にこれを行えばr.text、 にアクセスr.textすると正しくデコードされ、文字列が得られます。文字エンコーディングをいじる必要はまったくありません。

ちなみに、Python 3 では、文字列とバイト文字列の違いを維持するのがいくらか簡単になっています。これは、それらを表すために異なるタイプのオブジェクトを使用する必要があるためです。

于 2016-04-25T06:48:05.020 に答える
1

コードにいくつかのエラーがあります。

  1. まず、テキストを再エンコードする必要はありません。リクエストはページのネイティブ エンコーディングを提供し、BeautifulSoup はこの情報を取得してデコード自体を行うことができます。

    # -*- coding: utf-8 -*-
    import requests
    from BeautifulSoup import BeautifulSoup
    
    url = "http://www.columbia.edu/~fdc/utf8/"
    r = requests.get(url)
    
    soup = BeautifulSoup(r.text, "html5lib")
    
  2. 第二に、エンコーディングの問題があります。端末で結果を視覚化しようとしている可能性があります。得られるのは、ASCII セットにないすべての文字のテキスト内の文字の Unicode 表現です。次のように結果を確認できます。

    res = [item.encode("ascii","ignore") for item in soup.find_all(text=True)]
    
于 2016-04-25T07:08:35.950 に答える