浅析PHP关键词替换的类(避免重复替换,保留与还原原始链接)


Posted in PHP onSeptember 22, 2015

php关键词替换的类(避免重复替换,保留与还原原始链接)

本节主要内容:

一个关键词替换的类

主要可以用于关键词过滤,或关键词查找替换方面。

实现过程分析:

关键词替换,其实就是一个str_replace()的过程,如果是单纯的str_replace面对10W的关键词,1W字的文章也只需要2秒左右。

问题所在:

关键词替换了不只一次,比如a需要替换成<a>a</a>,但结果可能是<a><a>a</a></a>等这样。

为此,需要一个方法保护好已经替换了的标签,那么在处理文章之前,就先把标签替换掉比如[_tnum_]在文章处理好了以后再把它还原。

另外一个问题,如果关键字或文章中有[_tnum_]本身怎么办,那么就需要排除这种这里就不能使用str_replace了而需要用到preg_replace用正则来排除。

第三个问题,如果有两个关键字a和ab怎么办,希望先把长的匹配掉,短后匹配,这样就需要在匹配前先排序。

最后一个问题,当str_replace改成了preg_replace以后,变慢了同样一段话10W次匹配要5秒钟,字符串处理的函数中strpos要快一些,那么先用strpos找出关键词即可,10W次查询还不到1秒。就算是100万才道8秒多。

一个关键词匹配替换的类,代码:

代码示例:

<?php
 /* 
  * 关键词匹配类
  * @author ylx <ylx@gmail.com>
  * @packet mipang
  * 使用实例
  * $str = "绿壳蛋鸡撒范德萨下一年,下一年的洒落开房间卢卡斯地方军";
  * $key = new KeyReplace($str,array("xxxx"=>"sadf","下一年"=>'http://baidu.com',"下一年"=>'google.com'));
  * echo $key->getResultText();
  * echo $key->getRuntime();
  */
