202010

package com.john.j2se.util;
/**
* MD5加密算法
*/
import java.security.MessageDigest;

public class MD5Util {
public final static String MD5(String s) {
char hexDigits[] = { ’0′, ’1′, ’2′, ’3′, ’4′,
’5′, ’6′, ’7′, ’8′, ’9′,
‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’};
try {
byte[] btInput = s.getBytes();
MessageDigest mdInst = MessageDigest.getInstance(“MD5″);
mdInst.update(btInput);
byte[] md = mdInst.digest();
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

MD5加密算法是一种单向加密算法。

import java.io.UnsupportedEncodingException;

public class Base64 {
private static char[] base64EncodeChars = new char[] {
‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’, ‘H’,
‘I’, ‘J’, ‘K’, ‘L’, ‘M’, ‘N’, ‘O’, ‘P’,
‘Q’, ‘R’, ‘S’, ‘T’, ‘U’, ‘V’, ‘W’, ‘X’,
‘Y’, ‘Z’, ‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’,
‘g’, ‘h’, ‘i’, ‘j’, ‘k’, ‘l’, ‘m’, ‘n’,
‘o’, ‘p’, ‘q’, ‘r’, ‘s’, ‘t’, ‘u’, ‘v’,
‘w’, ‘x’, ‘y’, ‘z’, ’0′, ’1′, ’2′, ’3′,
’4′, ’5′, ’6′, ’7′, ’8′, ’9′, ‘+’, ‘/’ };

private static byte[] base64DecodeChars = new byte[] {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 };
//编码

public static String encode(byte[] data) {
StringBuffer sb = new StringBuffer();
int len = data.length;
int i = 0;
int b1, b2, b3;
while (i < len) {
b1 = data[i++] & 0xff;
if (i == len)
{
sb.append(base64EncodeChars[b1 >>> 2]);
sb.append(base64EncodeChars[(b1 & 0x3) << 4]);
sb.append(“==”);
break;
}
b2 = data[i++] & 0xff;
if (i == len)
{
sb.append(base64EncodeChars[b1 >>> 2]);
sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]);
sb.append(base64EncodeChars[(b2 & 0x0f) << 2]);
sb.append(“=”);
break;
}
b3 = data[i++] & 0xff;
sb.append(base64EncodeChars[b1 >>> 2]);
sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]);
sb.append(base64EncodeChars[((b2 & 0x0f) << 2) | ((b3 & 0xc0) >>> 6)]);
sb.append(base64EncodeChars[b3 & 0x3f]);
}
return sb.toString();
}

//解码
public static byte[] decode(String str) throws UnsupportedEncodingException {
StringBuffer sb = new StringBuffer();
byte[] data = str.getBytes(“US-ASCII”);
int len = data.length;
int i = 0;
int b1, b2, b3, b4;
while (i < len) {
/* b1 */
do {
b1 = base64DecodeChars[data[i++]];
} while (i < len && b1 == -1);
if (b1 == -1) break;
/* b2 */
do {
b2 = base64DecodeChars
[data[i++]];                 } while (i < len && b2 == -1);
if (b2 == -1) break;
sb.append((char)((b1 << 2) | ((b2 & 0×30) >>> 4)));
/* b3 */
do {
b3 = data[i++];
if (b3 == 61) return sb.toString().getBytes(“iso8859-1″);
b3 = base64DecodeChars[b3];
} while (i < len && b3 == -1);
if (b3 == -1) break;
sb.append((char)(((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2)));
/* b4 */
do {
b4 = data[i++];
if (b4 == 61) return sb.toString().getBytes(“iso8859-1″);
b4 = base64DecodeChars[b4];
} while (i < len && b4 == -1);
if (b4 == -1) break;
sb.append((char)(((b3 & 0×03) << 6) | b4));
}
return sb.toString().getBytes(“iso8859-1″);
}
}

Base64 是一种双向加密算法

Latex:图片及子图排版

Posted by 冰河 at 16:33 No Responses » 34,504 Views
102010

在谈插入eps之前,首先要了解常用的latex图形宏包——graphics和psfrag。

