我正在尝试向网站发送HTTP请求并读取它返回的数据。我试过的第一个网站成功运作。它返回了大约4个数据包,然后返回了一个脚本捕获并终止的0数据包。
但是,尝试加载http://www.google.com/不起作用。相反,它返回大约10个相同长度的数据包,最后一个较小的数据包,然后继续超时。这种情况发生是否正常?这一切只取决于主机使用的服务器吗?
如果有人可以推荐使用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
答案 0 :(得分:3)
TCP不会为您提供“数据包”,而是从另一方发送顺序字节。 这是一个流。 recv()
为您提供当前可用的流的块。您将它们拼接在一起并解析流内容。
答案 1 :(得分:2)
可能是Google使用Keep-Alive来保持套接字打开,以便提供进一步的请求。这将需要解析标头并读取确切的字节数。
根据您使用的HTTP版本,您必须将Connection: Keep-Alive
添加到标头中。 (这可能是最简单的解决方案:只使用HTTP / 1.0而不是1.1。)
如果您仍然使用该功能,则必须收到第一批数据
'\r\nContent-Length: '
,如果是,则取出该字节与下一个'\r\n'
之间的字节并将其转换为数字。那是你的尺寸。'\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
,你就拥有了一切;如果没有,请s.read(missing)
并重新计算missing
,直到它为0.
上面的代码是一个简单的工作开始;在继续之前,您可能需要进一步recv()
。
这非常相似。到目前为止,更简单的方法是
Connection: close
标头,答案 2 :(得分:2)
对于HTTP,请使用requests而不是自己编写。
> 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