发布一个纯PHP的中文关键字自动提取工具

没有评论

2010 年 12 月 06 日 at 下午 10:28分类:PHP | WEB开发

周末的时候看到腾讯的空间里面写日志的时候能自动提取关键字,感觉这个功能非常的好,于是我自己准备也写一个。因为,提取关键字,肯定要涉及分词,现在的分词算法,最好的估计是统计算法,但是实现稍微复杂一点,用PHP的话,性能往往也不够。于是,我一切从简,争取星期天一天能写完这个工具。
我翻了一下最简单的分词,好像就是向前最大匹配。而且如果字典好的话,据说准确率还挺高的。当然,我没有什么好字典,从中科院的分词软件里面,拿了一本字典。大概有10万的词汇量。当然,你可以用其他的字典,但是一定要有词频。
当然,只是简单的分词,算法没有什么好说的,我就说说我写的时候遇到的问题。

1. 字典管理。
本来我想把字典先读成一个PHP Array 来实现,但是,发现内存占用很大,而且非常的慢。这样,即使写出来,也太慢了。于是乎,我想到了给字典设计一个简单的索引。
索引建立的方法是这样的:
1.1 所有的词汇进行排序。
1.2 然后对每个词汇的第一个字,建立索引,放在字典文件的开头。
1.3 索引区后面就是内容,为了方便进行二分查找,所有的项必须对齐,所以某个字下面按照最长的那个词汇进行对齐。
我写了一个工具,把中科院分词的字典,转换成我的格式的字典。
这样,一测试, 发现性能还可以。但是,每秒查询 2000次左右。为了加速这本字典,减少IO的次数。又写了一个类:MFile,先把整个文件读入内存,我发现读取200K,和读取1M的文件,花费的时间差不多,所以自己加载进入内存算了。
这本字典足足让我写了一个下午才搞定(上午我还没有起床)。

2. PHP不支持Unicode,所以,其实,它不把汉字当作一个字,而是两个char。于是,我还显得把文章转换成一个字的数组。这里,
本来不需要这样复杂,但是我为了以后扩展方便,给字加了分类。
define(“T_CHINESE”, 1); //中文
define(“T_SEP”, 1 << 1); //分割符合 define("T_NUM", 1 << 2); //数字 define("T_INDEX", 1 << 3); //索引 ① ② ③ ④ ⑤ ⑥ ⑦ define("T_LETTER", 1 << 4); //字母 define("T_WORD", 1 << 5); //正常单词 define("T_OTHER", 1 << 6); 用一个Int 的位,表示一种类型。比如中文数字就是 T_CHINESE | T_NUM 正确区分数字我觉得对提取关键字不是非常的有用。所以,我其实没有对数字进行特殊的处理。这样,我分词的基本思路是: 先根据句子的分割符号,分成子句。如果子句中还有中文和英文的话,那就分成切分中文部分,和切分英文部分。当然,我这个分法还不是非常的合理。我把阿拉伯数字也算成英文了,这点我没有深入去判断,因为数量词一般不会成为文章的关键字。 写完所有的分词部分,已经是晚上11点了。我不得不草草收场了。本来想支持英文的提取,但是,找不到一本有词频的英文字典,所以,只能算了,时间已经很晚了,大家就凑合着用。我估计也没有什么人会用,哈哈。只是,无聊的时候看连续剧,好不如时间这样打发来的快。 关键字: 胡同,原名,和尚,大街,名字,街巷,小街,王府井,历史,宣武门 cost : 0.1061
代码在这里下载,我写代码的习惯不是很好,欢迎大家批评指正。
点击下载

关于PHP判断浏览器语言

一条评论

2010 年 12 月 06 日 at 下午 2:22分类:PHP | WEB开发

