找回密码

碧海潮声大学生网

查看: 566|回复: 0
打印 上一主题 下一主题

技术贴一碗汤没有,我来热热锅,简单全文索引实现

[复制链接]
跳转到指定楼层
1#
发表于 2013-12-6 20:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
复制代码
1、sphinx的seekcore
不必说,mysql全文搜索的不二方案,为mysql所问索引而生的第三方软件。coreseeksphinx的衍生版本,为适应中国市场而生做了很多本土化的优化。之前在公司实习的时候有接触过sphinx,但是没有深入研究。拿到sphinx高兴啊,立即装上百度找一些配置文章。装好之后才想起来我用的是虚拟空间,虚拟空间装什么sphinx啊。
2、海曼大神pscws分词神器
首先我想说网上很多人都说highman的分词神器,但是不知道多少人用过了,highman个人现在应该是把大部分时间放在迅搜上边,关于分词的pscws已经很久没更新了。迅搜和seekcore一样都是建立在服务器端的,这种解决方案对只能虚拟空间的屌丝来说几乎不太可能实现。首先我想说highmanpswcs在高版本php下支持是不怎么好的,之前用的是5.01的没有报错,后来换了5.4+php版本结果上来直接一脸的错。能在虚拟机上运行的分词php文件有两个一个pswcs23还有一个pswcs4,官方说pswcs4速度较慢不推荐使用,剩下的只有23两个版本了。看了一下速度还不错。注意pswcs2pswcs3只支持gbk形式文件。
当初自己没看清楚文档,吃不少苦,整整调试了三天全是乱码,害得我一个项目全跟着乱码巴拉巴拉看源代码,看得稀里糊涂没发现什么错了,最后在一字一句的去读了文档才发现只支持gbk编码。还好我是随时备份的。我用的是nodepad++默认是utf-8编码,所以是没法分割,只有乱码。而且数据库也是utf-8的编码,后来一运行我整个项目全乱码,什么验证码无法显示啊,乱七八槽。所以我再次提醒就算你全都用gbk形式来编码,做用之前别直接放到项目里边去测试。海曼的pswcs我研究了好几天,也得到了解决方案。解决方案请耐心看完下边关于另个方法的介绍。待会一起提到。
3、下面介绍关于二元法全文索引解决方案。
研究海曼哥哥的东西最后无功而返,倍受打击本来打算放弃了的。后来去研究了discuzecshop的站内搜索引擎,没有惊喜,无例外的用like只是在提交的搜索做了简单的处理全文索引用不上。百无聊赖躺在床上的时候用百度百科看了一下全文索引的定义,看到二分法做分词的方法,想想这倒是解决方案。然后花了一天去百度啊,找啊,终于找到了一个分词算法,因为不知道到底谁是原创,就不引用作者了。同样的问题,乱码,又不支持utf8
后来转念一想php不是可以转码吗?既然php可以转码,那么编码的问题就不存在了。
Ok到这里基本上问题都可以解决了。虽然可以转码,但是因为弄错了gbkutf-8ASCii码,害得我折腾了两天。把源代码看了无数遍。下面是我做的修改,我想再啰嗦一遍,网上有的哪个二元分词法是不正确的,只能分gbk,而且会把字符里的英文全过滤掉,我在这里做了点修正。
先说一下二元法分词怎么做:
(1)、如果要对一张article的表建立全文索引,那么得借助另一张变index来存放分词后的文本字符。两张表外键相关(分词后再逆回去是不现实的,而且建立全文索引之后写操作是相当吃力的)。
(2)、让msyql支持中文分词,最起码在my.ini里边加上这句ft_min_word_len = 1
这里有一边官文全文索引很好的文章可以参考一下,接下来怎么做我就不多说了
http://www.cnblogs.com/macula7/archive/2011/05/18/2050525.html

  1. /**
  2. * 二元发分割中文字符,可以对不同编码的中文进行分词
  3. * @param string $name 转入字符串
  4. * @return string
  5. */

  6. function spl_zhstr($strings) {
  7. $str=$strings;
  8. $encode = mb_detect_encoding($str, array("ASCII","UTF-8","GB2312","GBK","BIG5"));
  9. $str=iconv($encode,"GBK",$str);//更改编码,转为gbk,以一个汉字两个字节分词
  10. preg_match_all('/[0-9a-z]+?/U',$str,$enlg);
  11. $enword=implode(' ',$enlg[0]);//获得英文单词
  12. $charset= "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
  13. $str=preg_replace($charset,"\\0".chr(0x00),$str);//为了分词准确在每个单词后加'.'
  14. $search = array(",", "/", "\\", ".", ";", ":", "\"", "!", "~", "`", "^", "(", ")", "?", "-", "\t", "\n", "'", "<", ">", "\r", "\r\n", "$", "&", "%", "#", "@", "+", "=", "{", "}", "[", "]", ":", ")", "(", ".", "。", ",", "!", ";", "“", "”", "‘", "’", "〔", "〕", "、", "—", " ", "《", "》", "-", "…", "【", "】",);
  15. $str = str_replace($search,' ',$str);
  16. preg_match_all("/[\x80-\xff].?/",$str,$ar);
  17. $ar=$ar[0];
  18. for ($i=0;$i<count($ar);$i++)
  19. if($ar[$i]!=chr(0x00)) {
  20. $ar_new[]=$ar[$i];//将单词压入数组
  21. }
  22. $ar=$ar_new;
  23. $oldsw=0;
  24. for ($ar_str='',$i=0;$i<count($ar);$i++) {
  25. $sw=strlen($ar[$i]);
  26. if ($i>0 and $sw!=$oldsw)
  27. $ar_str.=' ';
  28. if ($sw==1)
  29. $ar_str.=$ar[$i];

  30. else
  31. if (@strlen($ar[$i+1])===2)
  32. $ar_str.=$ar[$i].$ar[$i+1].' ';
  33. elseif ($oldsw==1 or $oldsw==0)
  34. $ar_str.=$ar[$i];
  35. $oldsw=$sw;
  36. }
  37. $ar_str=trim(preg_replace("#\s{1,}#i"," ",$ar_str));
  38. $word=$ar_str;//.' '.$enword;
  39. $encode = mb_detect_encoding($word, array("ASCII","UTF-8","GB2312","GBK","BIG5"));
  40. $word=iconv($encode,"utf-8",$word);//编码转回utf-8
  41. return $word;
  42. }

  43. /**
  44. * 二元发分割中文字符,可以对不同编码的中文进行分词
  45. * @param string $name 转入字符串
  46. * @return string
  47. */

  48. function spl_zhstr($strings) {
  49. $str=$strings;
  50. $encode = mb_detect_encoding($str, array("ASCII","UTF-8","GB2312","GBK","BIG5"));
  51. $str=iconv($encode,"GBK",$str);//更改编码,转为gbk,以一个汉字两个字节分词
  52. preg_match_all('/[0-9a-z]+?/U',$str,$enlg);
  53. $enword=implode(' ',$enlg[0]);//获得英文单词
  54. $charset= "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
  55. $str=preg_replace($charset,"\\0".chr(0x00),$str);//为了分词准确在每个单词后加'.'
  56. $search = array(",", "/", "\\", ".", ";", ":", "\"", "!", "~", "`", "^", "(", ")", "?", "-", "\t", "\n", "'", "<", ">", "\r", "\r\n", "$", "&", "%", "#", "@", "+", "=", "{", "}", "[", "]", ":", ")", "(", ".", "。", ",", "!", ";", "“", "”", "‘", "’", "〔", "〕", "、", "—", " ", "《", "》", "-", "…", "【", "】",);
  57. $str = str_replace($search,' ',$str);
  58. preg_match_all("/[\x80-\xff].?/",$str,$ar);
  59. $ar=$ar[0];
  60. for ($i=0;$i<count($ar);$i++)
  61. if($ar[$i]!=chr(0x00)) {
  62. $ar_new[]=$ar[$i];//将单词压入数组
  63. }
  64. $ar=$ar_new;
  65. $oldsw=0;
  66. for ($ar_str='',$i=0;$i<count($ar);$i++) {
  67. $sw=strlen($ar[$i]);
  68. if ($i>0 and $sw!=$oldsw)
  69. $ar_str.=' ';
  70. if ($sw==1)
  71. $ar_str.=$ar[$i];

  72. else
  73. if (@strlen($ar[$i+1])===2)
  74. $ar_str.=$ar[$i].$ar[$i+1].' ';
  75. elseif ($oldsw==1 or $oldsw==0)
  76. $ar_str.=$ar[$i];
  77. $oldsw=$sw;
  78. }
  79. $ar_str=trim(preg_replace("#\s{1,}#i"," ",$ar_str));
  80. $word=$ar_str;//.' '.$enword;
  81. $encode = mb_detect_encoding($word, array("ASCII","UTF-8","GB2312","GBK","BIG5"));
  82. $word=iconv($encode,"utf-8",$word);//编码转回utf-8
  83. return $word;
  84. }



