Archive for 十二月, 2009
PHP:两个数组合并,相同键名的值相加
0$array1 = array('a'=>1,'b'=>2);
$array2 = array('b'=>1,'c'=>5,'d'=>4);
foreach ((array)array_intersect(array_keys($array1),array_keys($array2)) as $key){
$mixed[$key] = $array1[$key]+$array2[$key];
unset($array1[$key],$array2[$key]);
}
$mixed = array_merge($array1,$array2,(array)$mixed);
PHP中二维数组的排序方法
0本文介绍的是从 BugFree 摘录来的二维数组排序函数,可以实现类似 MySQL 的 ORDER BY 效果,当数组不是从数据库取得时会有特殊应用。
PHP:
// 说明:PHP中二维数组的排序方法
// 整理:http://www.CodeBit.cn
/**
* @package BugFree
* @version $Id: FunctionsMain.inc.php,v 1.32 2005/09/24 11:38:37 wwccss Exp $
*
*
* Sort an two-dimension array by some level two items use array_multisort() function.
*
* sysSortArray($Array,"Key1","SORT_ASC","SORT_RETULAR","Key2"……)
* @author Chunsheng Wang
* @param array $ArrayData the array to sort.
* @param string $KeyName1 the first item to sort by.
* @param string $SortOrder1 the order to sort by("SORT_ASC"|"SORT_DESC")
* @param string $SortType1 the sort type("SORT_REGULAR"|"SORT_NUMERIC"|"SORT_STRING")
* @return array sorted array.
*/
function sysSortArray($ArrayData,$KeyName1,$SortOrder1 = "SORT_ASC",$SortType1 = "SORT_REGULAR")
{
if(!is_array($ArrayData))
{
return $ArrayData;
}
// Get args number.
$ArgCount = func_num_args();
// Get keys to sort by and put them to SortRule array.
for($I = 1;$I < $ArgCount;$I ++)
{
$Arg = func_get_arg($I);
if(!eregi("SORT",$Arg))
{
$KeyNameList[] = $Arg;
$SortRule[] = '$'.$Arg;
}
else
{
$SortRule[] = $Arg;
}
}
// Get the values according to the keys and put them to array.
foreach($ArrayData AS $Key => $Info)
{
foreach($KeyNameList AS $KeyName)
{
${$KeyName}[$Key] = $Info[$KeyName];
}
}
// Create the eval string and eval it.
$EvalString = 'array_multisort('.join(",",$SortRule).',$ArrayData);';
eval ($EvalString);
return $ArrayData;
}
//################# 示例 #################
$arr = array(
array(
'name' => '学习',
'size' => '1235',
'type' => 'jpe',
'time' => '1921-11-13',
'class' => 'dd',
),
array(
'name' => '中国功夫',
'size' => '153',
'type' => 'jpe',
'time' => '2005-11-13',
'class' => 'jj',
),
array(
'name' => '编程',
'size' => '35',
'type' => 'gif',
'time' => '1997-11-13',
'class' => 'dd',
),
array(
'name' => '中国功夫',
'size' => '65',
'type' => 'jpe',
'time' => '1925-02-13',
'class' => 'yy',
),
array(
'name' => '中国功夫',
'size' => '5',
'type' => 'icon',
'time' => '1967-12-13',
'class' => 'rr',
),
);
print_r($arr);
//注意:按照数字方式排序时 153 比 65 小
$temp = sysSortArray($arr,"name","SORT_ASC","type","SORT_DESC","size","SORT_ASC","SORT_STRING");
print_r($temp);
?>
Perl 的 html 解析模块
0HTML::TreeBuilder
这个解析模块使用了强大的 HTML::Element 模块。解析时,HTML::TreeBuilder模块把整个 html 文档转换成了 perl 的数据结构,可以进行任意的操作。
使用时先创建一个 HTML::TreeBuilder 对象。
use Data::Dumper qw(Dumper);
$Data::Dumper::Indent = 1;
use HTML::TreeBuilder;
my $tree = new HTML::TreeBuilder;
直接向 HTML::TreeBuilder 传递文件好像会把中文转换成 unicode 的字符,所以一般传递文件句柄。而且传递的字符串或者句柄一般要先确保是 utf8 字符串才行,不然会有一个warning:
Parsing of undecoded UTF-8 will give garbage when decoding entities at /home/ywb/temp/t.pl line 16, line 5.
解析文件和解析字符串的区别仅仅是前者是使用 parse_file 函数,而后者使用parse 函数。下面以解析文件句柄的例子:
binmode DATA, “utf8″;
$tree->parse_file(\*DATA);
print Dumper($tree), “\n”;
__DATA__
| x | y |
| 1 | 2 |
要提取出表格中的内容可以这样:
foreach my $row ( $tree->find_by_tag_name(“tr”) ) {
foreach my $cell ( $row->content_list ) {
print $cell->as_text, “\t”;
}
print “\n”;
}
由于 HTML::Element 会强制把所有的 tag 都转换成小写,所以不用担心 tag的大小写问题。HTML::TokenParser和 HTML::Parser 等模块不同,HTML::TokenParser 模块是类似于流(stream oftokens)的方式来解析 HTML 文件。在解析的过程中 HTML 中的文本转换成这六种token:
["S", $tag, $attr, $attrseq, $text]
["E", $tag, $text]
["T", $text, $is_data]
["C", $text]
["D", $text]
["PI", $token0, $text]
这个例子应该能够体现这个模块解析的一些特点:
use HTML::TokeParser;
my $file = \*DATA;
my $parser = HTML::TokeParser->new($file)
or die “Can’t open $file: $!\n”;
my (@table, @row, $inrow);
while (my $token = $parser->get_token( )) {
my $type = $token->[0];
if ( $type eq ‘T’ ) {
push @row, $token->[1] if $inrow;
}
elsif ( $type eq ‘S’ ) {
if ( $token->[1] eq ‘tr’ ) {
$inrow = 1;
}
}
elsif ( $type eq ‘E’ ) {
if ( $token->[1] eq ‘tr’ ) {
push @table, [@row]; # 注意这一行不能用 \@row
@row = ();
$inrow = 0;
}
}
}
print Dumper(\@table), “\n”;
__DATA__
| x | y |
| 1 | 2 |
与前面 HTML::TreeBuilder 的例子相比可能有些麻烦,但是很多情况下,只需要一次处理一个 token,这时候用这个模块就非常方便了,比如你要得到一个html 里所有的图片或者所有的链接,像这样写就行了:
my @images;
while (my $token = $parser->get_token( )) {
my $type = $token->[0];
if ( $type eq ‘S’ ) {
if ( $token->[1] eq ‘img’ ) {
push @images, $token->[2];
}
}
}
__DATA__