<?php
if ($_SERVER['HTTP_ACCEPT_LANGUAGE']=='zh-CN' || $_SERVER['HTTP_ACCEPT_LANGUAGE']=='zh-cn'){

	echo("<meta http-equiv='refresh' content = '0;URL = http://zh-cn.xcomm.cn'>;");

}elseif ($_SERVER['HTTP_ACCEPT_LANGUAGE']=='zh-TW' || $_SERVER['HTTP_ACCEPT_LANGUAGE']=='zh-tw'){

	echo("<meta http-equiv='refresh' content = '0;URL = http://fan.xcomm.cn'>;");

}elseif ($_SERVER['HTTP_ACCEPT_LANGUAGE']=='zh-HK' || $_SERVER['HTTP_ACCEPT_LANGUAGE']=='zh-hk'){

	echo("<meta http-equiv='refresh' content = '0;URL = http://fan.xcomm.cn'>;");

}elseif ($_SERVER['HTTP_ACCEPT_LANGUAGE']=='zh-MO' || $_SERVER['HTTP_ACCEPT_LANGUAGE']=='zh-mo'){

	echo("<meta http-equiv='refresh' content = '0;URL = http://fan.xcomm.cn'>;");

}elseif ($_SERVER['HTTP_ACCEPT_LANGUAGE']=='zh-SG' || $_SERVER['HTTP_ACCEPT_LANGUAGE']=='zh-sg'){

	echo("<meta http-equiv='refresh' content = '0;URL = http://fan.xcomm.cn'>;");

}elseif ($_SERVER['HTTP_ACCEPT_LANGUAGE']=='en' || $_SERVER['HTTP_ACCEPT_LANGUAGE']=='zh-sg'){

	echo("<meta http-equiv='refresh' content = '0;URL = http://en.xcomm.cn'>;");

}else{
	
	echo("<meta http-equiv='refresh' content = '0;URL = http://zh-cn.xcomm.cn'>;");

}
?>

这段为什么在FF中不管是英文还是中文只会跳到最后 ELSE 的 URL 中去,判断完全失效,为什么??
因为firefox、chrome……$_SERVER['HTTP_ACCEPT_LANGUAGE']的值类似于:zh-CN,zh;q=0.8

php文件操作函数

没有评论

2010 年 12 月 06 日 at 上午 9:49分类:PHP | WEB开发

php文件操作函数,返回指定目录下面的文件信息

<?php
	function get_dir_file_info($source_dir, $include_path = FALSE, $_recursion = FALSE)
	{
		static $_filedata = array();
		$relative_path = $source_dir;

		if ($fp = @opendir($source_dir))
		{
			// reset the array and make sure $source_dir has a trailing slash on the initial call
			if ($_recursion === FALSE)
			{
				$_filedata = array();
				$source_dir = rtrim(realpath($source_dir), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
			}

			while (FALSE !== ($file = readdir($fp)))
			{
				if (@is_dir($source_dir.$file) && strncmp($file, '.', 1) !== 0)
				{
					 get_dir_file_info($source_dir.$file.DIRECTORY_SEPARATOR, $include_path, TRUE);
				}
				elseif (strncmp($file, '.', 1) !== 0)
				{
					$_filedata[$file] = get_file_info($source_dir.$file);
					$_filedata[$file]['relative_path'] = $relative_path;
				}
			}
			return $_filedata;
		}
		else
		{
			return FALSE;
		}
	}
	function get_file_info($file, $returned_values = array('name', 'server_path', 'size', 'date'))
	{

		if ( ! file_exists($file))
		{
			return FALSE;
		}

		if (is_string($returned_values))
		{
			$returned_values = explode(',', $returned_values);
		}

		foreach ($returned_values as $key)
		{
			switch ($key)
			{
				case 'name':
					$fileinfo['name'] = substr(strrchr($file, DIRECTORY_SEPARATOR), 1);
					break;
				case 'server_path':
					$fileinfo['server_path'] = $file;
					break;
				case 'size':
					$fileinfo['size'] = filesize($file);
					break;
				case 'date':
					$fileinfo['date'] = filectime($file);
					break;
				case 'readable':
					$fileinfo['readable'] = is_readable($file);
					break;
				case 'writable':
					// There are known problems using is_weritable on IIS.  It may not be reliable - consider fileperms()
					$fileinfo['writable'] = is_writable($file);
					break;
				case 'executable':
					$fileinfo['executable'] = is_executable($file);
					break;
				case 'fileperms':
					$fileinfo['fileperms'] = fileperms($file);
					break;
			}
		}

		return $fileinfo;
	}
	$data = get_dir_file_info('Mail');
	print_r($data);