写了个新的玩意

前两天, Jenny 让我去听美国之音,但是美国之音死活都打不开,我也没办法翻Q,当时就想做一个代理下载的应用,因为我有几个国外的免费空间,应该可以连上。但是找了一圈,发现没人提出提取录音的方法,网站访问不了的话我自己也没办法去找,所以做了个从国内某网站下载VOA录音的东西,每天下载当天的录音到我服务器上,然后我从我网站上取资源。

本来想做成在线听的,但是我的HTML5播放器在重构代码,还非常不稳定,所以不便放出(到时侯有没有,要看播放器写成啥样)。现在只有提供下载地址。应用的地址在:http://voa41week.sinaapp.com/

免费空间流量貌似只有 10G 还是 20G 。。。

YUI Compressor

虽然 YUI Compressor 是首屈一指的 js/css 压缩软件,但是从来没有用过呃,以前在 win 下一直都用一个高手用 Java 封装调用 YUI Compressor 的GUI,现在到了 Ubuntu 下,那个 GUI 死活跑不起来,开始直接使用 YUI CCompressor 。

用法:

java -jar yuicompressor.jar --type js --charset utf-8 -v src.js > packed.js # 压缩js
java -jar yuicompressor.jar --type css --charset utf-8 -v src.css > packed.css # 压缩css

莫名其妙不高兴

今天莫名其妙地不高兴,可能是代码写多了的缘故。

本来编码是件很幸福的事的,但是今天写了一天,发现东西的质量下降了,到处是漏洞,前天设计的时候怎么就没有考虑到这些呢。今天基本都是在修补漏洞,但是学到了Ajax的很多东西,到时侯修改起其他小玩意来估计会顺手很多。比较悲哀的是,本来打算写的这个单用户微博系统,被我写得越来越像留言本了。管它了,顺其自然吧,我都不知道到底希望它成为什么样子。而且本来SQL还是比较容易的,谁知道自己一时兴起选了txtSQL作为数据库,现在写数据库操作语句的时候后悔得不行(而且都不知道多久没有更新了这玩意)。

今天看到比较开心的事情就是Typecho官方在5月8号宣布了更新的计划,证明Typecho并没有被抛弃。

最爱天然呆

这篇文章是去年7月初考试周写的,留在我的点点网博客上,文笔很烂(一向如此)。那是我永远无法忘记的一年,太多的伤痛和成长,我在这年5月开始接触网页设计和制作(这也要感谢 Jenny ),从此开始走上前端学习者的道路。

这几天迷上了宫崎骏,昨天看了一天的宫崎骏。从龙猫看到千与千寻,风之谷,天空之城,当然还有我的最爱——《侧耳倾听》。

也许是前一阵子看多了《越狱》,需要放松一下。觉得《侧耳倾听》是最好的一部了。很仔细地从头到尾看了三遍。

没有记住什么经典台词,倒是记住了快结尾的时候月岛雯和天泽圣司在山坡上看日出的那一段画面。惊讶于画师可以如此精致地描绘出日出的画面。

怎么写了呢。豆瓣有影评题为“是神让我在这样的季节看到《侧耳倾听》”,看到标题我笑了,夏天是个适合看这样的电影的季节。感谢冥冥中的谁让我在这样的季节看到《侧耳倾听》。
昨天阳光明媚,看完这部电影之后,向窗外看去,楼下小花园里前天的积水已经看不到痕迹,不认识的花开了,长凳上坐着一对一对的情侣。我又笑了。关于爱情,关于友情,关于理想,这部电影给了我们太多太多。

影评里写道,

所有的漫画都可以有真人版,但我无法忍受宫崎骏的片子变成真人版。无论怎样的俊男靓女,真人版就再也无法变成一个梦,男女主角的现实身份和纠葛,更会让我无法忍受。

另一篇里写道,

中途问呆有没有看过这片,他说,少女漫画喔。
有些生气。
我真被这片感动过。

那个说了我喜欢你之后嫁娶的承诺。有没有觉得一点点的熟悉?未来的承诺仅仅对那个年纪的人来说。是如此神圣不可侵犯。嘘。我们不说。不说。只是静静的看可好。