graphics 图形宏包套件主要有两个宏包:早期标准的 graphics 宏包和在其基础上扩展增强的 graphicx 宏包。它们可用以引入外部图形,旋转或缩放文字、图表等等;对不同的DVI 驱动,它们提供了对 EPS、PS、PDF、TIFF 和 JPEG 等图形格式的支持。这两个宏包的功能很相近,提供的命令名称相同,只是参数格式有所不同。目前一般都使用功能较完善的 graphicx。实际上,在调用 graphicx 时,其基础文件 graphics 也自动被加载了。

graphicx 宏包具有多种驱动程序选项,常用的有 dvips、dvipdf 和 pdftex;还有多个功能控制选项,如 draft,为草稿模式,只显示图形的边框及其名称。

graphicx 提供了一组控制命令,其中最常用的是插图命令:

includegraphics[选项]{图形名},

下表为常用选项:

选项 说明
angle 图形旋转角度,正值表示逆时针旋转
height 图形高度
width 图形宽度
scale 图形缩放因数
psfrag,在 CJK 和 CCT 等中文环境中,可用该宏包将 EPS 图形中的外文字符替换为相应的中文字符。那些不支持中文输入的绘图软件如 Gauss 等,就可用它来再处理。
因此,在插入eps图片的时候,需要首先在cls文件中插入相应的命令:RequirePackage{graphicx};如果需要在图片中插入中文注释,可以插入命令:RequirePackage{graphicx,psfrag}。
插入eps分为两种情况,一种是只有一个图,一个标题;另一种是有多个图,每个图有个子标题,然后有个总的大标题。
对于第一种情况,举例如下:

egin{figure}[!htbp]

enewcommand{captionlabeldelim}{ }
centering
includegraphics[width=6cm,height=4cm,engle=90]{eps图的名字.eps}
caption{图片标题}
end{figure}

enewcommand{captionlabeldelim}{ }命令用来定义标题的标号后面是空格,而不是“:”。
对于第二种情况,除了需要graphicx宏包,还需要加入对子标题支持的宏包subfigure。可以在cls文件中插入命令usepackage{subfigure}。参考下面的例子:

begin{figure}[!htbp]

enewcommand{captionlabeldelim}{ }
centering
subfigure[子图1]{
label{fig:subfig:a} %% label for first subfigure
includegraphics[width=3.2cm,height=3.5cm]{bian.eps}}
hspace{0.5in}
subfigure[子图2]{
label{fig:subfig:b} %% label for second subfigure
includegraphics[width=3.2cm,height=3.5cm]{jing.eps}}
hspace{0.5in}
subfigure[子图3]{
label{fig:subfig:c} %% label for second subfigure
includegraphics[width=3.2cm,height=3.5cm]{jia.eps}}
caption{大标题}
label{fig:subfig} %% label for entire figure
end{figure}

LaTeX中一般只直接支持插入eps(Encapsulated PostScript)格式的图形文件, 因此在图片插入latex文档之前应先设法得到图片的eps格式的文件.

在LaTeX文档中插入图片都是通过使用一些latex图形处理宏命令来实现的, 有很多宏命令都支持在在LaTeX文档中插入eps格式的图形文件, 主要有:
1. 用includegraphics宏命令(graphicx包):

首先需在latex文档的文件说明部分加上:

usepackage{graphicx}

然后在需要插入图片的地方引用:

includegraphics[height=高度]{图片文件名}

或者: includegraphics[width=宽度]{图片文件名}

其中的”高度”和”宽度”是指希望图片打印的高度和宽度, 必须给出单位, 可用厘米(cm)或英寸(in). 高度和宽度也可用上述格式同时给出, 这样可以改变原图的长宽比例. 上述命令中的图片文件名是指欲插入的图片文件 的文件名, 图片必需是eps格式的.

用graphicx包的includegraphics宏命令插入图片时还可以使图片旋转, 方法是:
includegraphics[height=高度][angle=旋转角度]{图片文件名}
2. 用psfig宏命令:
首先需在latex文档的文件说明部分加上:

usepackage{psfig}
然后在需要插入图片的地方引用:
psfig{figure=图片文件名,height=高度}
或者: psfig{figure=图片文件名,width=宽度}
其中的”高度”和”宽度”是指希望图片打印的高度和宽度, 必须给出单位, 可用厘米(cm)或英寸(in). 高度和宽度也可用上述格式同时给出, 这样可以改变原图的长宽比例. 上述命令中的图片文件名是指欲插入的图片文件 的文件名, 图片必需是eps格式的.
3. 用epsfig宏命令:
epsfig宏命令的使用方法和psfig完全相同, 具体方法是: 首先需在latex文档的文件说明部分加上:

usepackage{epsfig}
然后在需要插入图片的地方引用:
epsfig{figure=图片文件名,height=高度}
或者: epsfig{figure=图片文件名,width=宽度}
其中的”高度”和”宽度”是指希望图片打印的高度和宽度, 必须给出单位, 可用厘米(cm)或英寸(in). 高度和宽度也可用上述格式同时给出, 这样可以改变原图的长宽比例. 上述命令中的图片文件名是指欲插入的图片文件 的文件名, 图片必需是eps格式的.
4. 用epsf宏命令:
用epsf宏命令的使用方法是: 首先需在latex文档的文件说明部分加上:

usepackage{epsf}
然后在需要插入图片的地方引用:
epsfxsize=宽度epsffile{图片文件名}
或者: epsfysize=高度epsffile{图片文件名}
其中的”高度”和”宽度”是指希望图片打印的高度和宽度, 必须给出单位, 可用厘米(cm)或英寸(in). 高度和宽度也可用上述格式同时给出, 这样可以改变原图的长宽比例. 上述命令中的图片文件名是指欲插入的图片文件 的文件名, 图片必需是eps格式的.

LaTex:图片排版

Posted by 冰河 at 15:54 2 Responses » 23,496 Views
102010

一般支持三种格式的图片排版

%% if you use PostScript figures in your article

%% use the graphics package for simple commands

%% usepackage{graphics}

%% or use the graphicx package for more complicated commands

%% usepackage{graphicx}

%% or use the epsfig package if you prefer to use the old commands

%% usepackage{epsfig}

eps格式图片的排版举例:

首先需要在导言部分引入相关包:usepackage{epsfig}

排版效果图:

排版代码:

%Latex排版之图片排版

begin{figure*}[!htbp]

centering

psfig{file=pic/Ex4-20ga.eps,width=1.5in,origin=br,angle=-90}

psfig{file=pic/Ex4-20gb.eps,width=1.5in,origin=br,angle=-90}

%psfig{file=pic/Ex4-20gc.eps,width=1.5in,origin=br,angle=-90}

caption {Experiment result for uneven data distribution.}

label{fig:ex4}

end{figure*}

需要注意的:在论文中排版eps图片后,编译tex文件的顺序为:先运行编译TeXify ,再运行dvi2pdf 得到pdf文件。

LaTex:算法排版

Posted by 冰河 at 21:19 5 Responses » 66,088 Views
092010

排版可能需要的包:

usepackage{algorithm} //format of the algorithm

usepackage{algorithmic} //format of the algorithm

usepackage{multirow} //multirow for format of table

usepackage{amsmath}

usepackage{xcolor}

DeclareMathOperator*{argmin}{argmin} //argmin或argmax公式的排版

enewcommand{algorithmicrequire}{ extbf{Input:}} //Use Input in the format of Algorithm

enewcommand{algorithmicensure}{ extbf{Output:}} //UseOutput in the format of Algorithm

排版图片可能需要的包:

usepackage{graphics}

usepackage{graphicx}

usepackage{epsfig}

算法的排版举例:

\begin{algorithm}[htb] %算法的开始

caption{ Framework of ensemble learning for our system.} %算法的标题

label{alg:Framwork} %给算法一个标签,这样方便在文中对算法的引用

\begin{algorithmic}[1] %这个1 表示每一行都显示数字

REQUIRE ~~\ %算法的输入参数:Input

The set of positive samples for current batch, $P_n$;\

The set of unlabelled samples for current batch, $U_n$;\