专门的模块HTML::LinkExtor如果要提取 html 文件中的链接,也不用自己写了,用 HTML::LinkExtor 就好了。一个简单的例子:
require HTML::LinkExtor;
my $p = HTML::LinkExtor->new();
$p->parse_file(\*DATA);
print Dumper($p->links), “\n”;
__DATA__
x

HTML::LinkExtor 的 new 函数可以提供一个 callback 函数,这个函数是当发现链接时就调用这个函数。传递给这个函数的第一个参数是链接的类型,比如 ‘a’,'img’,其余的参数是链接的属性。如果提供了 callback 函数,HTML::LinkExtor 就不再累积链接了,这意味着你不能再用 links 函数来得到所有的链接。要得到所有链接,只有在 callback 函数里自己保存好。
require HTML::LinkExtor;
my $p = HTML::LinkExtor->new(\&cb);
$p->parse_file(\*DATA);
sub cb {
my($tag, %links) = @_;
print Dumper($tag, \%links), “\n”;
}
__DATA__
x

HTML::HeadParser如果只是要得到 html 的标题或者其它在 head 标签之间内容,就不要用HTML::TreeBuilder 这样的重量级模块了,HTML::HeadParser 模块就能完成这个任务,并且使用相当简单。
require HTML::HeadParser;
my $p = HTML::HeadParser->new;
my $text = join(”, );
$p->parse($text) and print “not finished”;
# to access
print “Title: “, $p->header(‘Title’), “\n”;
# to access
print “Base: “, $p->header(‘Content-Base’), “\n”;
# to access
print “Content type:”, $p->header(‘Content-Type’), “\n”;
# to access
print “Author:”, $p->header(‘X-Meta-Author’), “\n”;
print Dumper($p->header), “\n”;
__DATA__
可以看出它不能解析出 script、link、style 这样的标签。
HTML::TableExtractHTML::TableExtract 只能从 html 中提取出 table 里的内容。如果只要这个,那么这个模块是很容易使用的。
use HTML::TableExtract;
use Data::Dumper qw(Dumper);
my $html_string = join(“”, );
$te = HTML::TableExtract->new();
$te->parse($html_string);
print Dumper($te), “\n”;
foreach $ts ($te->tables) {
print “Table (“, join(‘,’, $ts->coords), “):\n”;
foreach $row ($ts->rows) {
print join(‘,’, @$row), “\n”;
}
}
__DATA__
| x | y |
| 1 | 2 |
由这个例子可以看出,解析后链接信息都丢失了。但是表格里的内容是很容易得到的。
使用perl脚本抓取网页总结
0使用perl实现网页抓取,对网络蜘蛛的初步尝试。
环境
windows xp,IIS,perl 5.88,CMD
使用到的模块
use LWP::Simple; 用来得到网页
use HTML::HeadParser; 对部分进行解析,得到标题、编码、关键词等
use HTML::FormatText::WithLinks; 将html变成文本可读样式
use Encode qw/encode decode/; 解决不同网页的编码问题
需求
在CMD中调试,最后IIS中调用,解析结果要保存到数据库中,数据库中采用utf8编码,解析的网页为gb2312编码,所以理清编码特别重要。
关于编码首先应该弄清楚的概念
- Perl字符串是使用utf8编码的,也就是说读进perl的字符的编码格式都是utf8;
- 读取输入时,perl会自动将其转换为urf8,输出时的编码依据运行环境已经上下游环境。
乱码问题
脚本使用ANSI编码,只是数据库的内容使用decode,结果内容有个别字符乱码,是HTML::FormatText::WithLinks; 将html变成文本可读样式时出现问题。可以算是一个bug
解决方法
脚本实用utf8编码,得到的网页首先进行decode,再进行其他的处理,问题解决,但在cmd下调试的时候,会有“Wide character in print”警告信息,因为环境是gbk,输出urt8编码是会报警,使用encode(”euc-cn”, $value),对输出进行转义,可以解决这个问题,而网上说的加 use encoding “utf-8″; 不能解决这个问题。
其他需要注意的问题
- 调用匹配的内容再去匹配其他内容时,注意对该内容的元字符进行转义;
- 入库的内容也要进行转义;
遗留问题:IIS对perl的支持,配置没有问题,增加了对.pl、.cgi的定义,测试时发现在IE下正常,在firefox下弹出保存文件的对话框,但是以前的.pl正常。估计于haed的输出有关系,还有待于进一步的测试。
encode、decode函数说明
encode函数是用来编码Perl字符串的。它将Perl字符串中的字符用指定的编码格式编码,最终转化为字节流的形式,因此和Perl处理环境之外的事物打交道经常需要它。
其格式很简单:
$octets = encode(ENCODING, $string [, CHECK])
$string: Perl字符串
encoding: 是给定的编码方式
$octets: 是编码之后的字节流
check: 表示转换时如何处理畸变字符(也就是Perl认不出来的字符)。一般不需使用
decode函数则是用来解码字节流的。它按照你给出的编码格式解释给定的字节流,将其转化为使用utf8编码的Perl字符串,一般来说从终端或者文件取得的文本数据都应该用decode转换为Perl字符串的形式。它的格式为:
$string = decode(ENCODING, $octets [, CHECK])
$string、ENCODING、$octets和CHECK的含义同上。
明白如何使用该函数的例子:
use Encode;
$dat="测试文本";
$str=decode("gb2312",$dat);
@chars=split //,$str;
foreach $char (@chars) {
print encode("gb2312",$char),"\n";
}
perl–模块安装方法和常用模块
0CPAN(Comprehensive Perl Archive Network)是internet上Perl模块最大的集散地,包含了现今公布的几乎所有的perl模块。网址:http://www.cpan.org/
而http://search.cpan.org/,可以查找任何一个模块并提供下载
Linux/Unix—perl模块的安装方法
Linux/Unix下安装Perl模块有两种方法:手工安装和自动安装。第一种方法是从CPAN上下载您需要的模块,手工编译、安装。第二种方法是联上internet,使用一个叫做CPAN的模块自动完成下载、编译、安装的全过程。
A. 手工安装
从CPAN下载了安装模块的压缩文件,假设放在/usr/local/src(一般需要编译安装的软件,都放在此目录下安装)。
1. cd /usr/local/src
2. tar xvzf x.x.tar.gz
3. cd x.x
4. perl Makefile.PL (生成makefile)
5. make (建立模块)&& make test (测试模块)
如果测试结果报告“all test ok”,您就可以放心地安装编译好的模块了。
6. make install
注意:上述步骤适合于Linux/Unix下绝大多数的Perl模块。可能还有少数模块的安装方法略有差别,安装前,先看一下目录里的README或INSTALL。
B. 自动安装:
安装前需要先联上线,并且您需要取得root权限。
perl -MCPAN -e shell
初次运行CPAN时需要做一些设置,如果您的机器是直接与internet相联(拨号上网、专线,etc.),那么一路回车就行了,只需要在最后选一个离您最近的CPAN镜像站点。
cpan>h (获得帮助)
cpan>m (列出CPAN上所有模块的列表)
cpan>install module_name (自动完成从下载到安装的全过程。)
cpan>q (安装完,后退出)
常用模块:
(1) Net::FTP
(2) Net::Telnet
(3) LWP::Simple, get()
(4) Expect
(5) XML::Simple, XMLin()
(6) Data::Dumper, Dumper()
(7) IO::Socket
(8) Date::Manip, DateCalc(), UnixDate()
(9) Date::Manip, Date_Cmp()
(10) File::Find, find()
(11) ExtUtils::Installed, new(), modules(), version()
(12) DBI, connect(), prepare(), execute(), fetchrow_array()
(13) Getopt::Std
(14) Proc::ProcessTable
(15) Shell
(16) Time::HiRes, sleep(), time()
(17) HTML::LinkExtor, links(), parse_file()
(18) Net::Telnet, open(), print(), getline()
(19) Compress::Zlib, gzopen(), gzreadline(), gzclose()
(20) Net::POP3, login(), list(), get()
(21) Term::ANSIColor
(22) Date::Calc Calendar(), Today()
(23) Term::Cap, Tgetend(), Tgoto, Tputs()
(24) HTTPD::Log::Filter
(25) Net::LDAP
(26) Net::SMTP mail(), to(), data(), datasend(), auth()
(27) MIME::Base64, encode_base64(), decode_base64()
(28) Net::IMAP::Simple, login(), mailboxes(), select(), get()…
(29) Bio::DB::GenBank, Bio::SeqIO
(30) Spreadsheet::ParseExcel
(31) Text::CSV_XS, parse(), fields(), error_input()
(32) Benchmark
了解这些模块功能以及具体使用方法,可以去http://search.cpan.org/ 查看。
perl中使用递归遍历目录[zt]
0perl自带的函数远不及php多,但功能确实很强大,实现起来也只有几行代码。
perl中的目录操作函数有:
1。mkdir 函数
调用语法:mkdir (dirname, permisions)
dirname:将要创建的目录名,可以为字符串或表达式。
permisions:八进制数,指定目录的访问权限。其值和意义如下:
权限值 权限
4000 运行时设置用户 ID
2000 运行时设置组 ID
1000 粘贴位
0400 拥有者读权限
0200 拥有者写权限
0100 拥有者执行权限
0040 组读权限
0020 组写权限
0010 组执行权限
0004 所有人读权限
0002 所有人写权限
0001 所有人执行权限
2。chdir 函数
调用语法:chdir (dirname)
3。opendir 函数
调用语法:opendir (dirvar, dirname)
dirvar:目录句柄,与文件句柄类似
dirname:目录名,可为字符串或表达式
调用成功返回真,否则返回假
4。closedir 函数
调用语法:closedir (mydir)
5。readdir 函数
调用语法:readdir (mydir)
6。telldir 函数
调用语法:location = telldir (mydir)
返回当前所在目录
7。seekdir 函数
调用语法:seekdir (mydir, location)
location必须为telldir 函数返回的值
8。rewinddir 函数
调用语法:rewinddir (mydir)
9。rmdir 函数
调用语法:rmdir (dirname)
程序代码:
#!/usr/bin/perl
sub listdir { my @arr, $j = 0;
for($i=0;$i<=$#_;$i++) {
if(-d $_[$i]) {
if(opendir($handle, $_[$i])) {
while($dir = readdir($handle)) {
if(!($dir =~ m/^\.$/) and !($dir =~ m/^(\.\.)$/)) {
print "$dir";
if(-d $_[$i]."\\$dir") {
$arr[$j++] = $_[$i]."\\$dir";
print "\t[DIR]"
}
print "\n";
}
}
closedir($handle);
}
}
}
if($j>0) {
listdir (@arr);
}
}
listdir “D:\\download”;
迷宫闹钟G-Alarm 注册方法
0G-Alarm2.3V.cab 安装包一个
galarm_KeyGen.exe注册机一个
到程序中打开G_Alarm,然后将注册值输入注册即可。。
解决xmarks不能用的方法[zt]
0xmarks的在线书签居然不能用了,老是”problem syncing”,“网络超时错误”,下面介绍几个解决方法。
1 修改 HOSTS
将以下内容手工添加至C:WindowsSystem32etc的hosts文件里(linux在/etc)
64.147.188.86 www.xmarks.com
64.147.188.92 api.xmarks.com
64.147.188.89 login.xmarks.com
64.147.188.87 sync.xmarks.com
64.147.188.86 static.xmarks.com
64.147.188.86 download.xmarks.com
64.147.188.86 my.xmarks.com
如果还不行的话,左键点击 Xmarks 的图标,弹出设置菜单,选择“高级”,加密那个下拉框里面选择“全部加密”,再同步就成功了。
这个只是暂时性的解决,如果墙继续动一下的话可能就失效了,有FTP服务器的朋友可以考虑将XMarks的书签同步到自己的服务器去。
2 搭建自己的xmarks服务器
如果你有自己的虚拟主机或服务器的话,就可以使用xmarks的“使用自己的服务器”功能,方法如下:
- 用FTP在网站根目录创建一个文件夹(如:xmarks),用来存放xmarks的书签数据。
- 打开xmarks的“设置”窗口,“把Status”中的用户名和密码改成你的FTP的用户名和密码。
- 进入“高级”,选中“使用自己的服务器”,然后
“地址”里填:ftp://你的服务器IP/xmarks/xmarks.json
“Password URL”里填:ftp://你的服务器IP/xmarks/passwords.json - 点击“手动覆盖”区域里“强制覆盖服务器书签”后面的“上传”,xmarks将自动通过FTP把书签数据保存到你的服务器空间中。