看着这些影评,一个人偷偷地想,蠢蠢地笑。我也被这片感动过。这里面有太多我们自己的影子。
据说这是近藤喜文导演一生拍的唯一一部片子。我相信。

时常想,是要有多美好的心灵,才能拍出如此令人感动的动画。

另外一个翻译“《心之谷》”也不错。但是我不喜欢她被翻译成“《梦幻街少女》”,虽然风格有一点接近,但她不是少女漫画。

还是最喜欢日文原意,《侧耳倾听》。

最爱天然呆。

近藤喜文、宫崎骏《侧耳倾听》

更改DNS

这几天上网慢得要死,一部分原因是带宽不够,一部分我猜测是运营商的DNS压力大(这还是往好了猜,其实劫持什么的更严重,污染就不用说了),所以想起来更换一下DNS。

因为不会用vi,所以凡是要用终端修改文本的我都用gedit来实现(果然win系统已经把我培养成GUI重度依赖者了呃)。照网上找的方法,使用命令sudo gedit /etc/resolv.conf,将nameserver后的ip地址改好保存就行了,然后需要重启网络,使用命令:sudo /etc/init.d/networking restart。

这样改完了之后感觉网络有明显改善,不过用着用着就又慢了,我再去看resolv.conf里面,nameserver又被改成了127.0.0.1。后来搜索了很久,发现有人说可能是因为用了resolvconf(也许我记错了,反正就是一类的自动配置工具)之类的工具,我一看还真是,用了工具之后,在/etc下的resolv.conf实际上是个链接,所以更改内容后会被自动恢复默认。

方法是删除这个链接,新建一个文件(这个倒不必,因为我之前有备份过这个文件,只要复制过来就行了)。

sudo rm /etc/resolv.conf
sudo cp /etc/resolv.conf-backup /etc/resolv.conf
sudo gedit /etc/resolv.conf #编辑之后记得保存~
sudo /etc/init.d/networking restart

我现在使用的是Google DNS、Norton DNS和OpenDNS。

#Google DNS
nameserver 8.8.8.8
nameserver 8.8.4.4
#Norton DNS
nameserver 198.153.192.1
nameserver 198.153.194.1
#Open DNS
nameserver 208.67.222.222
nameserver 208.67.220.220

一些小玩意

呃。。。我就不吐槽我写这篇文章的时候是多么的傻了,反正大家都是这么过来的。

写了点JavaScript的小玩意呃,因为越来越多人开始用jQuery(曾经我也是这大军中的一员),但是感觉太大了,而且附带了太多我不需要的功能,比如动画,要使用得当的话还要引入一堆插件,无端地增加页面加载时间。涉及到一些问题,从自己服务器引用文件的话太慢,甚至有时候文件不完整;从google lib引用的话时不时就被Q;从sina lib引用的话,我翻Q的时候速度又下来了。

要是自己写的话,灵活度就大了,需要什么功能再加上,文件肯定比jQuery小很多,而且功能都是我需要的,不会有冗余。写了一堆小东西了,不过比较成熟、拿得出手的也不多,先放两个。

$选择器:http://www.qblog.kilu.net/source/Query.js

Show&Hide:http://www.qblog.kilu.net/source/shownhide.js

天气预报服务2

前天晚上查看天气预报的Cron执行结果时,看到了这个:

SuccessSuccessSuccessSuccessSuccessSuccessSuccessSuccessSuccessFailSuccess

我感到莫名的压力。。。因为实际上这个服务只有11个用户。只有11个用户的服务都无法保证服务质量,这多荒唐。

这时我才发现,原作者的设计实际上是最优的选择。他的设计是,数据库里每一个用户的记录多一个字段today,作为今天是否已经发送的标记。应用是在18:00~18:30每隔几分钟执行一次,而不是在18:00执行一次。运行时,从数据库取出today字段值为0的用户发送短信,发送成功后将这个字段值改为1,直到不存在此字段为0的用户为止。应用的Cron任务有两个,出了18:00~18:30的发送短信以外,每晚00:30有还一次数据库写入,将所有用户的today字段值改为0,以供第二天发送短信时读取。

