Tag Archives: python

vicalloy的庄家

12306刷票工具

项目地址: https://github.com/vicalloy/12306-ticket-checker

只是在刷出票后发送提醒消息,并不能自动购票。在收到消息后还是得拼手速。 脚本用 Python3 实现,可挂到服务器上 24 小时刷。

前言

总体来说火车票应当是越来越好买,因此一直没怎么太操心。哪知道今年票似乎没有很好买,最近在 12306 刷了几天一张票都没看到。广大抢票软件又都只支持 Windows 系统,作为 Mac 用起来不是太方便。
弄了一个小脚本挂到服务器上,在查询到有符合条件的车票后将通过Slack将消息推送给我。

注意事项

  • 脚本采用python3开发,请使用python3运行该脚本。
  • 在刷到票后,采用 Slack 发送通知消息,因此请先创建Slack的Team。在创建好Team后,创建一个名叫ticket的channel,并申请一个Bot用于发消息。如希望采用其他的通知途径,请自行修改12306.py中的send_message实现。

后记

一大早就刷出了一大波票,不过等我兴冲冲的打开手机客户端一查,连个票的影子都没看到。可能是经过几年的发展抢票市场也日渐成熟,所有的票都在第一时间给抢票软件给刷走了。

TODO

目前这个脚本只能实现余票的提醒功能,但理论上要实现自动购票的功能并会太难。buy.py中给出了登陆的基础实现,不过考虑到实现所有功能所要付出的时间成本因此不打算继续了。
注:也是因为票被秒光的速度太快,估计折腾完也用处不大。

自动购票最大的障碍还是来自于12306的验证码。

验证码的处理思路

手动处理验证码

手动处理验证码应当是最简单有效的处理方式,当前缺点也很明显,无法做到全自动。Slack的API非常强大且易用,通过Slack的”Real Time Messaging API”,我们可以利用Slack实现交互。在需要输入验证码的时候,通过Slack将验证码推送到用户,用户在完成验证码输入后,系统自动处理之后的业务逻辑。

自动识别

要做好验证码的自动识别时间就比手动处理要麻烦多了。如果不是想卖给黄牛我个人是觉得没必要打自动识别的主意了。

12306的验证码可以分为2部分,最顶部的文字以及下方的8张图片。

文字的变形其实并不算太大,相信以现在OCR的水平识别率还是挺高的,重点是下发的8张图片。12306的验证码图小分辨率低,不说机器,要人来识别都不容易。如果纯粹根据机器学习来做图片识别,即使学习库再大效果也不会好到哪去。

最有效的还是”笨方法”,让系统频繁的去请求12306的验证码,然后手工将所有图片打上Tag。考虑到12306的图库不会太小,给图片打Tag必然会有很大的工作量,如果没有利益驱使是百分百做不来的。
另一方面,即使前期做了非常多的准备工作也很难保证12306不会添加新的图片。在遇到不认识图片的时候最简单的方法自然是先将图片记录下来等待手工加Tag,另一方面重新刷新验证换个自己认识的。
Google有提供上传图片进行搜索的功能,可以把图片上传到Google然后得到图片的关键字(当然精确度不会太高)。在图片资料库不够完整的时候也可以利用Google来猜些图。

编程

Python 3的type hints

近年来新出的语言Go、Rust、Swift都无疑例外的是静态类型。随着软件的越来越复杂,动态语言“太过随意”的缺点也越来越明显。此外随着IDE的发展,静态类型语言“繁琐”的缺点也得到了很好的规避。
在学习Swift的时候,Swift的类型推导给了留下了很深的印象。类型推导或许是现阶段兼顾类型检查以及动态语言简洁的最佳解决方案。
Python从3.5开始加入了type hints(类型注释)。

从名字“type hints”就可以看出,只是类型注释并不是强制要求。由于只是“注释”,“type hints”需要第三方工具的配合。你需要使用Mypy来对代码进行语法检查。另外PyCharm在新版本中也加入了对“type hints”的支持。