如果你没有自己的服务器,推荐你用下面的比较稳定的免费空间:
http://www.v3host.be
http://www.cwahi.net
http://www.website.org
3 使用Weave Sync插件https://services.mozilla.com/
这是由Mozilla实验室开发的一个Firefox同步插件,不仅能同步书签,还能同步Firefox中保存的密码、浏览历史、自动填表内容、Tab项和一些个人设置。
登陆时会要求你输入在第一步注册时使用的邮箱、密码。另外还会要求输入一个Encryption Passphrase用于数据的加密,你可以输入一句好记、有个性、有意义的短语,如果怕麻烦就设成和密码一样的吧。这个短语不能更改(不确定),请和密 码一样牢记它,因为在以后的登录中也需要输入。
4 使用Gmarks(对中文支持不好)
Gmarks是一个基于Google Bookmarks的Firefox插件。
5 使用代理
很多地方都有相关的知识!!!
xmarks的在线书签居然不能用了,老是”problem syncing”,“网络超时错误”,下面介绍几个解决方法。
1 修改 HOSTS
将以下内容手工添加至C:WindowsSystem32etc的hosts文件里(linux在/etc)
64.147.188.86 www.xmarks.com
64.147.188.92 api.xmarks.com
64.147.188.89 login.xmarks.com
64.147.188.87 sync.xmarks.com
64.147.188.86 static.xmarks.com
64.147.188.86 download.xmarks.com
64.147.188.86 my.xmarks.com
如果还不行的话,左键点击 Xmarks 的图标,弹出设置菜单,选择“高级”,加密那个下拉框里面选择“全部加密”,再同步就成功了。
这个只是暂时性的解决,如果墙继续动一下的话可能就失效了,有FTP服务器的朋友可以考虑将XMarks的书签同步到自己的服务器去。
2 搭建自己的xmarks服务器
如果你有自己的虚拟主机或服务器的话,就可以使用xmarks的“使用自己的服务器”功能,方法如下:
- 用FTP在网站根目录创建一个文件夹(如:xmarks),用来存放xmarks的书签数据。
- 打开xmarks的“设置”窗口,“把Status”中的用户名和密码改成你的FTP的用户名和密码。
- 进入“高级”,选中“使用自己的服务器”,然后
“地址”里填:ftp://你的服务器IP/xmarks/xmarks.json
“Password URL”里填:ftp://你的服务器IP/xmarks/passwords.json - 点击“手动覆盖”区域里“强制覆盖服务器书签”后面的“上传”,xmarks将自动通过FTP把书签数据保存到你的服务器空间中。