Ensemble of classifiers on former batches, $E_{n-1}$;

ENSURE ~~\ %算法的输出:Output

Ensemble of classifiers on the current batch, $E_n$;

STATE Extracting the set of reliable negative and/or positive samples $T_n$ from $U_n$ with help of $P_n$; label{code:fram:extract} %算法的一个陈述,对应算法的一个步骤或公式之类的; label{ code:fram:extract }对此行的标记,方便在文中引用算法的某个步骤

STATE Training ensemble of classifiers $E$ on $T_n cup P_n$, with help of data in former batches; label{code:fram:trainbase}

STATE $E_n=E_{n-1}cup E$; label{code:fram:add}

STATE Classifying samples in $U_n-T_n$ by $E_n$; label{code:fram:classify}

STATE Deleting some weak classifiers in $E_n$ so as to keep the capacity of $E_n$; label{code:fram:select}

RETURN $E_n$; %算法的返回值

end{algorithmic}

end{algorithm}

排版效果图:

在文中对算法和算法的某个步骤的引用:Therefore, in step
ef{code:fram:extract} of algorithm
ef{alg:Framwork}, we extract $T_n$, a set of reliable negative samples

1、 For和While循环语句的排版举例

(1) 排版效果图

(2)排版代码

\begin{algorithm}[h]

caption{An example for format For & While Loop in Algorithm}

\begin{algorithmic}[1]

FOR{each $iin [1,9]$}

STATE initialize a tree $T_{i}$ with only a leaf (the root);\

STATE $T=Tigcup T_{i};$\

ENDFOR

FORALL {$c$ such that $cin RecentMBatch(E_{n-1})$} label{code:TrainBase:getc}

STATE $T=T cup PosSample(c)$; label{code:TrainBase:pos}

ENDFOR;

FOR{$i=1$; $i<n$; $i++$ }

STATE $//$ Your source here;

ENDFOR

FOR{$i=1$ to $n$}

STATE $//$ Your source here;

ENDFOR

STATE $//$ Reusing recent base classifiers. label{code:recentStart}

WHILE {$(|E_n| leq L_1 )and( D
eq phi)$}

STATE Selecting the most recent classifier $c_i$ from $D$;

STATE $D=D-c_i$;

STATE $E_n=E_n+c_i$;

ENDWHILE label{code:recentEnd}

end{algorithmic}

end{algorithm}

问题:如果有两个等式排成一列,如下:
a+b=1
c+d=2   (1)
其右端的编号(1)如何显示在两个等式的中间?

如果用eqnarray环境,只能将编号显示在上面或下面等式的后面,如:
begin{eqnarray}

a+b &=& 1
onumber


c+d &=& 2

end{eqnarray}
则显示为:
a+b=1
c+d=2  (1)
编号显示在第二个等式的后面。

可以使用下面的语句,使得编号显示在两个等式的中间:
begin{equation}

begin{array}{l}

a+b=1 \

c+d=2

end{array}

end{equation}
有时上下列等式之间显得拥挤,可在每个等式前加上displaystyle来避免这种情况,如:
begin{equation}
begin{array}{l}
displaystyle a+b=1 \
displaystyle c+d=2
end{array}
end{equation}

此外,利用split环境也可以将编号写在中间,如:
begin{equation}

begin{split}

a+b=1\

c+d=2

end{split}

end{equation}

这个方法是网友xhpan于2009年8月1日提供的,在此表示感谢!

在交叉引用中,博主习惯上用符号”eq:n”,来标示文章中需要引用的第n个公式,如:
begin{equation}
begin{array}{l}
displaystyle a+b=1 \
displaystyle c+d=2
end{array}
label{eq:1}
end{equation}

按说Tex文件中出现
ef{eq:1}
的地方,在编译后就会自动出现公式的编号,然而实际上什么都没有显示。博主尝试用其它符号来标示此公式,如label{eq1},一切又恢复正常,看来array环境中用来标示引用的符号不可任意选择!使用split环境不存在这个问题。

LaTeX:公式及编号

Posted by 冰河 at 17:02 1 Response » 103,392 Views
092010