于是我想到了使用 xml 文件的方式,我可以在 SAE 建立一个 Storage ,将数据放入 xml 文件,保存在那里,使用跟数据库类似的原理进行读写。而且跟方便的是, php 可以用 DOMDocument 读取 xml (虽然我从来没有用过,我的 php 实践只到文件夹扫描为止),这跟 JavaScript 类似,而数据库?从上学期期末数据库设计作业之后我就再也没写过 SQL 语句了。然后我动手写了这么一堆玩意。

<?php
function getCityId($cName){
  $cxml = new DOMDocument('1.0');
  $cxml -> load('citydata.xml');
  $cities = $cxml -> getElementsByTagName('city');
  foreach($cities as $cs){
    $cns = $cs -> getElementsByTagName('name');
    $cis = $cs -> getElementsByTagName('id');
    $cn = $cns -> item(0) -> nodeValue;
    $ci = $cis -> item(0) -> nodeValue;
    if($cn == $cName){
      return $ci;
    }
  }
}

$xml = new DOMDocument();
$xml -> load('userfeed.xml');
$users = $xml -> getElementsByTagName('user');
foreach($users as $user){
  $nicks = $user -> getElementsByTagName('nick');
  $citys = $user -> getElementsByTagName('city');
  $mobiles = $user -> getElementsByTagName('mobile');
  $todays = $user -> getElementsByTagName('today');
  $nick = $nicks -> item(0) -> nodeValue;
  $city = $citys -> item(0) -> nodeValue;
  $mobile = $mobiles -> item(0) -> nodeValue;
  $today = $todays -> item(0) -> nodeValue;
  if($today == 0){
    $cityId = getCityId($city);
    $tomorrow = getWeatherData($cityId);
    $msg = $nick . ',您好!' . $city . '明天' . $tomorrow['Weah'] . ',温度' . $tomorrow['Temp'] . ',关注天气变化,注意身体哦~' . $serviceIntro;
    $SMSUrl = $sendBaseUrl . '?phone=' . $mobileNo . '&pwd=' . $mobilePwd . '&to=' . $mobile .'&u=1&msg=' . $msg;
    $SMSResult = httpRequest($SMSUrl);
    if($SMSResult == '200'){
      //Change sent state.
      $xml -> formatOutput = true;
      // $user -> getElementsByTagName('today') -> item(0) -> nodeValue = 1;// 看到这一句和下一句了吗?
      $today = 1;
      $xml -> save('userfeed.xml');
    }
  }
}

喵了个咪的,看到中文注释那里了吗?为了排除问题,我把两个方式都用上了。最后确实可以发送出去短信,但是 xml 里的 today 值压根就没有变化。。我还尝试了 saveXML('userfeed.xml'); ,我还尝试了把保存的语句写在 foreach 循环的外面。。实际上这好像是个不可能的任务了。。

所以我想,应该只能用数据库了。

顺便说一句,在本地进行测试的时候,获取天气数据有很多时候都是返回空字符,没有仔细研究原因。而在服务器上则不会出现这种情况。

天气预报服务

这是仿造一位知友写的天气预报订阅写的,没什么技术含量,为了节约数据库开销(SAE的数据库读写好贵T.T),把用户数据和城市数据存在单独的php文件里作为两个数组。。。orz。。其实本来想写到xml文件里,这样以后导出也比较方便,数据格式也比较规范,但是对于xml不熟悉,而且貌似权限没有办法进行恰当的设置(这样会造成直接访问xml文件就看到数据了),所以没有使用。

现在有个问题,就是整个流程是由一个文件驱动的,这个文件一旦运行,就循环地取得天气数据和用户数据,然后把短信发送出去了。就是说,直接访问这个文件跟crontab触发这个文件,本质上是没有区别的,短信都会发出去。这样就造成一个比较麻烦的问题,如果有爬虫访问了这个文件,所有用户都会收到短信,如果有人无意间访问了这个文件,短信也会发送出去,这样对用户来说是很不礼貌的。目前还没有想到解决办法。