如果你没有自己的服务器,推荐你用下面的比较稳定的免费空间:
http://www.v3host.be
http://www.cwahi.net
http://www.website.org
3 使用Weave Sync插件https://services.mozilla.com/
这是由Mozilla实验室开发的一个Firefox同步插件,不仅能同步书签,还能同步Firefox中保存的密码、浏览历史、自动填表内容、Tab项和一些个人设置。
登陆时会要求你输入在第一步注册时使用的邮箱、密码。另外还会要求输入一个Encryption Passphrase用于数据的加密,你可以输入一句好记、有个性、有意义的短语,如果怕麻烦就设成和密码一样的吧。这个短语不能更改(不确定),请和密 码一样牢记它,因为在以后的登录中也需要输入。
4 使用Gmarks(对中文支持不好)
Gmarks是一个基于Google Bookmarks的Firefox插件。
5 使用代理
很多地方都有相关的知识!!!xmarks的在线书签居然不能用了,老是”problem syncing”,“网络超时错误”,下面介绍几个解决方法。
1 修改 HOSTS
将以下内容手工添加至C:WindowsSystem32etc的hosts文件里(linux在/etc)
64.147.188.86 www.xmarks.com
64.147.188.92 api.xmarks.com
64.147.188.89 login.xmarks.com
64.147.188.87 sync.xmarks.com
64.147.188.86 static.xmarks.com
64.147.188.86 download.xmarks.com
64.147.188.86 my.xmarks.com
如果还不行的话,左键点击 Xmarks 的图标,弹出设置菜单,选择“高级”,加密那个下拉框里面选择“全部加密”,再同步就成功了。
这个只是暂时性的解决,如果墙继续动一下的话可能就失效了,有FTP服务器的朋友可以考虑将XMarks的书签同步到自己的服务器去。
2 搭建自己的xmarks服务器
如果你有自己的虚拟主机或服务器的话,就可以使用xmarks的“使用自己的服务器”功能,方法如下:
- 用FTP在网站根目录创建一个文件夹(如:xmarks),用来存放xmarks的书签数据。
- 打开xmarks的“设置”窗口,“把Status”中的用户名和密码改成你的FTP的用户名和密码。
- 进入“高级”,选中“使用自己的服务器”,然后
“地址”里填:ftp://你的服务器IP/xmarks/xmarks.json
“Password URL”里填:ftp://你的服务器IP/xmarks/passwords.json - 点击“手动覆盖”区域里“强制覆盖服务器书签”后面的“上传”,xmarks将自动通过FTP把书签数据保存到你的服务器空间中。


如果你没有自己的服务器,推荐你用下面的比较稳定的免费空间:
http://www.v3host.be
http://www.cwahi.net
http://www.website.org
3 使用Weave Sync插件https://services.mozilla.com/
这是由Mozilla实验室开发的一个Firefox同步插件,不仅能同步书签,还能同步Firefox中保存的密码、浏览历史、自动填表内容、Tab项和一些个人设置。
登陆时会要求你输入在第一步注册时使用的邮箱、密码。另外还会要求输入一个Encryption Passphrase用于数据的加密,你可以输入一句好记、有个性、有意义的短语,如果怕麻烦就设成和密码一样的吧。这个短语不能更改(不确定),请和密 码一样牢记它,因为在以后的登录中也需要输入。
4 使用Gmarks(对中文支持不好)
Gmarks是一个基于Google Bookmarks的Firefox插件。
5 使用代理
很多地方都有相关的知识!!!