推荐学习书目
› 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 · Jun 11, 2016 · 10253 views
    This topic created in 3807 days ago, the information mentioned may be changed or developed.

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

    $ tickets 上海 北京 2016615
    

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

    $ tickets -dt 上海 北京 2016615
    

    结果如下,

    tickets

    其他参数

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

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

    $ pip install tickets
    

    安装使用.

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

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

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

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