web-dev-qa-db-ja.com

Pythonリクエストを使用してhtmlを取得しますか?

私は自分自身に基本的なウェブスクレイピングを教えようとしています。 Pythonの要求モジュールを使用して、これを試すまでさまざまなWebサイトのhtmlを取得できました。

>>> r = requests.get('http://www.wrcc.dri.edu/WRCCWrappers.py?sodxtrmts+028815+por+por+pcpn+none+mave+5+01+F')

このページのソースである基本的なhtmlの代わりに、次のようにします。

>>> r.text
'\x1f\ufffd\x08\x00\x00\x00\x00\x00\x00\x03\ufffd]o\u06f8\x12\ufffd\ufffd\ufffd+\ufffd]...

>>> r.content
b'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\xed\x9d]o\xdb\xb8\x12\x86\xef\xfb+\x88]\x14h...

ドキュメントとSOおよび他の例から推測できるすべての構文でget/postの多くの組み合わせを試しました。上記で見ているものが理解できません。それを私が読むことができるものに変えて、私が実際に欲しいものを手に入れる方法を理解することができません。

20
Rich Thompson

問題のサーバーは、gzip圧縮された応答を提供しています。サーバーも非常に壊れています;次のヘッダーを送信します。

$ curl -D - -o /dev/null -s -H 'Accept-Encoding: gzip, deflate' http://www.wrcc.dri.edu/WRCCWrappers.py?sodxtrmts+028815+por+por+pcpn+none+mave+5+01+F
HTTP/1.1 200 OK
Date: Tue, 06 Jan 2015 17:46:49 GMT
Server: Apache
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd"><html xmlns="http: //www.w3.org/1999/xhtml" lang="en-US">
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 3659
Content-Type: text/html

<!DOCTYPE..>行があります有効なHTTPヘッダーではありません。そのため、Serverを過ぎた残りのヘッダーはignoredです。サーバーが介入する理由は不明です。すべての可能性のあるフードWRCCWrappers.pyはヘッダーを出力しないCGIスクリプトですが、Doctype行の後に二重改行が含まれており、Apacheサーバーに追加のヘッダーを挿入するようになります。

そのため、requestsは、データがgzipエンコードされていることも検出しません。データがすべて揃っているので、デコードするだけです。または、それがかなり不完全ではなかった場合でも可能です。

回避策は、圧縮を気にしないようにサーバーに指示することです。

headers = {'Accept-Encoding': 'identity'}
r = requests.get(url, headers=headers)

圧縮されていない応答が返されます。

ちなみに、Python 2では、HTTPヘッダーパーサーはそれほど厳密ではなく、Doctypeをヘッダーとして宣言できます。

>>> pprint(dict(r.headers))
{'<!doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "dtd/xhtml1-transitional.dtd"><html xmlns="http': '//www.w3.org/1999/xhtml" lang="en-US">',
 'connection': 'Keep-Alive',
 'content-encoding': 'gzip',
 'content-length': '3659',
 'content-type': 'text/html',
 'date': 'Tue, 06 Jan 2015 17:42:06 GMT',
 'keep-alive': 'timeout=5, max=100',
 'server': 'Apache',
 'vary': 'Accept-Encoding'}

そしてその content-encoding情報は存続するので、requestsが期待どおりにコンテンツをデコードします。

17
Martijn Pieters

このURLのHTTPヘッダーは修正されました。

>>> import requests
>>> print requests.__version__
2.5.1
>>> r = requests.get('http://www.wrcc.dri.edu/WRCCWrappers.py?sodxtrmts+028815+por+por+pcpn+none+mave+5+01+F')
>>> r.text[:100]
u'\n<!DOCTYPE html>\n<HTML>\n<HEAD><TITLE>Monthly Average of Precipitation, Station id: 028815</TITLE></H'
>>> r.headers
{'content-length': '3672', 'content-encoding': 'gzip', 'vary': 'Accept-Encoding', 'keep-alive': 'timeout=5, max=100', 'server': 'Apache', 'connection': 'Keep-Alive', 'date': 'Thu, 12 Feb 2015 18:59:37 GMT', 'content-type': 'text/html; charset=utf-8'}
3
Grant