Разбирать GTFS в реальном времени без protobuf с python

Я пытаюсь анализировать GTFS данные в реальном времени trip_update в формате простого текстового файла, а не в формате pb (protobuf).

(вот адрес фида)

https://extranet.trainose.gr/epivatikos/transit/trip_updates

Однако единственные примеры, которые я нашел, касаются файлов pb.

from google.transit import gtfs_realtime_pb2
....
response = requests.get(url, allow_redirects=True)
feed.ParseFromString(response.content)
for entity in feed.entity:

Итак, как я могу разобрать фид, который не является pb? Спасибо.


person Plirkee    schedule 14.06.2019    source источник


Ответы (2)


Оказывается, есть способ обработать текстовую ленту боли примерно так:

   response = requests.get(url, allow_redirects=True)
    ...
    try:
        from google.protobuf import text_format
        text_format.Parse(response.content.decode('UTF-8'), feed, allow_unknown_extension=True)
        print("Parse with text format successfully.")
        printResults(feed)
    except text_format.ParseError as e:
            raise IOError("Cannot parse text %s." % (str(e)))

собственно вот и весь мой скрипт

from google.transit import gtfs_realtime_pb2
import os
import requests


def main():
    feed = gtfs_realtime_pb2.FeedMessage()
    url = ('https://feed.utl.com/feed')
    get_feed(feed, url)

def printResults(feed):
    from datetime import datetime
    ts = int(str(feed.header.timestamp))
    print("Last update: " + datetime.fromtimestamp(ts).strftime('%d-%m-%Y %H:%M:%S'))
    for entity in feed.entity:
        print (str(entity.trip_update.trip.trip_id)+';')
        with open('output.txt', mode='w') as f:
            for entity in feed.entity:
                if entity.HasField('trip_update'):
                        f.write(str(entity.trip_update.trip.trip_id)+';')
def get_feed(feed, url):
    proxies = {'http': '127.0.0.1:5555','https': '127.0.0.1:5555'}
    response = requests.get(url, allow_redirects=True,proxies=proxies)
    try:
        feed.ParseFromString(response.content)
        printResults(feed)
    except :
        print("Oops!  That was no valid data. Try again...\n\n" + response.content)
        try:
            from google.protobuf import text_format
            text_format.Parse(response.content.decode('UTF-8'), feed, allow_unknown_extension=True)
            print("Parse with text format successfully.")
            printResults(feed)
        except text_format.ParseError as e:
            raise IOError("Cannot parse file %s." % (str(e)))
if __name__ == "__main__":
    main()
person Plirkee    schedule 18.06.2019
comment
Увлекательно — я сделал свое заявление на основе этого документация, в которой не упоминается метод Parse, но по сравнению с фактическим кодом protobuf Python на github я вижу, что документация несколько устарела. - person abeboparebop; 18.06.2019

Человекочитаемый текст не является стандартным форматом для отправки и получения сообщений protobuf. (Если вам нужен только обычный текст, вы должны использовать стандартный текстовый формат, такой как JSON.) В принципе, это только для целей отладки. Таким образом, в библиотеке Python Protobuf нет методов для анализа текстовых сообщений. Правильное решение здесь — найти реальную конечную точку protobuf, возможно, связавшись с владельцем домена. (EDIT: по-видимому, в библиотеке Python действительно существует метод Parse для сообщений в текстовом формате — см. исходный код здесь.)

Тем не менее, библиотека C++ Protobuf, по-видимому, содержит методы для прямого разбора текстового формата, поэтому, если у вас нет возможности получить доступ к настоящему protobuf, это может быть резервным вариантом: https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.text_format.

Насколько мне известно, нет строгих гарантий согласованности текстового формата между версиями, но тот факт, что он представлен в библиотеке, предполагает, что на практике он, вероятно, довольно стабилен. Это обсуждение производит такое же впечатление (так как есть внутренние инструменты Google, которые анализируют текстовый формат): https://github.com/protocolbuffers/protobuf/issues/1297#issuecomment-390825524.

person abeboparebop    schedule 15.06.2019
comment
Спасибо за ответ! На самом деле вы дали мне идею, как продолжить поиск решения для gtfs rt в текстовом формате Python. Так что я проголосую, а позже опубликую свое собственное решение на Python. - person Plirkee; 18.06.2019