golang加载和解析GTFS文件插件库go-gtfs的使用

Golang加载和解析GTFS文件插件库go-gtfs的使用

安装

go get github.com/artonge/go-gtfs

示例

加载包含GTFS文件的单个目录

假设目录结构如下:

path/to/gtfs_files
├── agency.txt
├── attributions.txt
├── calendar_dates.txt
├── calendar.txt
├── fare_attributes.txt
├── fare_rules.txt
├── feed_info.txt
├── frequencies.txt
├── levels.txt
├── pathways.txt
├── routes.txt
├── shapes.txt
├── stops.txt
├── stop_times.txt
├── transfers.txt
└── trips.txt

加载代码示例:

package main

import (
	"fmt"
	"github.com/artonge/go-gtfs"
)

func main() {
	// 加载单个GTFS目录
	g, err := gtfs.Load("path/to/gtfs_files", nil)
	if err != nil {
		fmt.Printf("加载GTFS文件失败: %v\n", err)
		return
	}
	
	// 访问数据
	fmt.Printf("共加载了 %d 条路线\n", len(g.Routes))
	fmt.Printf("共加载了 %d 个站点\n", len(g.Stops))
	
	// 示例:打印前5条路线信息
	for i, route := range g.Routes {
		if i >= 5 {
			break
		}
		fmt.Printf("路线ID: %s, 短名称: %s, 长名称: %s\n", 
			route.ID, route.ShortName, route.LongName)
	}
}

加载包含多个GTFS子目录的目录

假设目录结构如下:

path/to/gtfs_directories
├── gtfs1
│   ├── agency.txt
│   ├── attributions.txt
│   ├── ...
└── gtfs2
    ├── agency.txt
    ├── attributions.txt
    ├── ...

加载代码示例:

package main

import (
	"fmt"
	"github.com/artonge/go-gtfs"
)

func main() {
	// 加载包含多个GTFS子目录的目录
	gs, err := gtfs.LoadSplitted("path/to/gtfs_directories", nil)
	if err != nil {
		fmt.Printf("加载GTFS文件失败: %v\n", err)
		return
	}
	
	// 访问数据
	for i, gtfsData := range gs {
		fmt.Printf("数据集 %d:\n", i+1)
		fmt.Printf("  共加载了 %d 条路线\n", len(gtfsData.Routes))
		fmt.Printf("  共加载了 %d 个站点\n", len(gtfsData.Stops))
	}
}

数据结构

go-gtfs库提供了完整的GTFS数据结构:

type GTFS struct {
	Path           string // 包含目录的路径
	Agency         Agency
	Agencies       []Agency
	Attributions   []Attribution
	Calendars      []Calendar
	CalendarDates  []CalendarDate
	FareAttributes []FareAttribute
	FareRules      []FareRule
	FeedInfos      []FeedInfo
	Frequencies    []Frequency
	Levels         []Level
	Routes         []Route
	Pathways       []Pathway
	Shapes         []Shape
	Stops          []Stop
	StopsTimes     []StopTime
	Trips          []Trip
	Transfers      []Transfer
}

type Route struct {
	ID        string `csv:"route_id"`
	AgencyID  string `csv:"agency_id"`
	ShortName string `csv:"route_short_name"`
	LongName  string `csv:"route_long_name"`
	Type      int    `csv:"route_type"`
	Desc      string `csv:"route_desc"`
	URL       string `csv:"route_url"`
	Color     string `csv:"route_color"`
	TextColor string `csv:"route_text_color"`
}

// 其他数据结构类似...

项目状态

该项目目前处于维护模式。它保持与Go生态系统的变化兼容,但不会开发新功能。可能会接受Pull Request。


更多关于golang加载和解析GTFS文件插件库go-gtfs的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang加载和解析GTFS文件插件库go-gtfs的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用go-gtfs加载和解析GTFS文件

GTFS(General Transit Feed Specification)是公共交通数据的标准格式。在Go语言中,go-gtfs是一个专门用于处理GTFS文件的库。下面我将详细介绍如何使用这个库。

安装go-gtfs

首先需要安装go-gtfs库:

go get github.com/artonge/go-gtfs

基本使用示例

1. 加载GTFS文件

package main

import (
	"fmt"
	"log"
	
	"github.com/artonge/go-gtfs"
)

func main() {
	// 加载GTFS文件
	gtfsPath := "path/to/your/gtfs.zip"
	feed, err := gtfs.Load(gtfsPath)
	if err != nil {
		log.Fatalf("加载GTFS失败: %v", err)
	}
	
	fmt.Printf("成功加载GTFS文件,包含 %d 条路线\n", len(feed.Routes))
}

2. 解析GTFS内容