1.自动编号的单行公式环境是
\begin{equation}

end{equation}

不参与自动编号的单行公式环境:
[

]

人工编号的单行公式可以使用Tex原有的行间公式标记
$$公式 eqno 编号 $$ 将编号放在右边
$$公式 leqno 编号 $$ 将编号放在左边

引用时候可以直接用$编号$即可。

例如,$$a^2+b^2=c^2 eqno (**)$$
由公式($**$)即可得到结论。

一般情况下,行间公式 $$…$$也可以用[…]表示
但对于这种人工编号的公式,不能用[..]代替$$…$$.

2.单个公式很长,需要换行,但仅允许生成一个编号时,可以用split命令

\begin{equation}
\begin{split}
a &= b \
c &= d
end{split}
end{equation}

注意:每行只允许出现一个“&”,使用split命令后,编号上下居中显示。

3.多行公式:

\begin{eqnarray}
左 & 中 & 右\
左 & 中 & 右\

end{eqnarray}
该环境对多行公式每行都加自动编号,如果相对某行不加编号,可在换行之前添加命令
onumber

其中两个&号之间的是公式间对齐的位置,用\隔开各行公式。将eqnarray改为eqnarray*输出的公式是没有编号。

如果要改变公式的自动编号,可以重设计数器初始值:
setcounter{equation}{数}
下一个编号自动加1。

4.方程组的排版:
多个公式,每个公式自动编号。

1) gather环境
是下面align环境的一种特殊情形。
\begin{gather}
a &= b \
c &= d \

end{gather}
>>1.如果其中某几行使用同一个编号,则需要内嵌一个split环境。
>>2.命令
otag可使当前行不编号。
2) align环境
可使几组公式并排在一起,即在同一行显示多个公式,方法是跟以前一样,使用”&”对齐。
可替代gather环境。
3) 以上几种方程组环境,无论每个公式多小,都会占满一行。使用相应的gathered,aligned环境,则只占据公式的实际宽度,整体作为一个特大的符号与其他符号一同处理。
这个结构还可以添加位置参数,以决定与其他符号的竖直对齐方式(b,t)。而且这种环境不再具有自动编号功能。

例如:
\begin{equation}
left.
\begin{aligned}[b]
a &= b+c \
d &= b+c
end{aligned}

ight}
Longrightarrow
qquad a=d
end{equation}

272010

WP Super Cache 是 WordPress 官方开发人员 Donncha 开发,是当前最高效也是最灵活的 WordPress 静态缓存插件。它把整个网页直接生成 HTML 文件,这样 Apache 就不用解析 PHP 脚本,通过使用这个插件,能使得你的 WordPress 博客将显著的提速。

WP Super Cache 基本介绍

WP Super Cache 是基于 Ricardo Galli Granada 的 WP-Cache 2。WP-Cache 2 可以缓存你的 WordPress 博客使得不用再次访问数据库,但是它产生的是 PHP 文件而不是 HTML 文件,所以还需要 PHP 引擎去解析它们。而 WP Super Cache 则直接产生 HTML 文件,所以服务器不用解析甚至一行 PHP 代码,所以缓存之后的速度就和访问你服务器上的一张图片一样快。

WP Super Cache 是如何工作的

一半常规的缓存办法是手工把动态页面保存为 HTML 代码,WP Super Cache 也是通过同样的方式的,但是通过自动的方式完成这个过程。

当你一个访问者来的你的站点,他没有登入或者也没有留言,这样他得到是一个在 WordPress cache 文件夹下的 supercache 子文件夹下的纯静态文件,其实你都可以自己到上面的 supercache 目录下去查看同样的永久链接的 HTML 文件的备份。判断一个页面是否已经被缓存了,查看该页面的源代码,看看最后一行是否有 <!– super cache –> 或者 <!– super cache gz –>。

如果访问者已经登陆或者留了言,就会返回 WP Cache 函数生成的页面,并且最后一行会有 <!– Cached page served by WP-Cache — >

WP Super Cache 基本使用

上传 WP Super Cache 到插件目录,并在 Plugin 目录下激活之后,就可以到 Setting > WP Super Cache 进行详细配置。

