使用Python读取HTTP服务器推送流

4
我正在尝试编写一个客户端,用于访问一个提供HTTP流数据(也称为HTTP服务器推送)的网站。然而,urllib2.urlopen()会获取当前状态下的流,并关闭连接。我尝试跳过urllib2,直接使用httplib,但这似乎有相同的行为。
该请求是带有五个参数的POST请求。没有需要鉴权的cookie或认证信息。
有没有办法让流保持开启状态,这样每次程序循环时就可以检查新内容,而不是每隔几秒钟等待整个流重新下载,从而引入延迟?
3个回答

2
你可以尝试使用 requests 库。
import requests
r = requests.get('http://httpbin.org/stream/20', stream=True)

for line in r.iter_lines():
    # filter out keep-alive new lines
    if line:
        print line

您也可以添加参数:
import requests
settings = { 'interval': '1000', 'count':'50' }
url = 'http://agent.mtconnect.org/sample'

r = requests.get(url, params=settings, stream=True)

for line in r.iter_lines():
    if line:
        print line

1
你是否需要真正解析响应头,还是主要关心内容?你的HTTP请求是否复杂,需要设置cookie和其他头部信息,或者一个非常简单的请求就足够了?
如果你只关心HTTP响应的正文内容,并且没有非常复杂的请求,那么考虑使用socket连接可能会更简单:
import socket

SERVER_ADDR = ("example.com", 80)

sock = socket.create_connection(SERVER_ADDR)
f = sock.makefile("r+", bufsize=0)

f.write("GET / HTTP/1.0\r\n"
      + "Host: example.com\r\n"    # you can put other headers here too
      + "\r\n")

# skip headers
while f.readline() != "\r\n":
    pass

# keep reading forever
while True:
    line = f.readline()     # blocks until more data is available
    if not line:
        break               # we ran out of data!

    print line

sock.close()

这个方法可以运行一段时间(无论如何,我已经正确获取了POST请求的头部)。然而,几秒钟后,连接似乎终止了,我从服务器那里得到了一个“</div></body></html>”,没有更多的数据。是保持连接超时或类似的问题,如果是,我该如何停止它? - Sam
@Sam:你读到 </div></body></html> 这段代码,说明你已经到了输出的末尾。你确定还有更多内容吗?如果是这样,请考虑设置 Connection: Keep-Alive HTTP 头部:http://www.io.com/~maus/HttpKeepAlive.html - Eli Courtwright
肯定还有更多,因为在我的网络浏览器中读取相同的流时会出现。然而,查看页面源代码,每六秒钟运行一次JavaScript,将window.location更改为具有不同参数的POST请求;具体来说,它将“rnd=0.749976718186”更改为不同的数字。我不知道这是什么意思,但我怀疑它与流提前终止有关。我将不得不与流的所有者交谈并回复您。 - Sam
问题解决了!我正在与页面进行交互,它需要每隔20秒刷新一次另一个连接,否则它会认为你已经断开连接并关闭该连接。添加代码以每隔几秒钟抓取它,然后就可以愉快地工作了。谢谢! - Sam

0

使用urllib2的一种方法是(假设该网站还需要基本身份验证):

 import urllib2
 p_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
 url = 'http://streamingsite.com'
 p_mgr.add_password(None, url, 'login', 'password')

 auth = urllib2.HTTPBasicAuthHandler(p_mgr)
 opener = urllib2.build_opener(auth)

 urllib2.install_opener(opener)
 f = opener.open('http://streamingsite.com')

 while True:
     data = f.readline()

这似乎不起作用。我放弃了认证部分,因为我不需要它,只使用了HTTPHandler。还在循环中添加了sleep()以防止程序吞噬太多CPU,并在遇到任何数据时将其打印到屏幕上。它会按照脚本启动时流的内容运行,然后不再获取任何进一步的数据。 - Sam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接