如何用Python Twisted获取并解析XML文档?
我想要一种快速的方法来获取一个网址并在流式处理的同时解析它。理想情况下,这个过程应该非常快。我选择的编程语言是Python。我觉得twisted这个库可以做到这一点,但我找不到相关的例子。
2 个回答
0
你只需要处理一个网址吗?那就不用担心。可以用urllib2来打开连接,然后把文件句柄传给ElementTree。
你可以尝试一些不同的方法,比如使用ElementTree的增量解析器或者iterparse,但这要看你具体的需求是什么。有的方式是“超级快”,但也有“足够快”的选择。
只有当你需要同时处理多个连接时,才需要考虑使用Twisted或者多线程。
7
如果你需要以流式的方式处理HTTP响应,有几种选择。
你可以通过 downloadPage
来实现:
from xml.sax import make_parser
from twisted.web.client import downloadPage
class StreamingXMLParser:
def __init__(self):
self._parser = make_parser()
def write(self, bytes):
self._parser.feed(bytes)
def close(self):
self._parser.feed('', True)
parser = StreamingXMLParser()
d = downloadPage(url, parser)
# d fires when the response is completely received
这个方法之所以有效,是因为 downloadPage
会把响应的内容写入一个类似文件的对象中。这里,传入一个有 write
和 close
方法的对象就满足了这个要求,但它会逐步解析数据为XML,而不是直接把它存到磁盘上。
另一种方法是直接在 HTTPPageGetter
的层面上进行操作。 HTTPPageGetter
是 getPage
内部使用的协议。
class StreamingXMLParsingHTTPClient(HTTPPageGetter):
def connectionMade(self):
HTTPPageGetter.connectionMade(self)
self._parser = make_parser()
def handleResponsePart(self, bytes):
self._parser.feed(bytes)
def handleResponseEnd(self):
self._parser.feed('', True)
self.handleResponse(None) # Whatever you pass to handleResponse will be the result of the Deferred below.
factory = HTTPClientFactory(url)
factory.protocol = StreamingXMLParsingHTTPClient
reactor.connectTCP(host, port, factory)
d = factory.deferred
# d fires when the response is completely received
最后,新的HTTP客户端API很快就会推出。因为这还不是正式发布的一部分,所以它没有前面两种方法那么直接好用,但它会更方便,所以我提到它,让你对未来有个了解。:) 新的API允许你指定一个协议来接收响应内容。所以你可以这样做:
class StreamingXMLParser(Protocol):
def __init__(self):
self.done = Deferred()
def connectionMade(self):
self._parser = make_parser()
def dataReceived(self, bytes):
self._parser.feed(bytes)
def connectionLost(self, reason):
self._parser.feed('', True)
self.done.callback(None)
from twisted.web.client import Agent
from twisted.internet import reactor
agent = Agent(reactor)
d = agent.request('GET', url, headers, None)
def cbRequest(response):
# You can look at the response headers here if you like.
protocol = StreamingXMLParser()
response.deliverBody(protocol)
return protocol.done
d.addCallback(cbRequest) # d fires when the response is fully received and parsed