Как мне получить XML-документ и разобрать его с помощью скрученного Python? - PullRequest
3 голосов
/ 02 ноября 2009

Я хочу быстрый способ получить URL и проанализировать его во время потоковой передачи. В идеале это должно быть очень быстро. Мой язык выбора - Python. У меня есть интуиция, которая может сделать это, но я не могу найти пример.

Ответы [ 2 ]

6 голосов
/ 07 ноября 2009

Если вам нужно обрабатывать 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

Наконец, скоро будет новый API-интерфейс клиента HTTP. Поскольку это еще не является частью какого-либо релиза, он не так непосредственно полезен, как предыдущие два подхода, но он несколько лучше, поэтому я включу его, чтобы дать вам представление о том, что принесет будущее. :) Новый 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
0 голосов
/ 05 ноября 2009

Вам нужно только разобрать один URL? Тогда не волнуйся. Используйте urllib2, чтобы открыть соединение и передать дескриптор файла в ElementTree.

Варианты, которые вы можете попробовать, заключаются в том, чтобы использовать инкрементный синтаксический анализатор ElementTree или использовать iterparse, но это зависит от ваших реальных требований. Там "супер быстро", но есть и "достаточно быстро".

Это только когда вы начинаете иметь несколько одновременных подключений, где вы должны смотреть на Twisted или многопоточность.

...