WP Super Cache Status

首先是三个选项:

  • ON (WP Cache and Super Cache enabled)
  • HALF ON (Super Cache Disabled, only legacy WP-Cache caching.)
  • OFF (WP Cache and Super Cache disabled)

默认情况下,WP Super Cache 是没有开启的,所以在这里选择下,需按则第一个,就是 Super Cache,缓存为静态文件,如果第二种情况呢,则和 WP-Cache 一致。

Proudly tell the world your server is Digg proof! (places a message in your blog’s footer)
这个是说在你的 footer 显示一条信息告诉读者该博客已经缓存了,一般不要这样做。

Clear all cache files when a post or page is published. (This may significantly slow down saving of posts.)
这个是说发布新日志的时候清理所有缓存,这个肯定不能这么干了。

Super Cache Compression

启动这个则会成生 gzip 压缩,节省你的带宽。

Mod Rewrite Rules

WP Super Cache 是通过 Mod Rewrite 实现访问静态文件的,所以这里在是显示添加的 Mod Rewrite 规则。

Expiry Time and Garbage Collection

过期时间和垃圾收集,这里主要设置缓存文件过期时间,和多久删除一次过期的缓存文件。个人建议:一般缓存时间设置为1天(86400)左右,缓存删除时间为1个小时一次。

Accepted filenames, rejected URIs

这里设置一些链接不需要缓存,并且可以设置特例。

Rejected User Agents

这里设置某些 User Agents 来访问的时候不会缓存。比如 Google 和百度爬虫等。

Cache Contents

这里显示你博客缓存文件和过期文件的数量,你可以手工删除缓存文件和过期文件,因为 WP Super Cache 有垃圾回收机制,所以这里不帮不用手工删除,如果当你测试某个插件,看不到效果的时候,如果确定是缓存的原因,你可以到这里手工删除测试下。

Lock Down

一般情况下,某篇日志如果有了新留言,就会更新缓存文件,不过这篇日志是否已经到了缓存时间,但是在某种情况,你预料到你的博客可能会有很大流量和留言,候重复更新缓存文件可能并不是很好的选择,速度反而更慢,这个时候你就可以锁定缓存文件,新留言不再更新缓存日志。

插件作者也给出了一段代码,如果你的博客锁定了之后,可以通过判断一个变量 WPLOCKDOWN 是否存在告来诉读者,你博客已经锁定,待会才会更新,当然了,一般博客不建议使用。

Directly Cached Files

直接缓存文件,根据永久链接直接缓存,比如你的关于页面是不太更新,你就可以直接缓存它到你的 about 目录下(假如你的关于页面的 slug 是 about),这个直接缓存不会过期。适合一些经常性不更新的静态页面。

Configuration messed up?

因为上面那么多配置,你可能搞糊涂了,那么这里可以让你一键恢复到默认。

Cache Plugins

缓存插件还支持附加插件,比如作者自己就提供一个插件:No Adverts for Friends,不对朋友显示广告。

google.com 首页代码分析

Posted by 冰河 at 18:56 No Responses » 5,184 Views
262010

机缘巧合,对 google.com 的首页代码产生了浓厚兴趣。一点“分析”,杂记如下:

不同浏览器推送不同代码
google_src_diff.png

上图是在不同浏览器下,保存的 google 首页代码。

注意:文件大小是经过 IntelliJ IDEA 格式化处理后的大小,请查看:lab/2009/google.

其中 Chrome 和 Safari 的代码是一样的,Opera 仅仅一个 js 函数的写法与 Chrome 不同。差异最大的是 Firefox 和 IE。

我的想法:大部分应用场景下,针对不同浏览器实现不同版本,会增加开发和维护成本。google 首页采取这种差异化方案,很可能是考虑到要最大限度降低网页流量。毕竟对于日访问量上千万的网站来说,减少一个字符都能节约可观的流量。精简节约,在 google 首页上体现得淋漓尽致,下面会继续提及。

doctype 的写法

只有 Firefox 用了《!doctype html》来激活标准模式。其它浏览器下,都是简单粗暴的 Quirks 模式。

