use*_*720 3 python http request
出于教育目的,但没有任何重要性,我想实现一个脚本,可以发出简单的 HTTP 请求并在控制台上显示答案的内容(以纯文本形式)。我用这段代码实现了它:
import socket
import sys
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('localhost', 8080)
print >>sys.stderr, 'connecting to %s port %s' % server_address
sock.connect(server_address)
message = 'GET /php.php HTTP/1.1\r\n'
message += 'Host: localhost:8080\r\n\r\n'
print >>sys.stderr, 'sending "%s"' % message
sock.sendall(message)
data = sock.recv(10000000)
print >>sys.stderr, 'received "%s"' % data
sock.close()
Run Code Online (Sandbox Code Playgroud)
我只是构建 HTTP 请求,将其发送到服务器,然后等待答复。
现在问题来了:我不知道如何阅读整个答案,我知道有一个标题是“content-lengt”(让我们假设它永远存在)。我怎样才能不读答案的全部内容呢sock.recv (1000000000000000000)
?
通常,您会在循环中读取一定数量的字节(例如 1024)。如果recv
返回任何字节,请将其附加到您的数据中,否则打破循环并关闭连接。
import socket
server_address = ('httpbin.org', 80)
message = b'GET / HTTP/1.1\r\n'
message += b'Host: httpbin.org:80\r\n'
message += b'Connection: close\r\n'
message += b'\r\n'
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(server_address)
sock.sendall(message)
data = b''
while True:
buf = sock.recv(1024)
if not buf:
break
data += buf
sock.close()
print(data.decode())
Run Code Online (Sandbox Code Playgroud)
请注意,您必须将连接标头设置为“关闭”(或使用 HTTP 1.0)。否则,默认情况下,循环将因持久连接而挂起,如 HTTP 1.1 中实现的那样。
或者,您可以读取第一个字节并解析它们以获取 HTTP 标头。如果有 Content-Length 标头,您可以使用它来计算剩余字节。
...
data = b''
while b'\r\n\r\n' not in data:
data += sock.recv(1)
header = data[:-4].decode()
headers = dict([i.split(': ') for i in header.splitlines()[1:]])
content_length = int(headers.get('Content-Length', 0))
if content_length:
data += sock.recv(content_length)
...
Run Code Online (Sandbox Code Playgroud)
通过在send
和中使用字节recv
,这也应该适用于 Python3。然而,这是一个非常基本的示例,在许多情况下都会失败(HTTPS、cookie、重定向等),因此最好使用为 HTTP 请求设计的库。