上一部分代码吧,php学得好差,见笑了。

先是用户数据的范例。

<?php
$FeedUsers = array(
  '哈尔滨' => array(
    'user1' => array(
      'nick' => '用户1',
      'mobileNo' => '15123456789'
    ),
    'user3' => array(
      'nick' => 'user3',
      'mobileNo' => '13812345670'
    )
  ),
  '大连' => array(
    'user2' => array(
      'nick' => '用户2',
      'mobileNo' => '13800138000'
    )
  )
);
?>

城市数据的范例。

<?php
$cityDatabase = array(
  '哈尔滨' => '101050101',
  '大连' => '101070201'
);
?>

发送短信的部分。

<?php
error_reporting(0);
set_time_limit(0);
include_once('feed.php');// 这是用户数据
include_once('database.php');// 这是城市数据
$mobile = '13800138000';// 用来发送飞信的手机号
$mobilePwd = '123456';// 飞信密码
$to = $FeedUsers;// Import user data.
$cityList = $cityDatabase;// Import city data.
$serviceIntro = '(此服务由Joker强力驱动,详情访问http://mynook.info/)';// 很无耻地加了点附加信息~~
$sendBaseUrl = 'http://' . $_SERVER['HTTP_HOST'] . '/pafetion1.4.php';// 定义pafetion的路径

function getWeatherData($cId){// 这个比较简单,从中国天气网获取天气信息的函数
  if(empty($cId)){
    return false;
  }
  $wurl = 'http://m.weather.com.cn/data/' . $cId . '.html';
  $json = file_get_contents($wurl);
  $json = get_object_vars(json_decode($json));
  $json = get_object_vars($json['weatherinfo']);
  $Weah = $json['weather2'];
  $Temp = $json['temp2'];
  $tomo = array(
    'Weah' => $Weah,
    'Temp' => $Temp
  );
  return $tomo;
}

function _get_http_result($_url){// 发送http请求的函数,因为不想每一次都curl整个来一遍,所以分离出来了
  if(empty($_url)){
    return false;
  }
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, "$_url");
  curl_setopt($ch, CURLOPT_TIMEOUT, 8);
  curl_setopt($ch, CURLOPT_HEADER, 0);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
  $result = curl_exec($ch);
  $info = curl_getinfo($ch);
  curl_close($ch);
  if($result){
    return 'Success';
  }
}

foreach($to as $cityName => $group){//外层循环,对于每个组查询一次天气信息
  $cityId = $cityList[$cityName];// Get every city's id according to city's name.
  $groupUsers = $to[$cityName];// Get th users of current group.
  $tomorrow = getWeatherData($cityId);// Get current city's weather.
  foreach($group as $user){// Get users in current group.// 内层循环,针对每个用户生成不同短信内容
    $msg = $user['nick'] . ',您好!' . $cityName . '明天' . $tomorrow['Weah'] . ',温度' . $tomorrow['Temp'] . ',关注天气变化,注意身体哦~' . $serviceIntro;
    $url = $sendBaseUrl . '?phone=' . $mobile . '&pwd=' . $mobilePwd . '&to=' . $user['mobileNo'] .'&u=1&msg=' . $msg;// 生成短信请求的URL
    $sendResult = _get_http_result($url);
    if($sendResult == 'Success'){
      echo 'Success';
    }else {
      echo 'Fail';
    }
    sleep(1);
  }
}
?>

这个服务使用到了 pafetion 的飞信 API ,详情参看作者的博客:<http://3haku.net/tag/pafetion "pafetion">。城市数据由知友的原版天气预报订阅服务的源码提取:http://zhi.hu/DFWO

源码下载:http://www.qblog.kilu.net/source/nookweather.tar.gz

受到惊吓了

昨天下午在MDN上看东西看得头发涨,就去豆瓣看了下,正好有个友邻更新了图集,里面有一张是日本武士切腹的示意图。然后有个人在下面回帖贴了个视频地址。我手贱(我擦勒我手怎么那么贱啊)点进去缓冲了大半天看完之后我第一次有想吐的感觉。

阅读剩余部分 -