class KeyReplace
{
 private $keys = array();
 private $text = "";
 private $runtime = ;
 private $url = true;
 private $stopkeys = array();
 private $all = false;
 /**
  * @access public  
  * @param string $text 指定被处理的文章
  * @param array $keys 指定字典词组array(key=>url,...) url可以是数组,如果是数组将随机替换其中的一个
  * @param array $stopkeys 指定停止词array(key,...) 这里面的词将不会被处理
  * @param boolean $url true 表示替换成链接否则只替换
  * @param boolean $all true 表示替换所有找到的词,否则只替换第一次
  */
 public function __construct($text='',$keys=array(),$url=true,$stopkeys=array(),$all=false) {
  $this->keys = $keys;
  $this->text = $text;
  $this->url = $url;
  $this->stopkeys = $stopkeys;
  $this->all = $all;
 }
 /**
  * 获取处理好的文章
  * @access public  
  * @return string text
  */
 public function getResultText() {
  $start = microtime(true);
  $keys = $this->hits_keys();
  $keys_tmp = array_keys()($keys);
  function cmp($a, $b){
   if (mb_strlen($a) == mb_strlen($b)) {
 return ;
   }
   return (mb_strlen($a) < mb_strlen($b)) ? : -;
  }
  usort($keys_tmp,"cmp");
  foreach($keys_tmp as $key){
   if(is_array($keys[$key])){
 $url = $keys[$key][rand(,count($keys[$key])-)];
   }else
 $url = $keys[$key];
   $this->text = $this->r_s($this->text,$key,$url);
  }
  $this->runtime = microtime(true)-$start;
  return $this->text;
 }
 /**
  * 获取处理时间
  * @access public  
  * @return float 
  */
 public function getRuntime() {
  return $this->runtime;
 }
 /**
  * 设置关键词
  * @access public  
  * @param array $keys array(key=>url,...)
  */
 public function setKeys($keys) {
  $this->keys = $keys;
 }
 /**
  * 设置停止词
  * @access public  
  * @param array $keys array(key,...)
  */
 public function setStopKeys($keys) {
  $this->stopkeys = $keys;
 }
 /**
  * 设置文章
  * @access public  
  * @param string $text 
  */
 public function setText($text) {
  $this->text = $text;
 }
 /**
  * 用来找到字符串里面命中的关键词
  * @access public
  * @return array $keys 返回匹配到的词array(key=>url,...)
  */
 public function hits_keys(){
  $ar = $this->keys;
  $ar = $ar?$ar:array();
  $result=array();
  $str = $this->text;
  foreach($ar as $k=>$url){
   $k = trim($k);
   if(!$k)
 continue;
   if(strpos($str,$k)!==false && !in_array($k,$this->stopkeys)){
 $result[$k] = $url;
   }
  }
  return $result?$result:array();
 }
 /**
  * 用来找到字符串里面命中的停止词
  * @access public
  * @return array $keys 返回匹配到的词array(key,...)
  */
 public function hits_stop_keys(){
  $ar = $this->stopkeys;
  $ar = $ar?$ar:array();
  $result=array();
  $str = $this->text;
  foreach($ar as $k){
   $k = trim($k);
   if(!$k)
 continue;
   if(strpos($str,$k)!==false && in_array($k,$this->stopkeys)){
 $result[] = $k;
   }
  }
  return $result?$result:array();
 }
 /**
  * 处理替换过程 
  * @access private
  * @param string $text 被替换者
  * @param string $key 关键词
  * @param string $url 链接
  * @return string $text 处理好的文章
  */
 private function r_s($text,$key,$url){
  $tmp = $text;
  $stop_keys = $this->hits_stop_keys();
  $stopkeys = $tags = $a = array();
  if(preg_match_all("#<a[^>]+>[^<]*</a[^>]*>#su",$tmp,$m)){
   $a=$m[];
   foreach($m[] as $k=>$z){
 $z = preg_replace("#\##s","\#",$z);
 $tmp = preg_replace('#'.$z.'#s',"[_a".$k."_]",$tmp,);
   }
  };
  if(preg_match_all("#<[^>]+>#s",$tmp,$m)){
   $tags = $m[];
   foreach($m[] as $k=>$z){
 $z = preg_replace("#\##s","\#",$z);
 $tmp = preg_replace('#'.$z.'#s',"[_tag".$k."_]",$tmp,);
   }
  }
  if(!empty($stop_keys)){
   if(preg_match_all("#".implode("|",$stop_keys)."#s",$tmp,$m)){
 $stopkeys = $m[];
 foreach($m[] as $k=>$z){
  $z = preg_replace("#\##s","\#",$z);
  $tmp = preg_replace('#'.$z.'#s',"[_s".$k."_]",$tmp,);
 }
   }
  }
  $key = preg_replace("#([\#\(\)\[\]\*])#s","\\\\$",$key);
  if($this->url)
   $tmp = preg_replace("#(?!\[_s|\[_a|\[_|\[_t|\[_ta|\[_tag)".$key."(?!ag\d+_\]|g\d+_\]|\d+_\]|s\d+_\]|_\])#us",'<a href="'.$url.'">'.$key.'</a>',$tmp,$this->all?-:);
  else
   $tmp = preg_replace("#(?!\[_s|\[_a|\[_|\[_t|\[_ta|\[_tag)".$key."(?!ag\d+_\]|g\d+_\]|\d+_\]|s\d+_\]|_\])#us",$url,$tmp,$this->all?-:);
  if(!empty($a)){
   foreach($a as $n=>$at){
 $tmp = str_replace("[_a".$n."_]",$at,$tmp);
   }  
  }  
  if(!empty($tags)){
   foreach($tags as $n=>$at){
 $tmp = str_replace("[_tag".$n."_]",$at,$tmp);
   }  
  }  
  if(!empty($stopkeys)){
   foreach($stopkeys as $n=>$at){
 $tmp = str_replace("[_s".$n."_]",$at,$tmp);
   }  
  }  
  return $tmp;
 }
}

以上就是本文给大家介绍的PHP关键词替换的类(避免重复替换,保留与还原原始链接)。