对我而言“type hints”无疑是一个非常棒的特性,让Python也具备了类似Swift的类型推导功能。希望日后的各类Python都能加入type hints的支持。另外就希望各类开发工具可以充分的利用type hints特性。

注:
Swift中使用“?”表示option,Python里则需要写成Optional[str]相比之下有些太过繁琐。

编程

django-lbutils

在Github上公开了不少项目,不过其中大多都算不上“开源”。在我看来开源也应当是一件认真的事情,需要对项目持续的维护,同时也需要提供必要测试用例及文档以保证项目的质量。
最近打算将自用的Django工具组件做个简单的整理然后发布了。为了让项目不要太“随意”,开始补测试用例及文档。因为是自用,测试用例和文档几乎为零。最初只是想简单的修葺,不想真正做起来工作比预期的要高出很多。整了许久代码中的注释依旧很不全,测试的覆盖率都还未达到80%,文档更是没开始动。因为文档还没弄完,所以项目也不算正式发布,如果你感兴趣可以先去看看django-lbutils
为了这个项目,尝试了一些之前经常看到却一直没怎么使用过的工具。

Tox

Tox是一个Python的自动打包测试用具,用来测试Python库在不同环境下的兼容性。因为是自用,本机环境跑起来是没啥问题。不过在兼容性测试时部分测试用例在Python3以及Django的某些版本下跑起来会有问题。为了搞定兼容性花费了不少时间。

Travis CI

Travis CI是一个在线的持续构建平台。Travis CI会检查你在Github上项目的变化,每当有新push的时候进行自动编译。我现在是每次改动后,直接在Travis CI看测试用例的执行情况。

Coveralls

Coveralls测试覆盖率查看工具。结合Travis CI,可在每次测试完成后将测试覆盖率信息推送到Coveralls。在Coveralls可方便查看当前的测试覆盖率。

Read the Docs

Read the Docs文档托管服务。可从Github抓取文档并自动编译好生成在线文档,目前几乎所有的Python库都将文档托管在上面。

编程

用程序生成word文档(DOC)

很多程序都支持导出PDF文档,不过如果需要对导出文档进行编辑PDF就显得不那么方便了。就国内环境而言,导出word文档对有编辑需求的文档而言更为合适。
由于我使用python,因此这里只讨论python下可用的方案。目前找到的解决方案主要有下面几种

  • python-docx
    目前能找到支持word格式的库非常的少,就python而言只找到 python-docx 算是相对可用的解决方案。python-docx 的功能非常的弱,有很多的限制,比如不支持模板等。如果想生成复杂文档那就无能为力了。
  • POD
    POD是Appy框架的一部分,可使用ODF (Open Document Format)文件做为模板,并输出ODF格式的文件,并可调用LibreOffice将生成的文件转换成DOC等格式。相比python-docx,POD用于生成更为复杂的文档。但如果你需要动态生成一些复杂表格,POD可能会有些问题。
  • unoconv
    unoconv是个文档转换工具,可调用LibreOffice对文档格式进行转换。unoconv可将HTML转换为DOC格式。因此可先生成HTML,然后再将HTML转换为DOC。生成HTML对广大的WEB开发者而言无疑是轻而易举的,这也是我最终选择的方案。不过要注意的是用unoconv将HTML转换成DOC,遍地是坑-_-!。

    • 只支持有限的HTML语法。很多CSS语法根本就不支持,看到的和转换出来的效果完全不一样。解决办法:在LibreOffice中编辑文档,然后保存成HTML,然后对保存的HTML进行编辑。
    • unoconv的-t参数可传入.ott格式的文档模板。默认情况下LibreOffice转换出的表格的行高远大于文字的高度,更糟糕的是文字还是顶对齐,非常不美观。编辑个空文档,然后保存为.ott,转换的时候指定模板文件可解决该问题。
    • 生成的文档的左右边距不一致。恩…,这个我还没有找到解决办法。
编程

让你的python程序同时兼容python2和python3

