V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
推荐学习书目
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 · 9672 views
    This topic created in 3607 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
        1
    aristotll  
       Jun 11, 2016
    ![3 个 example 都报错]( )
    protream
        2
    protream  
    OP
       Jun 11, 2016
    @aristotll 我是在 Ubuntu 下写的, Windows 下没有测试, 要不你帮忙看看哪有问题, 帮忙改一个啊。新手务怪。
    Allianzcortex
        3
    Allianzcortex  
       Jun 11, 2016
    挺有意思的一个应用。 argparser + termcolor 应该也可以
    xiahei
        4
    xiahei  
       Jun 11, 2016
    挺不错, Mark.
    imn1
        5
    imn1  
       Jun 11, 2016
    @protream
    有可视的返回信息,而不是报错,估计是编码问题
    xsxsxszs
        6
    xsxsxszs  
       Jun 11, 2016 via iPhone
    挺有意思的 哈哈 赞一个
    protream
        7
    protream  
    OP
       Jun 11, 2016
    @imn1 我觉得也是, 能帮忙看看吗, 我现在身边没有 Windows 系统
    krivol
        8
    krivol  
       Jun 11, 2016 via Android
    赞一个
    9hills
        9
    9hills  
       Jun 11, 2016   ❤️ 2
    @protream
    @imn1
    看代码就知道,你判断某个站是通过查表实现的,表的 key 是站名( utf8 )。表存储也是 utf8 存储的。所以在 Linux 上没有问题。

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

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

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