PHP 相关文章推荐
模拟xcopy的函数
Oct 09 PHP
简单介绍下 PHP5 中引入的 MYSQLI的用途
Mar 19 PHP
PHP 修复未正常关闭的HTML标签实现代码(支持嵌套和就近闭合)
Jun 07 PHP
关于PHP递归算法和应用方法介绍
Apr 15 PHP
关于尾递归的使用详解
May 02 PHP
基于php冒泡排序算法的深入理解
Jun 09 PHP
yii框架表单模型使用及以数组形式提交表单数据示例
Apr 30 PHP
PHP的拦截器实例分析
Nov 03 PHP
PHP使用GETDATE获取当前日期时间作为一个关联数组的方法
Mar 19 PHP
ThinkPHP中limit()使用方法详解
Apr 19 PHP
PHP中CheckBox多选框上传失败的代码写法
Feb 13 PHP
php数组函数array_push()、array_pop()及array_shift()简单用法示例
Jan 26 PHP
PHP实现搜索相似图片
Sep 22 #PHP
从刷票了解获得客户端IP的方法
Sep 21 #PHP
fsockopen pfsockopen函数被禁用,SMTP发送邮件不正常的解决方法
Sep 20 #PHP
分享ThinkPHP3.2中关联查询解决思路
Sep 20 #PHP
使用PHPCMS搭建wap手机网站
Sep 20 #PHP
求帮忙修改个php curl模拟post请求内容后并下载文件的解决思路
Sep 20 #PHP
PHP执行SQL文件并将SQL文件导入到数据库
Sep 17 #PHP
You might like
5款适合PHP使用的HTML编辑器推荐
2015/07/03 PHP
微信小程序发送订阅消息的方法(php 为例)
2019/10/30 PHP
thinkphp框架无限级栏目的排序功能实现方法示例
2020/03/29 PHP
Js+Dhtml:WEB程序员简易开发工具包(预先体验版)
2006/11/07 Javascript
jQuery中与toggleClass等价的程序段 以及未来学习的方向
2010/03/18 Javascript
jquery ajax请求实例深入解析
2012/11/26 Javascript
jquery实现隐藏与显示动画效果/输入框字符动态递减/导航按钮切换
2013/07/01 Javascript
JavaScript eval() 函数介绍及应用示例
2014/07/29 Javascript
15个jquery常用方法、小技巧分享
2015/01/13 Javascript
JS设置cookie、读取cookie、删除cookie
2015/04/17 Javascript
jquery衣服颜色选取插件效果代码分享
2015/08/28 Javascript
js表单处理中单选、多选、选择框值的获取及表单的序列化
2016/03/08 Javascript
浅析在javascript中创建对象的各种模式
2016/05/06 Javascript
JS判断鼠标进入容器的方向与window.open新窗口被拦截的问题
2016/12/23 Javascript
Bootstrap导航条鼠标悬停下拉菜单
2017/01/04 Javascript
详解Layer弹出层样式
2017/08/21 Javascript
jQuery使用zTree插件实现可拖拽的树示例
2017/09/23 jQuery
详解如何使用koa实现socket.io官网的例子
2018/11/04 Javascript
小程序云开发实现数据库异步操作同步化
2019/05/18 Javascript
Vue中常用rules校验规则(实例代码)
2019/11/14 Javascript
[01:07:17]EG vs Optic Supermajor 败者组 BO3 第一场 6.6
2018/06/07 DOTA
Python父目录、子目录的相互调用方法
2019/02/16 Python
Selenium元素定位的30种方式(史上最全)
2020/05/11 Python
Mysql数据库反向生成Django里面的models指令方式
2020/05/18 Python
基于python实现MQTT发布订阅过程原理解析
2020/07/27 Python
如何查找和删除数据库中的重复数据
2014/11/05 面试题
银行求职信个人范文
2013/12/16 职场文书
个人简历自我评价范文
2014/02/04 职场文书
保护环境建议书300字
2014/05/13 职场文书
银行求职信怎么写
2014/05/26 职场文书
生物工程专业求职信
2014/09/03 职场文书
图书借阅制度范本
2015/08/06 职场文书
小学二年级班主任工作经验交流材料
2015/11/02 职场文书
解决Navicat for MySQL 连接 MySQL 报2005错误的问题
2021/05/29 MySQL
MySQL去除密码登录告警的方法
2022/04/20 MySQL
python缺失值填充方法示例代码
2022/12/24 Python