// 打印所有路线信息
func printRoutes(feed *gtfs.Feed) {
	fmt.Println("=== 路线列表 ===")
	for _, route := range feed.Routes {
		fmt.Printf("ID: %s, 简称: %s, 全称: %s, 类型: %d\n",
			route.ID, route.ShortName, route.LongName, route.Type)
	}
}

// 打印指定路线的所有站点
func printStopsForRoute(feed *gtfs.Feed, routeID string) {
	fmt.Printf("\n=== 路线 %s 的站点 ===\n", routeID)
	
	// 获取路线对应的行程
	var trips []gtfs.Trip
	for _, trip := range feed.Trips {
		if trip.RouteID == routeID {
			trips = append(trips, trip)
		}
	}
	
	// 获取行程对应的站点
	for _, trip := range trips {
		fmt.Printf("\n行程 %s:\n", trip.ID)
		stopTimes := getStopTimesForTrip(feed, trip.ID)
		for _, st := range stopTimes {
			stop := getStopByID(feed, st.StopID)
			fmt.Printf("- %s (到达: %s, 离开: %s)\n", 
				stop.Name, st.ArrivalTime, st.DepartureTime)
		}
	}
}

// 辅助函数:根据行程ID获取站点时间
func getStopTimesForTrip(feed *gtfs.Feed, tripID string) []gtfs.StopTime {
	var result []gtfs.StopTime
	for _, st := range feed.StopTimes {
		if st.TripID == tripID {
			result = append(result, st)
		}
	}
	return result
}

// 辅助函数:根据站点ID获取站点信息
func getStopByID(feed *gtfs.Feed, stopID string) gtfs.Stop {
	for _, stop := range feed.Stops {
		if stop.ID == stopID {
			return stop
		}
	}
	return gtfs.Stop{}
}

3. 查询功能示例

// 根据站点名称查找站点
func findStopsByName(feed *gtfs.Feed, name string) []gtfs.Stop {
	var result []gtfs.Stop
	for _, stop := range feed.Stops {
		if strings.Contains(strings.ToLower(stop.Name), strings.ToLower(name)) {
			result = append(result, stop)
		}
	}
	return result
}

// 查找两个站点之间的路线
func findRoutesBetweenStops(feed *gtfs.Feed, startStopID, endStopID string) []gtfs.Route {
	var routes []gtfs.Route
	
	// 获取包含起始站点的行程
	startTrips := getTripsForStop(feed, startStopID)
	endTrips := getTripsForStop(feed, endStopID)
	
	// 找出共同的行程
	for _, st := range startTrips {
		for _, et := range endTrips {
			if st.TripID == et.TripID {
				// 检查站点顺序
				if isStopBeforeInTrip(feed, st, et) {
					route := getRouteByID(feed, st.RouteID)
					routes = append(routes, route)
				}
			}
		}
	}
	
	return routes
}

// 辅助函数:获取包含特定站点的所有行程
func getTripsForStop(feed *gtfs.Feed, stopID string) []gtfs.StopTime {
	var result []gtfs.StopTime
	for _, st := range feed.StopTimes {
		if st.StopID == stopID {
			result = append(result, st)
		}
	}
	return result
}

// 辅助函数:检查站点顺序
func isStopBeforeInTrip(feed *gtfs.Feed, first, second gtfs.StopTime) bool {
	var firstSeq, secondSeq int
	for _, st := range feed.StopTimes {
		if st.TripID == first.TripID {
			if st.StopID == first.StopID {
				firstSeq = st.StopSequence
			}
			if st.StopID == second.StopID {
				secondSeq = st.StopSequence
			}
		}
	}
	return firstSeq < secondSeq
}

// 辅助函数:根据ID获取路线
func getRouteByID(feed *gtfs.Feed, routeID string) gtfs.Route {
	for _, route := range feed.Routes {
		if route.ID == routeID {
			return route
		}
	}
	return gtfs.Route{}
}

高级功能

1. 加载特定表

如果只需要加载GTFS中的特定表,可以使用LoadSpecific函数:

// 只加载路线和站点表
tablesToLoad := []string{"routes", "stops"}
feed, err := gtfs.LoadSpecific(gtfsPath, tablesToLoad)
if err != nil {
	log.Fatal(err)
}

2. 导出为CSV

// 将GTFS数据导出为CSV文件
err = gtfs.ExportToCsv(feed, "output_directory")
if err != nil {
	log.Fatal(err)
}

性能优化建议

  1. 对于大型GTFS文件,考虑只加载需要的表
  2. 可以预先建立索引数据结构来提高查询速度
  3. 对于频繁查询,可以将数据存储在内存数据库或缓存中

总结

go-gtfs库提供了简单易用的接口来加载和解析GTFS文件。通过上述示例,您可以:

  1. 加载GTFS ZIP文件
  2. 访问路线、站点、行程等数据
  3. 实现基本的查询功能
  4. 进行数据导出等操作

根据您的具体需求,可以在此基础上构建更复杂的公共交通查询系统。

回到顶部