python邮件列表里有人发表言论说“python3在10内都无法普及”。在我看来这样的观点有些过于悲观,python3和python2虽然不兼容,但他们之间差别并没很多人想像的那么大。你只需要对自己的代码稍微做些修改就可以很好的同时支持python2和python3的。下面我将简要的介绍一下如何让自己的python代码如何同时支持python2和python3。

  • 放弃python 2.6之前的python版本
    python 2.6之前的python版本缺少一些新特性,会给你的迁移工作带来不少麻烦。如果不是迫不得已还是放弃对之前版本的支持吧。
  • 使用 2to3 工具对代码检查
    2to3是python自带的一个代码转换工具,可以将python2的代码自动转换为python3的代码。当然,不幸的是转换出的代码并没有对python2的兼容做任何的处理。所以我们并不真正使用2to3转换出的代码。执行 2to3 t.py 查看输出信息,并修正相关问题。
  • 使用python -3执行python程序
    2to3 可以检查出很多python2&3的兼容性问题,但也有很多问题是2to3发现不了的。在加上 -3 参数后,程序在运行时会在控制台上将python2和python3不一致,同时2to3无法处理的问题提示出来。比如python3和python2中对除法的处理规则做过改变。使用-3参数执行4/2将提示 DeprecationWarning: classic int division 。
  • from __future__ import
    from __future__ import”后即可使使用python的未来特性了。python的完整future特性可见 __future__ 。python3中所有字符都变成了unicode。在python2中unicode字符在定义时需要在字符前面加 u,但在3中则不需要家u,而且在加u后程序会无法编译通过。为了解决该问题可以 “from future import unicode_literals” ,这样python2中字符的行为将和python3中保持一致,python2中定义普通字符将自动识别为unicode。
  • import问题
    python3中“少”了很多python2的包,在大多情况下这些包之是改了个名字而已。我们可以在import的时候对这些问题进行处理。

  • 使用python3的方式写程序
    python2中print是关键字,到了python3中print变成了函数。事实上在python2.6中已经带了print函数,所以对print你直接按照2to3中给出的提示改为新写法即可。在python3中对异常的处理做了些变化,这个和print类似,直接按照2to3中的提示修改即可。
  • 检查当前运行的python版本
    有时候你或许必须为python2和python3写不同的代码,你可以用下面的代码检查当前系统的python版本。

  • six
    six 提供了一些简单的工具用来封装 Python 2 和 Python 3 之间的差异性。我并不太推荐使用six。如果不需要支持python2.6之前的python版本,即使不用six也是比较容易处理兼容性问题的。使用six会让你的代码更像python2而不是python3。

python3的普及需要每位pythoner的推动,或许你还无法立即升级到python3,但请现在就开始写兼容python3的代码,并在条件成熟时升级到python3。

注:

编程

编程语言们各自的哲学

曾有同事打算将ZOPE和PLONE啃下,我是不建议的。同事说我不够开放,对自己不喜欢的技术都很排斥。我承认,每个人都会有自己的偏好。但我不赞成使用ZOPE恰恰不是因为偏好问题,我也不会因个人偏好而建议采用或不采用某项技术。

在我看来ZOPE是一个很变扭的技术。ZOPE引入了接口/容器等概念,给人感觉ZOPE在很多方面都在有意的模仿JAVA。Python和JAVA在语言哲学方面有着比较大的差异,试图以Java的方式来做一个Python的WEB开发框架无疑是有些别扭的。如果ZOPE真的学的特别象,那我为什么不干脆直接使用Java?

这世界上存在各种编程语言,每种编程语言都有着自己的特点,正是这些差异满足了各类人的不同需求。这些编程语言都有着自己最核心的思想,这个核心思想就是所谓的“哲学”。没有自己“哲学”的编程语言是无法在这个世界上存活的。有些编程语言看上去问题很多,却很流行。或许它的那些问题也正是它流行的原因。

PHP

PHP的使用门槛非常的低,而且通常用PHP写出来的东西代码都不是那么的“漂亮”。于是有些人将PHP看成是业余程序员用的东西。然而就是这么一个看似不怎么专业的东西统治了大半个互联网。PHP的“哲学”是“quick and dirty”。在一定程度上beauty和quick并不容易并存。PHP将quick和简单作为第一要求,代码的漂亮退居第二。dirty的代码并不容易维护,所以通常在系统在复杂后,复杂业务逻辑功能将交由其他技术实现。PHP则安心做着自己表现层的事。