我的想法:Firefox 下也可以直接用 Quirks 模式,视觉差异上极小。不清楚 google 为何仅针对 Firefox 开启了标准模式。

值得注意的是,在 google 搜索结果页,所有浏览器下都使用了《!doctype html》。 毕竟结果页复杂些,依旧用 Quirks 模式的话,会增加开发成本。首页因为简单,Quirks 和 Standards 相比,没什么显著差别,因此能省就省。

关于 doctype, 强烈推荐阅读:Activating Browser Modes with Doctype

对浏览器来说,doctype 实际上仅影响浏览模式,因此能从简就从简。W3C 校验,我觉得没必要,很少关注。

精简,还是精简

以 Firefox 下 google 首页的源码为例:

html, body 缺胳膊少腿

html 元素的很多属性没有用双引号括起来

class, id 等命名很短

script 和 style 元素没 type 等属性

没有 keywords 和 description 等 meta 值,我是搜索老大,哈哈

balabala 等等

想起一句话:遵守规范的一个重要标准,就是知道何时打破它,并大胆地打破。从这层意义上讲,google 首页是非常遵守规范的。

没有完美

细心点,还可以发现:

引号去得不彻底,比如《img alt=“Google” 。..

还有padding-left: 0px, px 可以去掉

js 上,也有进一步精简的余地。比如下面两行完全一样的代码,很?:

if(google.y) google.y.first = [];

if(google.y) google.y.first = [];

还有一段代码,div 提前到 script 前面能省去判断:

《script》

function wgjp() {

var xjs = document.createElement(‘script’);

xjs.src = ‘/extern_chrome/1mZ_-PL2Zjc.js’;

(document.getElementById(‘xjsd’) || document.body).appendChild(xjs)

};

《/script》

《div id=xjsd》《/div》

也许吹毛求疵了,笑过。

预加载

看代码:

《body onload=“sf();if(document.images){new Image().src=‘/images/nav_logo4.png’}” 。..

这就是 YSlow 34条性能法则中的 Preload Components. google 首页提前加载了搜索结果页的 css sprite. 另外赞一下这个 sprite 图的组织,很 cute.

延迟加载

看代码:

window.setTimeout(function() {

var a = document.createElement(“script”);

a.src = “/extern_js/f/。../XRt_2Y4Z5sM.js”;

(document.getElementById(“xjsd”) || document.body).appendChild(a)

}, 0);

上面这个 js 挺大的,包含了 google 的 js 库和输入框的提示补全组件。这个 setTimeout 起到了将下载进程延迟到 window.onload 后。很小的代码调整,却提升了不少用户体验,实在划算。

另提一下,这个 js 在不同浏览器下也有不同版本,大小差异比较明显。为了尽可能减少流量,google 还真费心。

奇淫技巧

代码虽少,淫荡之处却摇曳生姿:

1. 遍历数组

for (var i = 0,c; c = [“ad”,“p”,“pa”,“zd”,“ac”,“pc”,“pah”,“ph”,“zc”][i++];) {

// doing something, such as console.log(c)

}

2. 短路语句

function _gjp() {

!(window._gjwl.hash && window._gjuc()) && setTimeout(_gjp, 500)

}

短路表达式很常用,但用短路单独做语句,还真精简。

语义化

从语义上讲,google 的 html 代码是比较糟糕的。但考虑到各种浏览终端,或许 google 目前的写法非常优化。没有接触过跨n 》 20的浏览器开发经验,对此不多说。

小结

从首页代码中,能看出 google 推崇的是:简单 + 实用 + 性能。我越来越认同这种观点。

计算Google PageRank的php代码

Posted by 冰河 at 21:52 No Responses » 13,386 Views
十二 182009

可以方便调用。这段代码在windows和linux下都能用。

