使用Python无需Protobuf即可实时解析GTFS

时间:2019-06-14 09:45:36

标签: python python-2.7 gtfs

我正在尝试解析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的供稿? 谢谢。

2 个答案:

答案 0 :(得分:1)

人类可读的文本不是发送和接收protobuf消息的标准格式。 (如果只需要纯文本,则应使用JSON之类的标准文本格式。)原则上,它仅用于调试目的。因此,Python Protobuf库中没有用于解析纯文本消息的方法。正确的解决方案是找到实际的protobuf端点,也许可以通过与域所有者联系来实现。 (编辑:显然,Python库中实际上有一种Parse方法用于文本格式的消息-请参见源代码here。)

也就是说,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

答案 1 :(得分:1)

事实证明,有一种方法可以处理类似以下内容的痛苦的文本供稿:

   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()