Solrex's profileSolrex Shuffling.LifeBlogListsNetwork Tools Help

Blog


    10/29/2008

    DIY Free Weather Forecast SMS

    定制自己的免费天气预报短信

    作者:杨文博 < http://blog.solrex.cn >
    地址:http://blog.solrex.cn/articles/diy-free-weather-forecast-sms.html

    摘要:这篇博客介绍了一种在 Linux 下使用飞信(libfetion 库)来定时发送天气预报短信的方法。本文的主要贡献是:一、提供了一个 Linux 下发送飞信的命令行程序;二、提供了一个到中国气象网抓取、过滤天气信息并发送短信的脚本。

    天气预报短信一直是移动通信公司提供的一种收费服务,Google 免费天气预报服务打破了这个僵局。但是Google 的服务很不稳定,经常收不到短信,而且天气预报内容的定制性差。我家 xixi 一直有看天气预报的习惯,我就告诉她说我能写个程序每天给你发天气预报消息,她不相信,然后我就写了下面的程序。

    首先感谢一下 mirth@bbs.nju.edu.cn,本文的主要内容是基于他在小百合 BBS 上发表的如何用飞信定时给自己发免费天气预报一文做的少许改进。

    1. 发送飞信的命令行程序

    这个程序主要基于邓东东开发的 libfetion 库。这个库不是开源的,但是作者提供了头文件和库文件(在GUI源代码中),所以我们可以使用它的 API 来写一些自己的程序。下面的程序内容很简单,注释也不少,我就只贴源码,不再解释了(注意,编译时需要 curl 的 dev 库)。你可以在这里下载到我的 sendsms 小程序的源代码

    $ls
    include lib Makefile sendsms.cpp
    $ more sendsms.cpp Makefile
    ::::::::::::::
    sendsms.cpp
    ::::::::::::::

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <argp.h>
    #include "include/libfetion.h"

    /* Version, contact, user defined doc, argument doc strings for argp.h. */
    const char *argp_program_version = "sendsms 0.1";
    const char *argp_program_bug_address = "<solrex@gmail.com>";
    static char doc[] = "Options:";
    static char args_doc[] = "MESSAGE";

    /* Program options we understand. */
    static struct argp_option options[] = {
      {"from",   'f', "SENDER",    0, "The sender's fetion/phone number." },
      {"passwd", 'p', "PASSWD",    0, "The sender's password." },
      {"to",     't', "RECEIVER"0, "The receiver's fetion number." },
      { 0 }
    };

    /* Used by |main| to communicate with |parse_opt|. */
    typedef struct _args {
      char *from;       /* Sender's phone/fetion number string pointer. */
      char *passwd;     /* Sender's password string pointer. */
      char *to;         /* Receiver's phone/fetion number string pointer. */
      char *message;    /* SMS message body pointer. */
    } ARGUMENTS;

    /* Parse a single option. */
    static error_t
    parse_opt (int key, char *arg, struct argp_state *state)
    {
      /* Get the input argument from |argp_parse|, which we know is a pointer to
       * our |ARGUMENTS| structure. */
      ARGUMENTS *p_args = (ARGUMENTS *)state->input;
      /* Parse option key. */
      switch (key) {
        case 'f':
          p_args->from = arg;
        break;
        case 'p':
          p_args->passwd = arg;
        break;
        case 't':
          p_args->to = arg;
        break;
        case ARGP_KEY_ARG:   /* We have only one(none-option) argument: MESSAGE. */
          if (state->arg_num > 1)  
            argp_usage (state);
          p_args->message = arg;
        break;
        case ARGP_KEY_NO_ARGS:      /* The MESSAGE argument can not be ignored. */
          argp_usage (state);
        break;
        case ARGP_KEY_END:
          if (state->arg_num < 1)   /* The MESSAGE argument can not be ignored. */
            argp_usage(state);
        break;

        default:
          return ARGP_ERR_UNKNOWN;
      }
      return 0;
    }

    /* |argp| structure used by |argp_parse| function. */
    static struct argp p_argp = {options, parse_opt, args_doc, doc};

    int main(int argc, char** argv)
    {
      ARGUMENTS args;
      int ret;
      long int uid;

      /* Default option values. */
    #if 0
      args.from = "136xxxxxxxx";
      args.passwd = "*********";
    #endif
      args.to = NULL;

      /* Parse our arguments; every option seen by |parse_opt| will be reflected
       * in |args|. */
      argp_parse (&p_argp, argc, argv, 0, 0, &args);

      if (!fx_init()) {                         /* Init libfetion. */
        fprintf(stderr, "Failed to init.\n");
        return 1;
      }
      ret = fs_login(args.from, args.passwd);   /* Login with id and passwd. */
      if (!ret) {
        fprintf(stderr, "Failed to login.\n");
        return ret;
      }
      /* If "-t" option is ignored, send the MESSAGE to the SENDER-self. */
      if (args.to == NULL) {
        ret = fs_send_sms_to_self(args.message);
      } else {
        /* If "-t" option is a mobile phone number, use API:
         * |fs_send_sms_by_mobile_no|. */
        /* FIXME!/Wenbo-20081028: It doesn't work with libfetion 0.81. Maybe a
         * bug exsits, so we can only use fetion num as the value of RECEIVER. */
        if (strncmp(args.to, "13", 2) == 0) {
          ret = fs_send_sms_by_mobile_no(args.to, args.message);
        } else {
          /* If "-t" option is a fetion number, use API: |fs_send_sms|. */
          uid = strtol(args.to, NULL, 10);
          ret = fs_send_sms(uid, args.message);
        }
      }
      if (!ret) {
        fprintf(stderr, "Failed to send.\n");
        return ret;
      }
      /* Logout, disconnect and release resources. */
      /* FIXME!/Wenbo-20081028: |fx_loginout| doesn't work in this case. */
      //fx_loginout();
      fx_close_network();
      fx_terminate();
      return 0;
    }

    ::::::::::::::
    Makefile
    ::::::::::::::

    CC = gcc
    CPP = g++
    CFLAGS = -Iinclude -O2
    LFLAGS = lib/libfetion_32.a -lcurl -pthread

    BIN = sendsms
    SRCS = $(BIN).cpp
    OBJS = $(BIN).o

    $(BIN): $(OBJS)
        $(CPP) $^ $(LFLAGS) -o $@

    $(OBJS) : %.o : %.cpp
        $(CPP) $(CFLAGS) -c $<

    install: $(BIN)
        install $< /usr/bin

    clean:
        @rm -rf *.o

    distclean: clean
        @rm -f $(BIN)

    2. 到中国气象网抓取、过滤天气信息并发送短信的 bash 脚本

    你可以从这里下载到下面的 bash 脚本,或者到这里下载几乎同样功能的 python 脚本。脚本就不多做解释了,没几行代码,相信稍微研究一下就能看懂。

    $ more weatherman.sh
    #!/bin/bash
    CITY_LIST=("南京" "北京" "郑州")
    URL_LIST=("101190101" "101010100" "101180101")
    URLBASE="http://www.weather.com.cn/html/weather/"

    MY_CITIES=("南京" "北京")
    SMS_USER=("yyyyyyyyy")
    SMS_CITY=("郑州")

    get_html()
    {
      i=0
      for city in ${CITY_LIST[*]}; do
        url=$URLBASE${URL_LIST[i]}.shtml
        wget -O $city.txt $url
        i=$(($i+1))
      done
    }

    parse_html()
    {
      for city in ${CITY_LIST[*]}; do
        # Select useful part.
        if [ $(date +%H) -lt 18 ]; then
          sed -i -e '1,/c_1_1/d;/c_1_2/,1000d;' $city.txt
        else
          sed -i -e '1,/dd_0/d;/surf/,1000d;' $city.txt
        fi
        # Remove HTML tags.
        sed -i -e 's/<[^>]*>//g;/<!--/d' $city.txt
        # Remove empty lines.
        sed -i -e 's/&nbsp;//g;s/&deg;C//g;s/^\s*//g;/^$/d' $city.txt
        sed -i -e '11,$d;' $city.txt
        # Cut verbose words.
        sed -i -e 's/℃//g;s/高温//g;s/低温//g;s/://g;s/指数//g;' $city.txt
        sed -i -e 's/星期/周/g;'  $city.txt
        # Format file content to SMS.
        MES="${city}天气\n"
        MES=$MES`sed -n -e '1p' $city.txt | tr -d '\r\n'`:
        MES=$MES`sed -n -e '2p' $city.txt | tr -d '\r\n'`,
        MES=$MES`sed -n -e '4p' $city.txt | tr -d '\r\n'`
        MES=$MES`sed -n -e '3p' $city.txt | tr -d '\r\n'`度,
        MES=$MES`sed -n -e '5p' $city.txt | tr -d '\r\n'`'\n'
        MES=$MES`sed -n -e '6p' $city.txt | tr -d '\r\n'`:
        MES=$MES`sed -n -e '7p' $city.txt | tr -d '\r\n'`,
        MES=$MES`sed -n -e '9p' $city.txt | tr -d '\r\n'`
        MES=$MES`sed -n -e '8p' $city.txt | tr -d '\r\n'`度,
        MES=$MES`sed -n -e '10p' $city.txt| tr -d '\r\n'`
        echo -ne $MES >> $city.txt
        sed -i -e '1,10d' $city.txt
      done
    }

    send_forcast()
    {
      for city in ${MY_CITIES[*]}; do
        sendsms -f 13xxxxxxxxx -p ******** "`cat $city.txt`"
      done
      i=0
      for user in ${SMS_USER[*]}; do
        sendsms -f 13xxxxxxxxx -p ******** -t ${SMS_USER[$i]} "`cat ${SMS_CITY[$i]}.txt`"
        i=$(($i+1))
      done
    }

    clear_html()
    {
      for city in ${CITY_LIST[*]}; do
        rm -f $city.txt
      done
    }

    get_html
    parse_html
    send_forcast
    clear_html

    3. 将脚本设置为定时执行

    安装好 sendsms 到 /usr/bin 之后,将上面脚本放到 YOURPATH 下,然后在命令行执行:crontab -e,将下面一行添加进去:

    30 18 * * * /YOURPATH/weatherman.sh 1> /tmp/weatherman.out 2> /tmp/weatherman.err

    就设置为每天下午 6 点半发送天气预报短信。

    10/26/2008

    Failed to Install Ubuntu 8.10

    今天上午四个小时的折腾:

    1. 想装个 FreeBSD 6.2,出现未知错误,找不到 /dev 下面的一个东西(仿佛回到了刚开始学 Linux 的时代);

    2. 把分区表搞坏,一个扩展 data 分区丢失(这绝对是 FreeBSD 的问题,因为在安装时分区表中居然把这个 ext3 分区标示为 unused),我也居然愚蠢到认为不到最后时刻它就不会写入分区表;

    3. 既然 data 都丢了,就随便再装个 Ubuntu 8.10 玩玩吧,结果遇到安装光盘的 bug。整整花了我两个小时呀,下了 RC 和 dailybuild 两个光盘镜像,都是一个问题,到 launchpad.net 就发现还好不是我一个人在战斗,然后也插了一腿子。我发现这是我自从注册 launchpad 那几天以来第一次登录,注册时间是 2006-06-10。

    4. 到了最后,还是用我原来的 Ubuntu 8.04,把分区重新建立挂载起来。转了一圈,啥也没捞着。

    得了一个教训,再也不在双系统上装 FreeBSD 了,居然会犯连 RedHat9.0 都不可能犯的错误,连正确的分区表都识别不出来。

    10/22/2008

    Ibus Input Method

    Ibus 输入法

    由于种种历史遗留问题,本人惯用的汉字输入习惯和大多数人不一样:双拼输入法,并且是智能 ABC 风格的。这也就决定了我选择输入法的时候首先看它是不是支持我习惯的风格。以前 Google 推出中文输入法的时候,我的反应就很慢,因为不确定它是否支持双拼,后来发现它对智能 ABC 风格的双拼支持的很好,我在 Win 下的输入法就换成了 Google 的。

    听说 Linux 下的 Ibus 输入法已经很久了,也是因为同样的原因没去尝试。搜索 "Ibus 双拼",往往得不到有用的信息。今天在 Ubuntu 中文社区看到一张,发现已经有双拼支持,才让我下定决心尝试一下。

    Ibus 已经被打包到了 ubuntu-cn 的源里(注意,不是 ubuntu),可以直接 apt-get install ibus-pinyin。由于我的 locale 是 en_US.UTF-8,所以 im-switch 不好用,只好将输入法选择写到 ~/.profile 里:

    XIM=ibus
    XIM_PROGRAM=/usr/bin/ibus
    XIM_ARGS=""
    GTK_IM_MODULE=ibus
    QT_IM_MODULE=ibus
    DEPENDS="ibus"

    然后 re-login。网上有各种配置方法,其实我也不知道该怎么写才对,但输入法的启动不就是 X 启动时运行一个脚本嘛,从 /etc/X11/xinit/xinput.d/ibus 拷贝出来的东西总该没错。

    第一次启动输入法需要选择 engine,这一点要比 scim 好,scim 默认就把乱七八糟的 engine 都给你配置上,还需要一个个去删除。然后再找配置双拼的地方,开始怎么也找不到,为什么不在 preferences 里呀?最后才想起来去看看那个输入法的语言条,才发现和 Google 拼音一样,启动配置在语言条的最后一个图标。

    然后就开始码字,使用感觉是相当的爽的,界面比 scim 好看, 用户词库的记忆效果貌似也比 scim 好。而且 scim 在处理双拼时候一直有一个问题:只显示键字母而不显示拼音。就比如"将"这个字用 ABC 双拼打是"jq",在 scim 里拼音栏只会显示"jq",而不是把"q"转换成"iang",ibus 就没有这个问题。

    目前来讲,ibus 最大的问题是反应有一点点慢,当打字速度快的时候,可能最后一个键没有记录上就把前面的输出了。比如打"将"时,jq空格,如果空格敲得太快,可能出现的 是"就q",大概也跟我使用的机器比较慢有点儿关系。这篇文章就是用 ibus 敲的,速度还可以忍受。

    我把 scim 给删掉了,准备使用 ibus 一段时间,看看它是不是会引起一些程序的工作不正常。对 scim 引起的 KDE 程序崩溃和输入法不可用的毛病我已经容忍很久了,早就祈祷着到 Google 工作的 suzhe 能够继 scim 之后推出 Google 拼音的 Linux 版,目前看来 ibus 大概可以满足一下我的大部分需求。

    10/21/2008

    JabRef Quick Guide

    文献管理软件 JabRef 快速入门

    作者:杨文博 < http://blog.solrex.cn >
    地址:http://blog.solrex.cn/articles/jabref-quick-guide.html

    摘要:这篇博客主要介绍文献管理软件 JabRef 及其使用方法,适用对象为 LaTeX 用户、非 Windows 操作系统用户和用不起 EndNote 的 Windows 用户。

    我曾经非常愚蠢地认为手工维护自己的参考文献库就可以了,但随着看过论文的增加,文献的管理成为一件痛苦的差事。最近才领略到使用文献管理软件的方便。 JabRef 的中文教程比较少而不全,所以就写了这篇博客,简要介绍一下这个软件的使用方法。

    JabRef 图例(如果您无法看到此图,可能因为您无法连接国外网站)

    目录
    1. 软件介绍
    2. 建立数据库
    3. 导入文献条目
    4. 管理文献条目
    5. 与 vim 结合使用
    6. 其它应用
    7. 结语

    1. 软件介绍

    JabRef 是一个开源的参考文献管理软件,使用 Java 语言编写,所以天生具有跨平台特性,通用于安装有 Java 支持的 Windows, Linux 和 Mac,软件主页在:http://jabref.sourceforge.net/。它可以很方便地管理下载到本机的文献,生成 BibTeX 文献数据库,供 LaTeX 或其它软件使用,可以与 Kile, Emacs, Vim, WinEdt 等多种软件结合使用。

    JabRef 适合什么人使用?总的来说 JabRef 最大的特点就是使用 BibTeX 格式的数据库,所以它最适合 LaTeX 用户使用;如果仅仅使用它的管理功能,也可以用于本地电子书的管理;对于使用 M$ Office 写论文的用户来说,EndNote 是最好的选择,它能集成到 M$ Word 中,所以不推荐使用 JabRef。

    JabRef 当前最新版本是 2.4.1,如果你发现自己的 JabRef 不支持某些特性,最好检查一下版本信息。本文使用 Linux 下的 JabRef 演示,其它系统下应该没有什么不同。

    2. 建立数据库

    JabRef 的文献数据库是纯文本的 bib 文件,可以将该数据库文件放在该主题文献的目录下。比如要建立一个 p2p 方向相关文献的数据库,只需建立一个 p2p 目录,在 JabRef 中选择 File->New Database,然后 Ctrl-s,将该数据库起名 p2p.bib,保存在 p2p 目录下。然后将 File->Database properties 中的 Database Encoding 和 Directory 都设置成 p2p 目录。

    3. 导入文献条目

    文献数据库的内容自然是一篇一篇的论文,每篇论文在数据库中占一条记录。那么如何添加论文呢?自然不必全部手工添加,几乎所有的数据库在提供论文下 载的同时都有该论文 citation 信息的下载,下面这张图上是计算机科学类常用数据库网站的 citation 下载链接示例。也许你以前不知道它们是做什么用的,但你总能在文章下载页面的某个地方找到它们。

    Citation 下载链接(如果您无法看到此图,可能因为您无法连接国外网站)

    聪明如你,肯定知道该怎么做吧。点开 citation 的链接,将内容保存为相应的文件名。比如 BibTeX 格式的 citation 信息,将其保存到名为 xxx.bib 的纯文本文件中,然后到 JabRef 里选择 File->Import into current database,将该文件导入当前数据库,你就会发现数据库中多了一条记录。当然,JabRef 支持很多 citation 信息格式,但是既然 JabRef 采用 BibTeX 格式管理数据库,我们还是尽量下载 BibTeX 格式的 citation。

    每次只导入一条记录未免太麻烦了些,由于很多参考文献信息都是纯文本格式的,那么我们可以将很多条记录分段拷贝到 xxx.bib(或者 xxx.ris 等) 里,然后集中导入。

    4. 管理文献条目

    文献数据库的条目建立起来了,但是这只是一些 citation 和 abstract 信息,那么如何将下载下来的论文 pdf/ps 文件和它们对应的条目关联起来呢?

    只需要将下载下来论文的文件名保存成特定的格式,一种方法是文件名中包含 BibTeXkey,如果是 A. Yao 在 2005 年发表的文章,文件名就起为 xxx-Yao2005-yyy.pdf;一种方法是文件名包含论文名。然后修改匹配规 则:Options->Preferences->External Programs->Use Regular Expression Search 文本框,比如在当前目录下匹配包含 BibTeXkey 的文件:"./.*[bibtexkey].*\\.[extension]",在当前目录下匹配包含论文名的文件:"./.*[title].*\\. [extension]",在子目录中匹配包含 BibTeXkek 的文件:"**/.*[bibtexkey].*\\.[extension]"。如果我们把文献数据库 bib 文件和 pdf 文件放在同一目录下,只需要使用在当前目录下匹配即可。

    文件名和匹配关系修改好了,那么我们就可以将论文记录关联到文件了。双击某论文条目,或者选中后按 Ctrl-e,就可以编辑该条目。进入 General 选项卡,在 File 条目后面点 Auto,JabRef 就会按照匹配规则搜索匹配的文件,关联到该条目。如果能搜索到 pdf 文件,关联后该条目的前面会出现一个 pdf 图标,点击该图标,就可以直接打开该论文的 pdf 文件。除了自动匹配以外,也可以使用 Auto 旁边的 + 号手动添加文件。

    JabRef 图例(如果您无法看到此图,可能因为您无法连接国外网站)

    当然了,文献条目的其它信息我们也可以编辑。比如 ACM 的 BibTeX 中往往不包含摘要信息,我们可以在 Ctrl-e 以后的 Abstract 选项卡中添加对应论文的摘要信息;Springer 的 ris 信息往往过于简单,我们也可以通过网页信息添加一些条目;如果你对某篇文献有深刻印象或者想记一下笔记,可以在 Review 选项卡中记录下自己的想法。

    5. 与 vim 结合使用

    前面说过,JabRef 可以和很多软件结合使用,但是有一些软件我并不熟悉,所以这里仅仅介绍一下 JabRef 和 vim 关联使用的技巧。

    JabRef 是使用 vim server 和 vim 通信的,所以这要求双方使用同样的 vim server 名。在 JabRef 一端,Options->Preferences->External Programs->Vim Server Name 文本框中就是 vim server 名,你可以使用默认的 vim 服务器名 vim,也可以修改成任意名字,比如 solrexvim;在 vim 一端,编辑 LaTeX 文件时不要使用通常的命令启动 vim,要加上 vim 服务器名,比如 vim --servername solrexvim --remote-silent xxx.tex,这条命令的意思是:使用 vim 连接到服务器 solrexvim 修改 xxx.tex 文件,如果该服务器不存在,就创建它。

    等 JabRef 和 Vim 都启动了以后,如果在编辑 tex 文件的时候想加入某条文献的引用,只需要在 JabRef 上方的工具栏中先选择出 Vim,然后再点击该图标,vim 光标所在位置就会自动加入该文献的引用。

    6. 其它应用

    总的来说,JabRef 的作用主要是参考文献管理工具,但是也可以使用它来做一些其它的工作,比如个人数字图书馆。每个人电脑里可能都有一些电子书,有的人特别多。为了查阅方 便,一般都会把电子书分门别类放到一个目录树中,每次找文件都要进到很深的目录下;有时候为了系统兼容性,避免使用中文文件名,理解一个文件对应哪本电子 书成为一件痛苦的事。如果使用 JabRef 作为文件管理工具,就可以根据作者,书名排序或者直接检索,会方便很多。

    7. 结语

    本文简要介绍了 JabRef 的基本使用方法。我也是刚刚接触这个软件,对其体会并不深刻,可能 JabRef 还有很多特性可以加以发掘,就留给大家一起探索吧。

    10/16/2008

    A Chance For Linux and Freeware

    连着忙了几天,今天闲话几句。

    关于微软正版验证

    我家希希说:"我要被黑屏了,怎么办呀?我要学 Linux!"

    我说:"没关系,你把自动更新服务关掉就行了。"

    我家希希说:"我还是想学 Linux!"

    微软准备在 2008 年 10 月 20 日对中国用户启动的 WGA 计划这几天被吵得沸沸扬扬,搞得几乎人人自危,生怕被黑屏了。本人的评论如下:

    • 对此措施,我持欢迎态度。这件事起码给中国的盗版用户提了个醒:软件是有知识产权的!用盗版的操作系统很开心,用盗版的应用软件也很开心,到最后是中国整个落后的软件产业不开心,软件民工们也不开心。

    • 对于效果,我持保留态度。我相信中国盗版产业中广大劳动人民的智慧!

    • 对于影响,我持乐观态度。这是一个 Linux 和免费软件的机遇。此次 WGA 计划一出,势必会督促那些已经有学习其它操作系统愿望的用户真正动起手来,也会使那些使惯了盗版 Office 的人考虑一下免费的优秀国产软件 WPS Office,进而认识到许多优秀的免费软件并不比收费软件差

    最后友情提醒一下,WPS Office 2007 目前已更新到支持 M$ Office 2007 文件格式( .docx, .xlsx, .pptx ),免费的国产软件 Foxmail 和"进口软件" Thunderbird 都可以替代 Outlook , Ubuntu 8.10 还有 14 天就发布了。

    关于看论文

    最近被老师逼着快速浏览了大量论文,发现自己以前看论文的效率还是太低。眼高手低的毛病总是改不了,做研究还是要潜心进去。

    关于看书

    每天睡前逼着自己看一会儿书效率挺高的。豆瓣上我在读的书已经超过二十本了,平日很难分出大块时间看,目前已经利用睡前十分钟解决了两本。躺床上用 台灯看书的感觉蛮惬意的,置身于黑暗中的一小片光明,仿佛又回到了中学时代。当然这也得益于现在宿舍的环境布置,床头就是写字桌,要是像以前在中关村时住 上铺的话,势必就会影响室友的睡眠了。

    关于 writeos

    九月份更新了两次,十一假期无暇写字,第三章到现在还没写完,我希望十月底能完成发布第二个版本。上个星期一个墨西哥的小伙子加我 Gtalk,问这本书的问题,开始我还以为是华裔,后来知道人家根本不懂中文,没办法只好推荐他去看代码注释。也许等我再完成两章之后,会和某些朋友合作 开始将它翻译成英文。

    10/9/2008

    Golden Week 200810

    十一黄金周长假结束几天了,但回来之后时间一直安排得很满,没空更新博客。今天北京下了点小雨,羽毛球打不成,轮滑也玩不了,就写几个字吧。

    继买火车票不顺之后,我再次经历了凄惨的火车旅途。9 月 28 号那天赶到北京火车站的时间有点儿晚,T65 已经开始检票很长时间了,当我赶到站台上时,发现车厢门口仍然挤着一些人。我本以为人还没有上完,谁知道走近一看却发现是挤不上去,整个车厢跟上班高峰期的北京地铁似的。懊恼迟到之余,总得往上挤呀,于是开始一点一点往里蹭,整整蹭了半个小时,只蹭进去一米!还好蹭进去了一米,关车门的时候没把我关在外面,T65 的乘务员太厉害了,愣是把那么多人给劝下来,准时关上了车门,按点开出了北京站。

    发车之后乘务员打开车厢内厕所门,我和另外两个人就躲进了厕所里,期间被上厕所的人赶出去几次,但最后还是在里面呆了七个小时。自从我五岁以后,就 再也没坐过那么挤的火车,车厢里站的地方都没有,相比而言还是厕所里舒服一些。但随之而来就有一个问题,困了怎么办?因为厕所里有三个人,只能站着睡觉, 那个痛苦呀!我只能用手吊在窗户的栏杆上打瞌睡,稍微一深睡,腿马上支撑不住,膝盖一弯就要往下掉。当时我真的羡慕那些四条腿的马啊牛啊,它们真厉害,能站着睡觉。

    这种情况一直持续到第一个停车站,徐州。站了七个多小时到凌晨五点,我腿疼得实在受不了了,就趁在徐州停车时人刚下完,而上车的人还没进来之时,冲 到车厢中部,找了一个相对大一点儿的位置,打开我带的小马扎,坐了下来。好歹算是相对舒服地趴在自己腿上睡了两个小时,这时候坐得屁股又开始疼了。于是站 站坐坐,坚持到九点到南京,总算能解放了,当时那个心情舒坦啊!

    在南京的生活倒是很轻松啦,无非是陪女友逛逛街、吃吃饭,没什么好说的,也不太好说 :)

    回京的 T66 车票女友早已帮我买好,所以旅途还算顺利。托曹磊同学的福,咱拿的硬座车票也能混进软座候车室候车,所以上车时候没遇到什么困难,车厢里人也远不如来程时多。曹磊和我没有买到同一节车厢,一夜无事,坐着睡到天亮。只是到天津以后他旁边的人下车,我们才坐一起聊了聊天。

    下车后出北京站时,居然偶遇胡昊(就是小百合 BBS 上的 phoenixinter 啦),此人可是我仰慕已久的南大计算机的算法牛人呀!(baosheng 不要觉得不爽哈)他在港科读 PhD,目前在 MSRA 实习,做一些搜索引擎的研究课题。排队等安检和乘地铁时聊了几句,算是认识了一下久仰的名 ID 真人。

    10 月 6 号早上到的北京,赶到实验室坐了一会儿,下午还是没坚持住,在宿舍睡到近 5 点,把整个下午的班都给逃了。我的黄金周就在无比安逸的睡眠中结束了!