Java

有人说Java是给笨人用的语言。这话虽然很难听,不过在一定程度上这还真就是Java的哲学。Java充分利用语言特性和IDE等自动化工具来避免程序员犯错,让人海战术成为可能。对于大多Java项目只需要少数的牛人来设计系统构架和主要接口,下面的具体实现用“笨人”来做就可以了。

Python

python的哲学是“quick and clean”。在一定程度上说python确实非常clean也很quick。不过python的clean可让也让python变的有些平庸。python号称什么都能做,却又没在哪个领域特别突出。

Ruby

Ruby强调人文关怀,编程是一件有乐趣的事,你可以按照自己喜欢的方式去使用ruby。相对而言ruby可能更容易发挥个人的创造性,但在团队协作时则容易遇到麻烦。

编程

迁移到python3

python3自2008发布以来,已经历经了快4个年头。python3发布初期的速度慢,第三方开发库少的问题已得到了很好的改善。似乎已经没有太多的理由死抱着python2不放了。
考虑到目前的大多系统还都跑在python2.x上,直接迁移到python3还是有些冒进。最理想的方式是新代码都可实现python2&python3的兼容,日后可以平滑升级。下面的一些资料可以帮助你实现到python3的迁移。

vicalloy的庄家 编程

发布一个Django的论坛系统LBForum(开源、带演示)

简介