复制代码




关于pscws的的解决方案:
既然编码不是问题,那么就很容易了。如果appserv集成环境的我建议你该到wamp下来,因为appserv2.59太老了,2.6版本有太新了,php6都没正式发行就参合进去了。相对而言wamp的版本会多一点。但是我用的版本下一屏幕都是这个错Strict standards: Redefining already defined constructor for class PSCWS2,我想是highman大神太久没有更新了,文坛都是2008年的,我才上高中。我现在没有时间去研究为什么他会报错了,指导老师天天催着做设计(我的专业和计算机不搭嘎)。但是把php.inidisplay erros屏蔽掉时候还是能看到结果的。
下面是一个测试demo,我测过可以分词,不管是gbk/gb2312 还是utf-8,都可以成功分词。关于pscws请到官方自行下载http://www.xunsearch.com/scws/
  • require 'pscws2.class.php';
  • $str="你好吗天气好吗";
  • $encode = mb_detect_encoding($str, array("ASCII","UTF-8","GB2312","GBK","BIG5")); //获得编码
  • echo $encode;
  • $str=iconv($encode,"GBK",$str);//转码
  • $pscws = new PSCWS2('./dict/dict.xdb');//实例化对象,参数为路径,部分省略详见官网
  • $res = $pscws->segment($str);//返回的是数组哦
  • $res=implode(" ",$res);
  • $encode = mb_detect_encoding($res, array("ASCII","UTF-8","GB2312","GBK","BIG5"));
  • $res=iconv($encode,"UTF-8",$res);
  • echo $encode;
  • print_r($res




这是我的个人网站:http://www.hunhun234.com


最后唠叨一点。我也在学习web开发中,如果存在出错,请给我反馈:craber234@sina.cn
昨天才放到虚拟主机上,本地实现了全文索引,很遗憾虚拟主机不给改mysql参数故无法进行全文索引搜索,所有和全文索引相关的功能全废了,后来不情愿的改回了like模式。只是简单的测试,还有很多BUG。因为要毕业了,要做毕业设计,最近被老师下了最后通牒,所以没时间玩web了,不然就毕不了业了。一直在firefox和google chrome下开发所以不太顾及ie的兼容性,本人不太喜欢ie
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|小黑屋| 碧海潮声大学生网  

Copyright © 2001-2013 Comsenz Inc.   All Rights Reserved.

Powered by Discuz! X3.2( 浙ICP备11026473号 )

快速回复 返回顶部 返回列表