造了一个查找地铁换乘的轮子 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
jasonlee
V2EX    分享创造

造了一个查找地铁换乘的轮子

  •  
  •   jasonlee 2016-08-03 18:55:56 +08:00 6057 次点击
    这是一个创建于 3356 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近需要频繁出差,于是用 Python 和 Javascript 造了一个寻找最短路径的工具,托管在 https://metro.lihanming.me/。界面看起来像这样:

    定位

    它具有以下的功能:

    1. 站点提示(输入站名、线路名,可以提示一些车站)
    2. 根据当前位置寻找最近的车站,并提示怎么走过去(感谢高德地图)
    3. 寻找路径(支持按最短时间、换乘较少等模式查询)
    4. 提示行车时间(目前京沪穗三个地方支持实际时间,其他城市支持估算时间)

    目前支持中国内地所有有地铁的城市、香港(不含轻铁和电车)、台北和东京(两大地铁和 JR 部分线路)。伦敦正在写。线路保存在 JSON 文件中,可以随时扩展。

    比较有趣的细节:

    1. 支持虚拟换乘。虚拟换乘站会提示,并且会有不需要虚拟换乘的方案提供。(南京西路、上海火车站)
    2. 支持不同运营商或票务系统。如果行程需要转乘会提示。(如龙阳路、三元桥、青衣等)

    虚拟换乘提示 转乘提示

    目前几个需要努力的地方:

    1. 优化变量名。尽可能做到没有文档也能看懂;
    2. 连续多个换乘站的处理(四惠-四惠东、中环-金钟等);
    3. 提升算法性能。目前使用的算法在初始化时需要的时间比较长;
    4. 多语言支持。目前都是使用本地文字;
    5. 用户界面优化。城市太多了需要想个办法呈现;
    6. 几个城市合在一起做一个大的系统,并且包括一些城际线路(珠三角、长三角)
    7. 其它(包括你们的意见和建议);

    最后欢迎大家试试,希望它能在你们旅行出差的时候帮到你们,也欢迎你们提出意见和建议。

    网址: https://metro.lihanming.me/

    源码: https://github.com/DaZui/MetroSearch/

    Jason

    47 条回复    2016-08-17 20:19:30 +08:00
    niboy
        1
    niboy  
       2016-08-03 19:37:29 +08:00
    提个问题吧,比如在上海的金海路到世纪大道,其实有 2 种路线,实际搜出来的只有一种
    SourceMan
        2
    SourceMan  
       2016-08-03 19:39:00 +08:00 via iPhone
    最优路径的算法思路大概怎么样的?
    moult
        3
    moult  
       2016-08-03 19:51:14 +08:00
    杭州的,江陵路到客运中心,虽然 1 号线直达,但是换成一下 4 号线,就算加上换成时间,也比直达的快。
    jasonlee
        4
    jasonlee  
    OP
       2016-08-03 19:56:19 +08:00 via Android
    @niboy 有哪两种?提点一下
    jasonlee
        5
    jasonlee  
    OP
       2016-08-03 20:16:58 +08:00
    @SourceMan Floyd 算法。冷启动的时候生成距离矩阵,之后直接查矩阵。
    jasonlee
        6
    jasonlee  
    OP
       2016-08-03 20:17:36 +08:00
    @moult 这和时间计算方法有关。我设定的换乘的时间是 5 分钟。实际时间可能会短一些。
    niboy
        7
    niboy  
       2016-08-03 21:12:49 +08:00
    @jasonlee
    1. 12 号线金海路--》到大连路换 4 号线 --》世纪大道,起点站,胜在一路有座
    2. 12 号线金海路--》到巨峰路换 6 号线--》世纪大道,比路线 1 少一站,但站内换乘走路时间长,而且不一定有座

    可以和百度地图、腾讯地图等的路线对比一下
    jasonlee
        8
    jasonlee  
    OP
       2016-08-03 21:33:41 +08:00
    @niboy 我看了一下。估计是因为大连路那里需要过黄浦江,列车运行时间长一些。 Floyd 算法的主要缺点就是你找不到第二长的线路。我看看广度优先搜索能不能找到。谢了啊。
    jasonlee
        9
    jasonlee  
    OP
       2016-08-03 21:37:01 +08:00
    @moult 我新增了一个“换乘多”的模式,将换乘时间缩短为 2 分钟。主要是我不知道各个地方的列车间隔。如果列车衔接妥当,那么换乘所花的时间就短。
    niboy
        10
    niboy  
       2016-08-03 22:49:10 +08:00
    我下载了 Android 客户端,看起来就是网站,请问 lz 是用什么封装成 APK 的?难道就是一个 webview 加载了 bootstrap 的网站?
    jasonlee
        11
    jasonlee  
    OP
       2016-08-03 23:23:49 +08:00
    @niboy 正解。我写了一个 webView 。专门为 Android 写客户端的原因是因为一部分 Android 浏览器获取的地理位置不正确,所以无奈之下封装了。如果你是用 Chrome 等可以添加到桌面的浏览器,那我觉得不用下客户端也没事。
    wdlth
        12
    wdlth  
       2016-08-03 23:31:26 +08:00
    我认为如果只有一个结果的话就不要写换乘多了……
    jasonlee
        13
    jasonlee  
    OP
       2016-08-03 23:36:50 +08:00 via Android
    @wdlth 好主意。我在想这一块应该怎么展示。有什么建议吗?
    franklinyu
        14
    franklinyu  
       2016-08-04 01:10:39 +08:00
    @jasonlee 弗洛伊德算法是不是可以一次性找到所有「站」的最短路?而不用在收到求的候算?
    jasonlee
        15
    jasonlee  
    OP
       2016-08-04 08:01:49 +08:00 via Android
    @franklinyu 是的,就是原因。但 Floyd 演算法不能找到第二的路,十分疼。
    kenshin
        16
    kenshin  
       2016-08-04 10:54:59 +08:00
    挺棒的想法,前阵子去上海正好有这样的需求,当时的想法是自己有时间撸一个,没想到已经有成品了。

    提个建议:
    之前在上海的时候,想去迪士尼,出发地点附近有两个地铁线:老西门站与小南门站;通过地图 APP ,告诉我老西门站距离较慢 /较远,建议小南门站;结果发现,小南门的确时间或许比较少,但是需要换乘 n 站,结果这个 APP 就没有计算出每个换乘站需要走多久,需要等下趟车多久。

    所以,能否再加入一些人工干预,比如:
    - 各个换乘站步行时间
    - 每趟车的间隔时间
    - 从出发点到地铁站的时间
    lgh
        17
    lgh  
       2016-08-04 12:23:32 +08:00
    jasonlee
        18
    jasonlee  
    OP
       2016-08-04 12:35:05 +08:00 via Android
    @kenshin 不显示换乘时间的考虑就是这个。这个程序的好处就是简单。如果要显示这么细的话,就变成地图了(笑)。列车间隔也很难搞,因为不同时候的间隔不同。不过多个首站确实值得考虑,我设计一下流程来。
    jasonlee
        19
    jasonlee  
    OP
       2016-08-04 12:45:06 +08:00 via Android
    @lgh 所以说是造了轮子嘛。
    jasonlee
        20
    jasonlee  
    OP
       2016-08-04 12:46:57 +08:00 via Android
    @kenshin 我用我的查了一下,小南门出发确实多换一次。
    zhen14
        21
    zhen14  
       2016-08-04 17:25:55 +08:00
    没有 iOS ?
    jasonlee
        22
    jasonlee  
    OP
       2016-08-04 17:30:33 +08:00 via Android
    @zhen14 iOS 我觉得直接浏览器放到桌面比较方便。
    run2
        23
    run2  
       2016-08-04 23:34:28 +08:00
    json 里没有发现里程 2 站间距离很重要吧(大概)-。-
    jasonlee
        24
    jasonlee  
    OP
       2016-08-05 07:56:45 +08:00 via Android
    @sobigfish 不是用里程,而是用时间。因为不知道换乘需要多少里程。而且快车哪怕多走一点,时间也比慢车短。不过里程对算票价很有用。
    jasonlee
        25
    jasonlee  
    OP
       2016-08-05 10:04:35 +08:00 via Android
    话说有什么新的城市需要添加么?比如北美和欧洲
    zjqzxc
        26
    zjqzxc  
       2016-08-05 11:42:18 +08:00
    查北京地铁的时候经常只出现一种路径,例如西直门到东直门只出现了二号线方案;五路居到五道口只出现了换成 10 号线方案;
    北京地铁换成很多幺蛾子, 4/9 换成有同站台换成, 2->1 下了楼梯就是,但 1->2 要绕一大圈。。

    不过话说这种公共交通工具查询这些地图软件已经很成熟了。。
    jasonlee
        27
    jasonlee  
    OP
       2016-08-05 20:13:02 +08:00 via Android
    @zjqzxc 西直门到东直门…莫非 13 号?其实这就是选路问题。
    同站台和人流管制确实很麻烦,但我也没有精力去一个个收集这种细节。
    这东西就是自己给自己开发的轮子,就图一个简单快捷而已。很多应用都做得更好。
    franklinyu
        28
    franklinyu  
       2016-08-08 02:45:31 +08:00
    @jasonlee {{15L}}:我感你其可以每「站」保存前 K 的路( K 是你自己定的常),然後分出一後程算。竟每「站」只需要算一次,工作量於服器不算大。用求到算好的站的候,「站」算序列中提取出,放到序列的前面,同用返回一「算中……」的回覆。
    franklinyu
        29
    franklinyu  
       2016-08-08 02:52:47 +08:00
    @jasonlee {{15L}}:或者可以看一下 StackOverflow : http://stackoverflow.com/q/4971850
    jasonlee
        30
    jasonlee  
    OP
       2016-08-08 09:04:24 +08:00 via Android
    @franklinyu 一般来讲找多条路径用的是 BFS 。但 BFS 的复杂度很高。我正在考虑的思路是一路存储,就是在 BFS 的时候顺手存储所有沿路的站点。 Dijkstra 是单点出发所有点,也是一种可行的思路。
    franklinyu
        31
    franklinyu  
       2016-08-08 10:25:27 +08:00
    @jasonlee {{30L}}:如何用 BFS 找多路?
    jasonlee
        32
    jasonlee  
    OP
       2016-08-08 12:17:10 +08:00
    @franklinyu BFS 的演算法是的,起出往遍,只要能到的都算一路,如果是死路返回。最困的地方在於,有的候由於分,很及返回。(我人,州、深圳和香港可以用 BFS ,上海、北京就法及返回果)。有一篇文章,可供聊作考。 http://eddmann.com/posts/depth-first-search-and-breadth-first-search-in-python/
    franklinyu
        33
    franklinyu  
       2016-08-08 13:25:45 +08:00
    @jasonlee {{32L}}:所以你的有重的?如果有重的度先搜索不能保最短路先返回。
    jasonlee
        34
    jasonlee  
    OP
       2016-08-08 14:38:38 +08:00
    @franklinyu 有重。可以退化重算,然後逐一算路所需的,在器用 Javascript 解。我看了一下 BFS 失的原因是存溢出,竟是 BFS 的老。
    jasonlee
        35
    jasonlee  
    OP
       2016-08-08 15:17:33 +08:00 via Android
    @franklinyu 排序的上是大。比起客端算排序,用一直接找最短路的算法更快一些,也更服器存。
    franklinyu
        36
    franklinyu  
       2016-08-09 00:57:47 +08:00
    @jasonlee 存溢出?一城市也就十站,而且地是稀疏,怎耗存?是 Javascript 垃圾回收太?
    franklinyu
        37
    franklinyu  
       2016-08-09 01:14:19 +08:00
    我在 CS.StackExchange 面你了一下,好像最好的方法也只是逐算了: http://cs.stackexchange.com/q/62383
    jasonlee
        38
    jasonlee  
    OP
       2016-08-09 07:39:11 +08:00 via Android
    @franklinyu 北京上海京都是百站。如果重就不是稀疏了(因不 0)。是疼的。我一始州深圳都是可以 BFS ,在做上海的候的才向 Floyd 。 BFS 大模的方法主要是剪枝,但怎剪是。
    jasonlee
        39
    jasonlee  
    OP
       2016-08-09 07:41:36 +08:00 via Android
    @franklinyu 事上更坑的是有一部分向行的(北京),此上成有向。了矩我毅然了功能。
    akaayy
        40
    akaayy  
       2016-08-10 21:58:53 +08:00 via Android
    百度地图。
    jasonlee
        41
    jasonlee  
    OP
       2016-08-11 06:09:19 +08:00 via Android
    @akaayy 这是个轮子。另外百度地图目前无法提示出站换乘和转乘。这方面做得比较好的其实是日本人。
    wshcdr
        42
    wshcdr  
       2016-08-11 14:57:24 +08:00
    以前写过类似的,这东西其实不容易写的...
    jojobobo
        43
    jojobobo  
       2016-08-11 21:01:52 +08:00
    非常帮,,哈哈 为什么你这么棒
    jasonlee
        44
    jasonlee  
    OP
       2016-08-12 11:21:03 +08:00 via Android
    @wshcdr 是的。很多容易掉进去的陷阱。也祝您编程之路愉快
    jasonlee
        45
    jasonlee  
    OP
       2016-08-12 11:21:19 +08:00 via Android
    @jojobobo 多谢夸奖。编程之路愉快。
    kyzylsy
        46
    kyzylsy  
       2016-08-17 17:48:35 +08:00
    web 版点击寻找线路根本没有反应。。。差评
    jasonlee
        47
    jasonlee  
    OP
       2016-08-17 20:19:30 +08:00
    @kyzylsy 是不是网络问题?一般多点几次会有结果。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1388 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 16:49 PVG 00:49 LAX 09:49 JFK 12:49
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86