LBForum 用django开发的论坛系统,演示地址为:http://vik.haoluobo.com/lbforum/
项目的地址为:http://github.com/vicalloy/LBForum
界面部分抄的 FluxBB(一个开源的PHP论坛 http://fluxbb.org/ )。
虽然Django写的论坛也不少,不过还真没什么好用的。
大多Django论坛都是独立的app,而且不少还缺模板,想我这样有经验的Django用户要跑起来都觉得麻烦,其他普通用户就更别说了。
LBForum主要注重部署的方便性和易用性,功能方面目前还比较简单。
LBForum一开始就是以整站的形式提供,所以以LBForum做为基础项目进行二次开发是很容易的。
同时LBForum的开发尽量遵照Django可复用app原则,因此即使需要将LBForum做为独立的app集成到其他项目也并不会太难。

主要功能

目前功能还比较简单,而且还有些小问题有待修正。

  1. 论坛分类,分版块
  2. 发帖,回帖
  3. BBCode支持
  4. 置顶贴
  5. 使用django admin提供论坛管理功能

用开发服务器把LBForum跑起来

  1. 先把代码down下来。LBForum托管在github上,http://github.com/vicalloy/LBForum 。如果你没有安装git,你可以直接用界面右上方的download
    source功能下载代码。
  2. 运行\scripts\create_lbforum_env.py初始化lbforum的python虚拟环境。该脚本会自动创建一个python的虚拟环境并使用easy_install安装对应的依赖包,同时将一些依赖包解压到对应的目录中。
    注:django使用的是svn版本,所以机器上必须要安装有SVN,不然脚本会运行失败。如果因为由于svn的问题导致脚本运行失败,可以运行lbforum_env.bat进入lbforum环境,手动安装django的svn版本。
  3. 环境初始化好后,运行lbforum_env.bat进入lbforum环境
  4. 运行%mg% syncdb初始化数据库
  5. 运行%mg% runserver启动django开发服务器
  6. 进入admin,创建论坛分类和版块
  7. 进入版块发帖

LBForum的目录结构说明

|+lbforum_env/#lbforum运行的python虚拟环境,运行create_lbforum_env.py后自动创建
|+requirements/#lbforum用的第三方库和app,运行的时候会将该目录加到python路径
|~scripts/#工程相关脚本
| |-create_lbforum_env.py#初始化python虚拟环境,并自动安装easy_install/django依赖库
| |-helper.py#提供其他脚本所需的辅助函数
| -lbforum_env.bat*#启动lbforum运行的虚拟环境及,并为lbforum的manage.py提供快捷方式%mg%,比如初始化数据库%mg%
syncdb
|~sites/#站点配置/模板/静态文件
|
~default/#默认站点
|   |+static/#静态资源文件,如css等
|   |+templates/#Django模板目录
|   |+templates_plus/#Django模板目录,用户将自己重写过的目标放到该目录
|   -......
|~src/#django的app目录
| |+account/#account相关app。具体站点通常会对用户中心进行定制,所以该app在实际应用中很可能需要针对实际情况进行修改。
| |+djangohelper/#一些django的辅助函数等,
| |+lbforum/#lbforum的主app,论坛功能都在改app中
| |+lbregistration/#registration app的lbforum扩展,主要去掉邮件地址认证功能
| |+onlineuser/#显示在线用户的app(可复用的django app,可脱离lbforum单独使用)
|
+simpleavatar/#头像功能的app(可复用的django app,可脱离lbforum单独使用,依赖djangohelper)
|+tools/#工程用到的辅助工具,目前只有一个virtualenv的脚本

注:

  1. 由于计划在以后做i18n,所以目前只提供英文界面
  2. django的错误提示是显示在字段后面,fluxbb的错误全部都显示在表单前面。由于模板没有调好,所以目前按照fluxbb的方式显示错误,所以错误显示有些不太正常。
  3. bbcode的输入框本想做成自适应大小的,不过也调得有些问题,所以现在输入框的大小固定。
  4. 文档… ,感觉好难写-_-,目前文档不全(项目中没有带任何的文档),日后补上。
  5. 应用程序的目录结构主要查看pinax
  6. simpleavatar模块部分代码来自django-avatar
  7. 依赖包除用easy_install在线安装的外,尽量使用zip包的方式附带在项目中,减少安装依赖包的困难。
  8. 远程部署脚本计划使用fabric,但fabric本身安装比较麻烦,所暂未处理。
  9. 项目最早放在googlecode,不过感觉github的功能更强些,所以移了过去。
编程

SourceForge使用Python、TurboGears、MongoDB……来重构网站

pycon2010上关于SF网站重构的演讲,里面介绍了SF重构的技术选型及原因。在我看来SF用的东西还真的很GEEK。

主要用到的技术有Python、TurboGears2MongoDBJinja*、RabbitMQ,服务器用的是LigHTTPd和Nginx。

  • TurboGears2(为什么不的Django?)
    pdf中也有谈到此前也用到过django,而且有很不错的体验,但对SF的改造来说TG更为合适。SF有着上10年的历史,要完全抛弃原有的东西自然不现实,此次的网站重构并不是完全的重写。TG可以很容易的剥离掉不需要用到的东西,同时TG可以很好的同其他WSGI中间件配合工作。
  • MongoDB
    MongoDB是一个非关系的分布式数据库(NoSQL数据库),最大的优势快。由于这东西足够快,所以连web2.0网站常用的memcached也省掉了。(注:NoSQL数据库介绍可以参考 NoSQL数据库探讨之一 - 为什么要用非关系数据库)
  • Jinja*
    Django的模板很棒,但速度不怎么快,而且完全不支持任何嵌入式代码。Jinja和Django的模板长得非常的象,而且解决了上面的两个问题。(注:文档里说前台用的是PHP,所以不清楚是否有部分用到Jinja)
  • RabbitMQ
    用Erlang写的中间件,进行前后台的消息通信。SF的前台界面呈现,依旧使用的PHP,前后台通信用的就是这东西。
编程

Whoosh性能

早些时候就在google到Whoosh和xapian的性能对比文章,只是由于文章被墙,今天才翻墙看到。

文章是xapian作者写的。就文章里的对比结果来看,whoosh和xapian的性能差距还是比较明显。索引和搜索的速度有近4倍的差距,在full cache情况下的性能差距更是达到了60倍。

除算法原因外,whoosh的纯python定位也决定了whoosh很难达到其他c/java的搜索引擎库的速度。

当然,whoosh的优势是易用性,在考虑性能的情况下whoosh不是首先。

注:Xapian performance comparision with Whoosh