V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
protream
V2EX  ›  Python

Python 写了一个命令行火车票查看器.

  •  9
     
  •   protream · 2016-06-11 15:12:33 +08:00 · 8953 次点击
    这是一个创建于 3089 天前的主题,其中的信息可能已经有所发展或是发生改变。

    docopt 真是写命令行应用的神器啊, 刚撸了一个命令行查询火车余票的工具,tickets, 命令行下输入:

    $ tickets 上海 北京 2016615
    

    或者添加参数, 如 -dt获取动车和特快,

    $ tickets -dt 上海 北京 2016615
    

    结果如下,

    tickets

    其他参数

    • k 快速
    • g 高铁
    • z 直达

    项目已经提交到github 和 PyPI, 大家可以查看源码, 或

    $ pip install tickets
    

    安装使用.

    70 条回复    2016-06-18 17:41:49 +08:00
    aristotll
        1
    aristotll  
       2016-06-11 15:25:15 +08:00
    ![3 个 example 都报错]( )
    protream
        2
    protream  
    OP
       2016-06-11 15:39:43 +08:00
    @aristotll 我是在 Ubuntu 下写的, Windows 下没有测试, 要不你帮忙看看哪有问题, 帮忙改一个啊。新手务怪。
    Allianzcortex
        3
    Allianzcortex  
       2016-06-11 15:50:34 +08:00
    挺有意思的一个应用。 argparser + termcolor 应该也可以
    xiahei
        4
    xiahei  
       2016-06-11 15:52:09 +08:00
    挺不错, Mark.
    imn1
        5
    imn1  
       2016-06-11 15:54:37 +08:00
    @protream
    有可视的返回信息,而不是报错,估计是编码问题
    xsxsxszs
        6
    xsxsxszs  
       2016-06-11 15:55:24 +08:00 via iPhone
    挺有意思的 哈哈 赞一个
    protream
        7
    protream  
    OP
       2016-06-11 16:03:38 +08:00
    @imn1 我觉得也是, 能帮忙看看吗, 我现在身边没有 Windows 系统
    krivol
        8
    krivol  
       2016-06-11 16:04:47 +08:00 via Android
    赞一个
    9hills
        9
    9hills  
       2016-06-11 16:09:49 +08:00   ❤️ 2
    @protream
    @imn1
    看代码就知道,你判断某个站是通过查表实现的,表的 key 是站名( utf8 )。表存储也是 utf8 存储的。所以在 Linux 上没有问题。

    Windows 上默认命令行编码近似为 GBK ,自然就在表中查不到 key 。修复方法:

    1. 快速版:用 sys.stdin.encoding 拿到输入的编码,然后做输入编码转换,转换为 utf8 查找
    2. 最佳实践:同上,但是所有输入全部转换为 unicode ,读的站名表也转换为 unicode ,再去查表。
    protream
        10
    protream  
    OP
       2016-06-11 16:12:46 +08:00
    @9hills 感谢。看来我还需要再补补编码的知识。
    aristotll
        11
    aristotll  
       2016-06-11 16:19:21 +08:00
    @protream 类似这样是能取到的 from_station_code = stations.get(arguments['<from>'].decode('gbk').encode('utf8'))
    imn1
        12
    imn1  
       2016-06-11 16:20:06 +08:00
    @aristotll
    先运行"chcp 65001"(只需一次),再运行程序试试?

    @protream
    我 win 也没装 py ,但 win 简体,默认是 codepage936 ,也就是 GBK(非 GB2312)
    如果让 1 楼上面这个成功,就是编码问题,输入的是 GBK 编码,转换一下就行
    aristotll
        13
    aristotll  
       2016-06-11 16:20:10 +08:00
    @9hills 我 sys.stdin.encoding 还是取到'utf-8' 怎么才能取到'gbk'啊
    9hills
        14
    9hills  
       2016-06-11 16:27:19 +08:00
    @aristotll windows 上?,我这里实测可以
    C:\Python27>python
    Python 2.7.8 (default, Jun 30 2014, 16:03:49) [MSC v.1500 32 bit (Intel)] on wi
    32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import sys
    >>> print sys.stdin.encoding
    cp936
    >>>
    Allianzcortex
        15
    Allianzcortex  
       2016-06-11 16:28:54 +08:00
    所以最终原则是不要在 Windows 下编码,否则 GBK 会把你弄疯的。看了一下源码,其实是不用手动构造 query_url 的。 requests 里有一个参数是 params,直接用一个 dict 传进去就可以了。
    cashew
        16
    cashew  
       2016-06-11 16:34:35 +08:00
    Ubuntu 下完美运行。不错。
    21grams
        17
    21grams  
       2016-06-11 16:48:59 +08:00
    先 star 一个慢慢看
    heraldboy
        18
    heraldboy  
       2016-06-11 17:34:11 +08:00
    不错, mac 下没问题。
    protream
        19
    protream  
    OP
       2016-06-11 17:38:48 +08:00
    @Allianzcortex 谢谢指点。不知道为什么, 请求 12306 的参数顺序不对得不到数据,而用 dict 传参会打乱参数顺序
    protream
        20
    protream  
    OP
       2016-06-11 17:49:08 +08:00
    @Allianzcortex 改用 OrderedDict 了
    justou
        21
    justou  
       2016-06-11 17:55:46 +08:00
    @protream
    # For Python2
    if sys.version < '3':
    reload(sys)
    sys.setdefaultencoding('utf-8')

    看了下源码, py2 下这样做是很危险的, 会打乱整个程序的运行环境, 尤其是当使用了 sys.setdefaultencoding('utf-8')的代码被用到更大的程序中时, 程序何时崩溃都不奇怪, 一开始处理编码问题时也这样用, 直到程序莫名其妙的退出...
    http://stackoverflow.com/search?q=sys.setdefaultencoding%28%27utf-8%27%29
    protream
        22
    protream  
    OP
       2016-06-11 17:58:51 +08:00
    @justou 谢谢指点, 正要修改一下,统一为 unicode
    sudo987
        23
    sudo987  
       2016-06-11 18:26:26 +08:00 via iPhone
    iOS 下不能输入中文,怎么解决
    cc7756789
        24
    cc7756789  
       2016-06-11 18:53:44 +08:00
    这个数据是从哪里查的
    protream
        25
    protream  
    OP
       2016-06-11 19:38:25 +08:00
    @cc7756789 12306
    fhefh
        26
    fhefh  
       2016-06-11 23:20:49 +08:00
    nice
    sixer
        27
    sixer  
       2016-06-11 23:46:00 +08:00
    真不错
    Arnie97
        28
    Arnie97  
       2016-06-11 23:46:08 +08:00 via Android
    除了编码坑以外, ANSI 转义字符在 Windows 下也不能用。可以考虑 colorama
    araraloren
        29
    araraloren  
       2016-06-12 09:05:48 +08:00
    @cc7756789 12306 实时爬取的,否则有啥意义。。
    wujunze
        30
    wujunze  
       2016-06-12 10:20:40 +08:00
    最近在学 python mark 一下
    Tink
        31
    Tink  
       2016-06-12 10:31:10 +08:00 via iPhone
    这类界面一般是咋画出来的
    protream
        32
    protream  
    OP
       2016-06-12 11:06:18 +08:00
    @Tink Python 的一点好处就是有很多简单易用的库, 这是一个叫 PrettyTable 的库画出来的
    warcraft1236
        33
    warcraft1236  
       2016-06-12 11:08:17 +08:00
    没看具体的,不过当我看到 Linux 下编写, Windows 下没有测试,而且还是个命令行工具的时候,我就知道编码问题要出来了
    protream
        34
    protream  
    OP
       2016-06-12 11:08:36 +08:00
    @Arnie97 谢谢, 目前还没做 Windows 兼容, 以后会考虑使用
    protream
        35
    protream  
    OP
       2016-06-12 11:12:08 +08:00
    @warcraft1236 大神, 求指点
    warcraft1236
        36
    warcraft1236  
       2016-06-12 11:18:35 +08:00
    @protream 我也是初学者。也是头疼编码的问题很多次,才稍微了解一下。简单来说就是, Windows 下的 CMD 用汉字编码是 GBK ,而 Linux 这些是 UTF-8 , GBK 的字数少,所以有些 UTF-8 编码存在的文字, GBK 不存在,而且 GBK 是有损编码,所以这两个编码在转换中不能保持一致,就是 UTF-8 字符串转换成 GBK 然后再转成 UTF-8 之后,和原字符串不是相等的。具体的文章,伯乐在线有过相关文章,具体名字既不清楚了,是讲 MySQL 的 编码问题,讲了常用的编码是怎么回事
    protream
        37
    protream  
    OP
       2016-06-12 11:35:32 +08:00
    @warcraft1236 谢谢。感觉要是都用 utf-8 编码这个世界就清静了。
    cruisehu
        38
    cruisehu  
       2016-06-12 12:16:17 +08:00
    Could not find a version that satisfies the requirement ticket (from versions: )
    No matching distribution found for ticket
    wjfz
        39
    wjfz  
       2016-06-12 13:12:02 +08:00
    看评论想到一个段子: Pythoner 一半时间都在解决编码问题😂
    protream
        40
    protream  
    OP
       2016-06-12 13:54:04 +08:00
    @cruisehu 抱歉阿,版本更新的时候出了点问题
    shyling
        41
    shyling  
       2016-06-12 13:55:59 +08:00
    @wjfz +1
    protream
        42
    protream  
    OP
       2016-06-12 14:02:11 +08:00
    @wjfz
    @shyling 编码问题确实头疼, Python 还好,主要是跨平台的时候。
    Tinet
        43
    Tinet  
       2016-06-12 14:03:45 +08:00
    不知道这个数据源是哪里来的,我查了重庆到杭州的票,居然没有动车的信息
    protream
        44
    protream  
    OP
       2016-06-12 14:05:03 +08:00
    @Tinet 你查询的日期
    itlynn
        45
    itlynn  
       2016-06-12 14:05:58 +08:00 via iPhone
    @xiahei 又是你
    protream
        46
    protream  
    OP
       2016-06-12 14:10:43 +08:00
    @Tinet 如果你查的是今天的( 20160612 )那确实没有, 数据来源于 12306 , 不必有任何怀疑
    warcraft1236
        47
    warcraft1236  
       2016-06-12 15:32:01 +08:00
    @protream 你是准备做 Python 的开发吗?
    exoticknight
        48
    exoticknight  
       2016-06-12 15:37:44 +08:00
    argparser 跟这个的区别?
    我以前写一个爬广播数据的脚本是用 argparser 写的
    protream
        49
    protream  
    OP
       2016-06-12 15:44:17 +08:00
    @warcraft1236 是的。准备从 Python 做起。
    protream
        50
    protream  
    OP
       2016-06-12 15:45:15 +08:00
    @exoticknight 都是写命令行应用的工具,没本质区别, 只是解析参数的方式不一样
    Geoion
        51
    Geoion  
       2016-06-12 18:30:38 +08:00
    python 2.x 下这个编码问题啊,一颗赛艇 !! 口..口
    Tinet
        52
    Tinet  
       2016-06-12 22:29:33 +08:00
    @protream 呃...好像是查的今天的,明天我再试试
    alexapollo
        53
    alexapollo  
       2016-06-12 22:36:20 +08:00
    很有趣啊,不过有 JSON 格式的输出吗?
    protream
        54
    protream  
    OP
       2016-06-12 22:45:37 +08:00
    @alexapollo 添加一个功能导出 Json 或 cvs 什么的并不难,不过有什么用?
    alexapollo
        55
    alexapollo  
       2016-06-12 22:47:57 +08:00
    @protream 比较好复用,或者做成包来复用也不错
    richzhu
        56
    richzhu  
       2016-06-12 23:27:17 +08:00 via iPhone
    不错,留言 mark
    a414121088
        57
    a414121088  
       2016-06-13 10:45:18 +08:00
    请问写了多长时间
    qooweds
        58
    qooweds  
       2016-06-13 14:44:52 +08:00
    @protream 是只能查询本月的数据吗?
    tickets 上海 北京 20160701
    Not a valid date.
    protream
        59
    protream  
    OP
       2016-06-13 14:52:07 +08:00
    @a414121088 断断续续加起来一个晚上吧,主体并不难,主要是一些细节优化
    protream
        60
    protream  
    OP
       2016-06-13 15:07:43 +08:00
    @qooweds 不应该啊,默认支持 50 天内的查询。难道又是编码的问题?你有试试其他数据格式吗?另外新的版本这俩天会发布,到时候会有新的功能, 敬请关注:)
    qooweds
        61
    qooweds  
       2016-06-13 15:13:52 +08:00
    @protream 我也是 ubuntu
    tickets 上海 北京 20160630 有结果
    tickets 上海 北京 20160701 就没结果了
    shyling
        62
    shyling  
       2016-06-15 22:05:20 +08:00 via iPad
    我写了个 ruby 版的 0 0
    protream
        63
    protream  
    OP
       2016-06-15 22:30:37 +08:00
    @shyling 不错,支持
    publicAdmin
        64
    publicAdmin  
       2016-06-16 14:35:42 +08:00
    Mac os 10.11 下 python2.7 下报错。- -
    lk1ngaa7
        65
    lk1ngaa7  
       2016-06-16 22:35:02 +08:00
    想问下作者,火车票的数据是直接抓取 12306.cn 还是其他的 api 接口?
    protream
        66
    protream  
    OP
       2016-06-16 22:41:29 +08:00   ❤️ 1
    @lk1ngaa7 12306 一个掩藏的接口,具体你可以看源码
    lk1ngaa7
        67
    lk1ngaa7  
       2016-06-16 22:49:48 +08:00
    @protream 赞,我来看下,不知道这个接口会不会限制访问次数,你试过没?我有一个单 IP 机器抓取车票数据的需求。
    protream
        68
    protream  
    OP
       2016-06-16 23:12:53 +08:00
    @lk1ngaa7 并没有试过,你这是要抓取多少数据啊?
    pengliang
        69
    pengliang  
       2016-06-18 16:31:30 +08:00
    UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)
    protream
        70
    protream  
    OP
       2016-06-18 17:41:49 +08:00   ❤️ 1
    @pengliang 新版本不支持 Python2 了, 用 pip3 装,或者去 github 下载源码安装
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3368 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 12:00 · PVG 20:00 · LAX 04:00 · JFK 07:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.