使用Python Requests响应原始文件对象(处理pcap文件而无需将其保存到磁盘)

4
使用Python (2.7.9)的Requests库从URL下载pcap文件:
import requests
response = requests.get('http://example.com/path/1.pcap',  stream=True)

根据文档,response.raw 是类似文件的对象。我的目标是在不将下载的文件保存到磁盘的情况下处理它。我首先查看了 ScapyPyshark 库来解析 .pcap 文件,但它们的函数 (rdpcapFileCapture) 接受文件路径字符串作为参数。而来自 dpkt 库的 pcap.Reader 则接受一个文件对象。第一次尝试 pcap=dpkt.pcap.Reader(resonse.raw) 会报错:
AttributeError: 'HTTPResponse' object has no attribute 'name'

新增了Name属性:

setattr(response.raw,'name', 'test.pcap')

之后,pcap=dpkt.pcap.Reader(response.raw) 没有出现任何错误,但是 pcap.readpkts() 失败了,出现了以下错误:

io.UsupportedOperation: seek

事实上,response.raw.seekable()返回False

我尝试设置response.raw.decode_content = True,但这并没有帮助。

处理对象的方式是否有解决方案?也许需要额外的请求参数才能获得可寻址的响应对象?

顺便说一句,如果将响应对象写入文件(shutil.copyfileobj(response.raw, file)),然后dpkt可以成功地使用该文件。


你能展示一下失败的代码片段吗,@Andrey? - boardrider
1个回答

1
最近在dpkt中添加了对StringIO对象的支持。因此,您现在可以从字符串创建StringIO对象,然后将其传递给pcap.Reader。
要从字符串创建StringIO对象:
from StringIO import StringIO
data = StringIO("aaaaa..aa")

您可以这样做:

然后您可以执行

import dpkt
from StringIO import StringIO
import requests

response = requests.get('http://example.com/path/1.pcap',  stream=True)
data = StringIO(response.raw)
pcap = dpkt.pcap.Reader(data)
    for ts, buf in pcap:
        eth = dpkt.ethernet.Ethernet(buf)
        ...

1
你应该提到实现这个的方法是 from StringIO import StringIO# (or cStringIO),然后用 wrapped_string = StringIO("my string here") 将你的字符串包装起来。 - a p
Kiran,谢谢。我希望这种方法能够奏效,但我还没有测试过。在升级DPKT之后,它在from test import pystone处失败,并显示错误cannot import name pystone。我从pip安装了test包,但它不包含pystone。我还没有解决这个问题(我正在Ubuntu 12.04上使用Python 2.7)。 - Andrey Grachev
Andrey,pystone是Python 2.7的一部分。您不必从pip安装test。在某个时候,您可能意外地将test.py或test目录安装/复制到了标准的Python lib中。要检查这一点,请执行import test,然后执行print test。这将显示test的位置,很可能覆盖了默认的test模块。 - Kiran Bandla
Kiran,谢谢你解决了pystone的问题。但是,当将stringIO对象传递给pcap.Reader时,我得到了“无效的tcpdump头”异常。当为同一pcap文件传递文件对象时,一切都被正确处理。 - Andrey Grachev
@AndreyGrachev 如果这个对您有帮助,可以将其标记为答案。 - Kiran Bandla
显示剩余2条评论

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