1

HTTPリクエストをWebサイトに送信し、返されるデータを読み取ろうとしています。私が試した最初のWebサイトは正常に機能しました。約4パケットのデータを返し、次に0パケットを返し、スクリプトがそれをキャッチして終了しました。

ただし、 http://www.google.com/を読み込もうとしても、この方法では機能しません。代わりに、同じ長さの約10個のパケット、最後の小さいパケットを返し、タイムアウトに進みます。これが起こるのは正常ですか?それはすべて、ホストが使用しているサーバーに依存しているだけですか?

最終的なnullパケットが常に送信されるとは限らないことを考慮に入れて、socket.recv()を使用して読み取る別の方法を誰かが推奨できる場合は、それを大いに歓迎します。ありがとう。

    try:
        data = s.recv(4096)

        while True:
            more = s.recv(4096)
            print len(more)
            if not more:
                break
            else:
                data += more
    except socket.timeout:
        errMsg = "Connection timed-out while connecting to %s. Request headers were as     follows: %s", (parsedUrl.netloc, rHeader.headerContent)
        self.logger.exception(errMsg)
        raise Exception
4

3 に答える 3

3

TCPは「パケット」を提供しませんが、反対側から送信されるシーケンシャルバイトを提供します。ストリームです。recv()現在利用可能なそのストリームのチャンクを提供します。それらをつなぎ合わせて、ストリームコンテンツを解析します。

HTTPは手作業で機能するためのかなり複雑なプロトコルであるため、代わりにhttplibなどの既存のライブラリから始めたいと思うでしょう。

于 2012-08-24T14:12:06.997 に答える
3

HTTPの場合、独自に作成するのではなく、リクエストを使用します。

> ipython

In [1]: import requests

In [2]: r = requests.get('http://www.google.com')

In [3]: r.status_code
Out[3]: 200

In [4]: r.text[:80]
Out[4]: u'<!doctype html><html itemscope="itemscope" itemtype="http://schema.org/WebPage">'

In [5]: len(r.text)
Out[5]: 10969
于 2012-08-24T14:29:54.100 に答える
2

GoogleがKeep-Aliveを使用してソケットを開いたままにして、さらにリクエストを処理している可能性があります。これには、ヘッダーを解析し、正確なバイト数を読み取る必要があります。

Connection: Keep-Alive使用するHTTPのバージョンに応じて、ヘッダーに追加するかどうかを指定する必要があります。(これが最も簡単な解決策かもしれません。1.1の代わりにHTTP / 1.0を使用してください。)

それでもその機能を使用する場合は、最初のデータチャンクを受信する必要があります。

  1. '\r\nContent-Length: '内部がある場合は解析し、ある場合は、そのバイトと次のバイトの間のバイトを取得'\r\n'して、数値に変換します。それがあなたのサイズです。
  2. データにが含まれている場合は、こちらをご覧'\r\n\r\n'ください。もしそうなら、それはあなたのヘッダーの終わりです。ここから、上記の正確なバイト数を読み取る必要があります。

例:

import socket
s = socket.create_connection(('www.google.com', 80))
s.send("GET / HTTP/1.1\r\n\r\n")
x = s.recv(10000)
poscl = x.lower().find('\r\ncontent-length: ')
poseoh = x.find('\r\n\r\n')
if poscl < poseoh and poscl >= 0 and poseoh >= 0:
    # found CL header
    poseocl = x.find('\r\n',poscl+17)
    cl = int(x[poscl+17:poseocl])
    realdata = x[poseoh+4:]

これで、コンテンツの長さがにclなり、ペイロードデータ(の開始)がになりrealdataます。このリクエストで欠落しているバイト数はですmissing = cl - len(realdata)。もしそうなら0、あなたはすべてを持っています。そうでない場合は、0になるまで実行s.read(missing)して再計算します。missing

上記のコードは、実行するジョブの単純な開始です。recv()先に進む前に、さらに先に進む必要がある場所がいくつかあります。

これはかなり複雑です。はるかに簡単な方法は

  1. リクエストでHTTP1.1のConnection: closeヘッダーを使用するには、
  2. HTTP 1.0を使用するには、
  3. このタスクのために作成されたライブラリの1つを使用し、車輪の再発明を行わないようにします。
于 2012-08-24T14:28:09.160 に答える