简单爬虫
想给闺女下载些MP3,百度一下倒是有些网站有,可惜下载麻烦,于是想到写个爬虫来自动下载。原来没写过,脑子里闪过几个思路后,决定先用phantomjs [1] 试试。
很快写了一个phantomjs的版本,测试了下,用是能用,就是有些慢。嗯,phantomjs能够渲染页面,但渲染页面恰恰是我这个爬虫不需要的,要是专注dom解析,应该能节省不少时间。于是google到 jsdom [2] ,改了改,发现好用多了。
源代码在 这里 。
我的思路:
- Nodejs, 开发快
- 不自己下载,丢给bash/wget,可以把生成好的脚本丢到Openwrt路由器上
基础工作:
- 使用Chrome inspector,分析网站结构,选用任何技术都无法避免的前提。
[1] | http://phantomjs.org |
[2] | https://github.com/tmpvar/jsdom |
使用angular-nvd3构造圆形分数
目标简介
一个漂亮的分数显示,从0-100,就像下面几个图那样:



所用到的技术
angularjs [1] 是非常著名的前端MVC框架,由google支持的开源项目。
d3 [2] 是基于SVG的数据可视化技术,是教底层的可扩展的库。
nvd3 [3] 是对d3的封装,实现了柱状图、折线图、饼图等常用的统计图形的定制库,增加了d3的易用性。
angular-nvd3 [4] 是nvd3在angular框架中的进一步封装,使得其在angular用户中更加易用。
要使用angular-nvd3,html页面中需要包含如下片段(假设各个模块已经下载到本地,使用cdn的读者自行替换):
<link href="bower_components/nvd3/build/nv.d3.min.css" rel="stylesheet">
<script src="bower_components/d3/d3.min.js"></script>
<script src="bower_components/nvd3/build/nv.d3.min.js"></script>
<script src="bower_components/angular/angular.min.js"></script>
<script src="bower_components/angular-nvd3/dist/angular-nvd3.min.js"></script>
实现思路
在nvd3中,由于饼图(pieChart)可以定制成中间掏空环形图(donut),我们可以以此为基础来构造整个图形:
- 外圈绿色和灰色构成的环形图;
- 中圈白色和黄色构成的环形图;
- 内圈直接使用div
外圈环形图需要两个值, score和100-score; 中圈一样; 内圈通过css设置border-radius为50%来构成一个整圆形,使用line-height来居中。
不过,怎么使这两个环与中间的圆都是同心圆呢?这需要如下两个条件:
- 容器为正方形,绝对定位
- 两个nvd3图的选项,四边的border都是0
参考源代码
<html>
<head>
<title>漂亮的分数</title>
<link href="bower_components/nvd3/build/nv.d3.min.css" rel="stylesheet">
<script src="bower_components/d3/d3.min.js"></script>
<script src="bower_components/nvd3/build/nv.d3.min.js"></script>
<script src="bower_components/angular/angular.min.js"></script>
<script src="bower_components/angular-nvd3/dist/angular-nvd3.min.js"></script>
<link href="index.css" rel="stylesheet" >
</head>
<body ng-app="demoApp">
<h1>漂亮的分数</h1>
<div style="width: 400px; height: 400px; position:absolute;" ng-controller="DemoCtrl" >
<nvd3 options="chart.options" data="scoreData" class="full" ></nvd3>
<div style="width: 75%; height: 75%; margin-left: 12.5%; margin-top: 12.5%; position:absolute;">
<nvd3 options="chart.options_inner" data="scoreData" class="full" ></nvd3>
</div>
<div style="width: 80%; height: 80%; margin-left: 10%; margin-top: 10%; position:absolute;">
<div style="position:absolute; width: 50%; height: 50%; left: 25%; top: 25%; background: black; border-radius: 50%; text-align: center; color: white; line-height: 45px;">
<span style="font-size:2.5em; line-height: 160px;" >{{score}}分</span>
</div>
</div>
</div>
<script type="text/javascript">
angular.module("demoApp", ['nvd3'])
.controller("DemoCtrl", function($scope){
$scope.xFunction = function(){
return function(d){
return d.key;
};
};
$scope.yFunction = function(){
return function(d){
return d.value;
};
};
function init(){
$scope.score = 95;
$scope.chart = {};
$scope.chart.options = {
chart:{
type: 'pieChart',
margin: { left: 0, top: 0, right: 0, bottom: 0},
donut: true,
donutRatio: 0.60,
x: $scope.xFunction(),
y: $scope.yFunction(),
showLabels: false,
showLegend: false,
color: ['rgb(130,201,63)', 'lightgray']
}
};
$scope.chart.options_inner = {
chart:{
type: 'pieChart',
margin: { left: 0, top: 0, right: 0, bottom: 0},
donut: true,
donutRatio: 0.5,
x: $scope.xFunction(),
y: $scope.yFunction(),
showLabels: false,
showLegend: false,
color: ['transparent', 'rgb(252,225,11)']
}
};
}
init();
$scope.$watch('score', function(nv, ov){
if( nv ){
$scope.scoreData = [
{key: 'score', value: nv },
{key: 'other', value: 100-nv }
];
$scope.chart.data = {
key: 'thekey',
data: $scope.scoreData
};
}
});
});
</script>
</body>
</html>
.full{
position:absolute;
width: 100%;
height: 100%;
}
Media Source Extensions inside Webkit
Introduction
Webkit [1] is a famous web layout/rendering engine, which is opensource, active development by Apple (Safari browser is based on it). In history, Google Chrome is also based on Webkit, but after Google created their own (webkit) branch Blink, Chrome is based on Blink now.
Html5 video [2] (and audio) element is a technology that provide a standard HTML API for video(audio) playing without a plugin(like flash). In Web video content providers, Youtube and Netflix support html5 video. In Web browsers, Chrome / Safari / Firefox support html5 video.
Media Source Extensions [3] (MSE) is a W3C specification (Work in progress) that allows Javascript to dynamically construct media streams for html5 video and audio element.
In this blog post I want to analysis and show the architecture of MSE inside Webkit Source code. First an introduction to html5 video implementation itself( without MSE), then the big picture of MSE, finally key interface classes. Please note it is better to have Webkit source code to follow this blog, so if you don’t have it now , please check Webkit [1] site to get one. For impatient audiences I myself suggest to use
git clone git://git.webkit.org/WebKit.git
to take advantages of git (comparing to svn).
As Webkit and MSE is changing, for this blog I am writing, I refer to webkit version r159335.
sd卡数据恢复记
每天手机关机,突然有一天(上周)早上起来开机,提示“SD卡错误,需要重新格式化!” 惊出一头汗。拒绝格式化,关机重启,还是那样。肯定是坏了。拿到Linux上查一下分区表,没了。冷静,备份整个卡先,dd了搞一个8G的映像。然后再看看怎么折腾恢复数据。
haskell学习笔记:从Python源代码生成类图(继承关系图)
我想搞一个通过reST直接写论文的东东,想法如下:
![digraph name{ node[shape=box] reST -> latex -> pdf }](_images/graphviz-0ff3b609d8e14a7a3e18489a96103668889b2ad4.png)
而现状是: 从latex到pdf有了 模板 ,而Sphinx或者直接docutils都可以生成pdf, 但还不能直接生成模板所需要的那个样子(主要是表格和插图引用有问题),所以想系统的学习下docutils的源代码好hack,找了一个旧版本的 Presentation ,把代码也从 sf.net 下面搞到本地了,然后搞明白其关键的数据结构是 文档树 也就是 nodes.py所定义的数据结构。
说了半天还没没有到正题,nodes.py有2205行,132个类定义,我想搞一个UML类图反映继承关系,正好用用这几天刚学的haskell来测试下。哦, 忘了提一个附加背景知识了, plantuml 利用 graphviz 可以通过文本 转换UML图,那么我的问题就分解为如何利用haskell来生成plantuml所需要的输入文本。
使用 reStructuredText 生成中文pdf
reStructuredText [1] 这个好东西,我要多多的用,还要多多的推广。这个博客的底层技术就是它!
思路
- 通过rst2xetex 生成tex文件
- 通过xelatex 生成pdf文件 (Debian下懒人办法: 安装texlive-full)
- rst2xetex的时候指定 –documentclass=ctexart
- Linux下需要若干字体文件 [2]
Makefile
%.pdf: %.tex
xelatex $<
xelatex $<
xelatex $<
%.tex: %.rst
rst2xetex --documentclass=ctexart $< $@
字体文件列表
有多余的,我没去管。
$ /usr/share/fonts/windows$ ls
04B_21__.TTF ariblk.ttf framdit.ttf FZZYJW.ttf l_10646.ttf mingliu.ttc raavi.ttf SIMHEI.TTF timesbi.ttf verdanai.ttf wst_germ.fon
app932.fon batang.ttc framd.ttf gautami.ttf latha.ttf modern.fon roman.fon SIMKAI.TTF timesi.ttf verdana.ttf wst_ital.fon
app936.fon comicbd.ttf FZFSJW.TTF georgiab.ttf lsansdi.ttf msgothic.ttc script.fon SIMSUM.TTC times.ttf verdanaz.ttf wst_span.fon
app949.fon comic.ttf FZHTJW.TTF georgiai.ttf lsansd.ttf msmincho.ttc segoeuib.ttf STXINGKA.TTF trebucbd.ttf vrinda.ttf wst_swed.fon
app950.fon courbd.ttf FZKTJW.TTF georgia.ttf lsansi.ttf mvboli.ttf segoeuii.ttf sylfaen.ttf trebucbi.ttf webdings.ttf ZWAdobeF.TTF
arialbd.ttf courbi.ttf FZLSJW.ttf georgiaz.ttf lsans.ttf palabi.ttf segoeui.ttf symbol.ttf trebucit.ttf wingding.ttf
arialbi.ttf couri.ttf FZSSJW.TTF gulim.ttc lucon.ttf palab.ttf segoeuiz.ttf tahomabd.ttf trebuc.ttf wst_czec.fon
ariali.ttf cour.ttf FZXBSJW.ttf impact.ttf mangal.ttf palai.ttf shruti.ttf tahoma.ttf tunga.ttf wst_engl.fon
arial.ttf estre.ttf FZXKJW.ttf kartika.ttf micross.ttf pala.ttf SIMFANG.TTF timesbd.ttf verdanab.ttf wst_fren.fon
Haskell学习笔记: Unboxed Type
上文 提出了一个问题,怎么能写一个length函数能和内置的length一样快?最简单的办法莫过于 查看GHC源代码 了。
库里面的源代码确是这个样子:
-- | /O(n)/. 'length' returns the length of a finite list as an 'Int'.
-- It is an instance of the more general 'Data.List.genericLength',
-- the result type of which may be any kind of number.
length :: [a] -> Int
length l = len l 0#
where
len :: [a] -> Int# -> Int
len [] a# = I# a#
len (_:xs) a# = len xs (a# +# 1#)
搞不明白 Int# 是什么玩意,到处查,最后发现上面那个Slide里面有提示(自己太粗心了):
All those # marks are for “unboxed types”, which are faster but not asymptotically
然后再Google, 就可以找到 unboxed type的定义 。于是自己可以写一个和库里面源代码一模一样的 length:
{-# MagicHash #-}
import Data.List
import GHC.Prim
import GHC.Exts
length1 :: [a] -> Int
length1 l = len l 0#
where
len :: [a] -> Int# -> Int
len [] a# = I# a#
len (_:xs) a# = len xs (a# +# 1#)
用GHCi测试了下,速度比上回的好,但还是不如内置的length,这是为什么?我猜大约是编译器优化吧。
微信公众平台应用设想(高级智能客服)
前面 提到的是“简单的”“智能”客服, 说它简单,是因为两点:它只能够做对话,用户需要通过手动发送消息来操作;说它智能,如果后台足够强大,这种对话也可以干出很多花样的:例如实时天气查询,交通查询,多人文字游戏等等。本文实际上叫“设想”不太合适,因为这些东西是成功案例中已经存在的,我只不过重新组织了一下;但为了系列文章标题的一致性,就不改了,看官们将就一下吧。
微信公众平台的应用设想(智能客服)
微信 是最近很流行的短信替代服务, 微信公众平台 是微信的第三方开发接口,我之前并不关注,一个朋友想用这个公共平台来替代之前的手机App(物联网数据采集),我应邀对其进行技术评估。本博客准备写一个系列,每篇文章一个应用,并给出3个问题的答案: 做什么?怎么做?技术难点在什么地方?本文给出一个最简单直接的应用:智能客服。