<?php
class PageRank
{
//settings – host and user agent
var $googlehost='www.google.com';
var $googleua='Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.6) Gecko/20060728 Firefox/1.5';
//convert a string to a 32-bit integer
function StrToNum($Str, $Check, $Magic) {
    $Int32Unit = 4294967296;  // 2^32
    $length = strlen($Str);
    for ($i = 0; $i < $length; $i++) {
        $Check *= $Magic;    
        //If the float is beyond the boundaries of integer (usually +/- 2.15e+9 = 2^31),
        //  the result of converting to integer is undefined
        //  refer to http://www.php.net/manual/en/language.types.integer.php
        if ($Check >= $Int32Unit) {
            $Check = ($Check – $Int32Unit * (int) ($Check / $Int32Unit));
            //if the check less than -2^31
            $Check = ($Check < -2147483648) ? ($Check + $Int32Unit) : $Check;
        }
        $Check += ord($Str{$i});
    }
    return $Check;
}
//genearate a hash for a url
function HashURL($String) {
    $Check1 = $this->StrToNum($String, 0×1505, 0×21);
    $Check2 = $this->StrToNum($String, 0, 0x1003F);
    $Check1 >>= 2;    
    $Check1 = (($Check1 >> 4) & 0x3FFFFC0 ) | ($Check1 & 0x3F);
    $Check1 = (($Check1 >> 4) & 0x3FFC00 ) | ($Check1 & 0x3FF);
    $Check1 = (($Check1 >> 4) & 0x3C000 ) | ($Check1 & 0x3FFF);   
    $T1 = (((($Check1 & 0x3C0) << 4) | ($Check1 & 0x3C)) <<2 ) | ($Check2 & 0xF0F );
    $T2 = (((($Check1 & 0xFFFFC000) << 4) | ($Check1 & 0x3C00)) << 0xA) | ($Check2 & 0xF0F0000 );
    return ($T1 | $T2);
}
//genearate a checksum for the hash string
function CheckHash($Hashnum) {
    $CheckByte = 0;
    $Flag = 0;
    $HashStr = sprintf('%u', $Hashnum) ;
    $length = strlen($HashStr);
    for ($i = $length – 1;  $i >= 0;  $i –) {
        $Re = $HashStr{$i};
        if (1 === ($Flag % 2)) {             
            $Re += $Re;    
            $Re = (int)($Re / 10) + ($Re % 10);
        }
        $CheckByte += $Re;
        $Flag ++;   
    }
    $CheckByte %= 10;
    if (0 !== $CheckByte) {
        $CheckByte = 10 – $CheckByte;
        if (1 === ($Flag % 2) ) {
            if (1 === ($CheckByte % 2)) {
                $CheckByte += 9;
            }
            $CheckByte >>= 1;
        }
    }
    return '7'.$CheckByte.$HashStr;
}
//return the pagerank checksum hash
function getch($url) { return $this->CheckHash($this->HashURL($url)); }
//return the pagerank figure
function getrank($url)
{
    $urlinfo=parse_url($url);
    $start=$urlinfo["scheme"]<>""?strlen($urlinfo["scheme"]."://"):0;
    $url=substr($url,$start);
    $pr = -1;    // default return
    $ch = $this->getch($url);
    $fp = fsockopen("www.google.com", 80, $errno, $errstr, 30);
    if ($fp) {
       $out = "GET /search?client=navclient-auto&ch=$ch&features=Rank&q=info:$url HTTP/1.1
";
       //echo "<pre>$out</pre>"; //debug only
       $out .= "User-Agent: {$this->googleua}
";
       $out .= "Host: www.google.com
";
       $out .= "Connection: Close

";
       fwrite($fp, $out); 
       //$pagerank = substr(fgets($fp, 128), 4); //debug only
       //echo $pagerank; //debug only
       while (!feof($fp)) {
            $data = fgets($fp, 128);
            //echo $data;
            $pos = strpos($data, "Rank_");
            if($pos === false){} else{
                $pr=substr($data, $pos + 9);
                $pr=trim($pr);
                $pr=str_replace("",'',$pr);
                return $pr;
            }
       }
       //else { echo "$errstr ($errno)<br />"; } //debug only
       fclose($fp);
    }
    return $pr;
    }
}
//$gpr = new PageRank();
//echo $gpr->printrank("http://www.baidu.com/");
?>

© 2009 - 2024 冰河的博客