2017-12-10 19 views
3

Howdy folks、なぜこのUTF-8ページをデコードできないのですか?

私はPythonを使用してWebからデータを取得するのが初めてです。私は、文字列で、このページのソースコードを持っているしたいと思います: https://projects.fivethirtyeight.com/2018-nba-predictions/

次のコードは、(例えばhttps://www.basketball-reference.com/boxscores/201712090ATL.htmlなど)他のページのために働いています

import urllib.request 
file = urllib.request.urlopen(webAddress) 
data = file.read() 
file.close() 
dataString = data.decode(encoding='UTF-8') 

そして、私は期待したいですHTMLの文字列であることをdataStringため、

<!DOCTYPE html><html lang="en"><head><meta property="article:modified_time" etc etc 

代わりに(この特定の場合には私の期待は以下を参照してください) 538ウェブサイトは、私はこのエラーを取得する:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8b in position 1: invalid start byte 

私の研究はこの問題は、私のファイルが実際にUTF-8を使用してエンコードされていないことであることが示唆されますが、ページの文字セットと美しいスープのUnicodeDammit()クレームの両方ましたそれはUTF-8です(2番目は最初のものかもしれません)。 chardet.detect()はコード化を示唆していません。

ラテン-1

のWindows-1252

ISO-8859-1:私は無駄に 'UTF-8' デコードのエンコーディングパラメータの()のために、以下に置き換えて試してみました

おそらく言及する価値があるのは、バイト配列データが期待通りに見えないということです。作業URLから:[10]:ここではデータだ

b'\n<!DOCTYPE' 

ここでのデータです[:10] 538サイトから:

b'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03' 

がアップ何ですか?

+0

'wget'でデータを取得するとgzipで圧縮されたファイルが提供されます。これは圧縮されておらず、通常のUTF-8 HTMLページを提供します。おそらくサーバーがひどく構成されており、関連するヘッダーを設定せずに圧縮されたページを提供します。 –

+0

( 'file.headers ['content-encoding']'を見てください。) – Ryan

+0

@Ryan:実際に 'gzip'を' content-encoding'に設定しているようですが、 'curl'と' wget'のどちらもそれについて何もしません通常、トランスポートレベルの圧縮を透過的に処理するので、奇妙です。このサーバの動作には、何か変わったことがなければなりません。 –

答えて

4

あなたはgzipで圧縮されたデータを提供するサーバー。デフォルトではurllibにはaccept-encodingの値が設定されていないため、サーバーは一般的に保守的にデータを圧縮しません。

はまだ、応答content-encodingフィールドはセットですので、あなたのページには、実際にgzipで圧縮されていることを知る方法を持っている、とあなたはさらに処理する前に、Pythonのgzipモジュールを使用して、それを解凍することができます。

import urllib.request 
import gzip 
file = urllib.request.urlopen(webAddress) 
data = file.read() 
if file.headers['content-encoding'].lower() == 'gzip': 
    data = gzip.decompress(data) 
file.close() 
dataString = data.decode(encoding='UTF-8') 

OTOH、あなたがrequestsモジュールを使用する可能性を持っている場合、それは圧縮を含め、それ自体ですべてのこの混乱を処理すると、(で(私はあなたにもdeflategzip以外に、どのis the same but with different headersを得ることができます?ということを言及しました)少なくとも部分的に)符号化する。

import requests 
webAddress = "https://projects.fivethirtyeight.com/2018-nba-predictions/" 
r = requests.get(webAddress) 
print(repr(r.text)) 

これは、あなたの要求を実行し、既にデコードされたUnicode文字列を正しく出力します。

関連する問題