浅析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 相关文章推荐
PHP简洁函数(PHP简单明了函数语法)
Jun 10 PHP
PHP常用函数和常见疑难问题解答
Mar 05 PHP
ci检测是ajax还是页面post提交数据的方法
Nov 10 PHP
php数组查找函数总结
Nov 18 PHP
解决phpcms更换javascript的幻灯片代码调用图片问题
Dec 26 PHP
php实现session自定义会话处理器的方法
Jan 27 PHP
php判断文件夹是否存在不存在则创建
Apr 09 PHP
微信支付开发交易通知实例
Jul 12 PHP
laravel中的错误与日志用法详解
Jul 26 PHP
PHP编程实现脚本异步执行的方法
Aug 09 PHP
thinkPHP框架通过Redis实现增删改查操作的方法详解
May 13 PHP
Laravel框架Eloquent ORM简介、模型建立及查询数据操作详解
Dec 04 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
php 连接mysql连接被重置的解决方法
2011/02/15 PHP
php过滤所有恶意字符(批量过滤post,get敏感数据)
2014/03/18 PHP
php str_replace替换指定次数的方法详解
2017/05/05 PHP
jQuery实现元素拖拽并cookie保存顺序的方法
2016/02/20 Javascript
easyui window refresh 刷新两次的解决方法(推荐)
2016/05/18 Javascript
jQuery中show与hide方法用法示例
2016/09/16 Javascript
JS 获取HTML标签内的子节点的方法
2016/09/21 Javascript
BootStrap Validator对于隐藏域验证和程序赋值即时验证的问题浅析
2016/12/01 Javascript
jQuery实现对网页节点的增删改查功能示例
2017/09/18 jQuery
Vue 使用 Mint UI 实现左滑删除效果CellSwipe
2018/04/27 Javascript
webpack项目轻松混用css module的方法
2018/06/12 Javascript
详解JavaScript中的函数、对象
2019/04/01 Javascript
基于JavaScript判断两个对象内容是否相等
2020/01/10 Javascript
小程序开发之模态框组件封装
2020/04/23 Javascript
jquery插件懒加载的示例
2020/10/24 jQuery
原生js实现弹窗消息动画
2020/11/20 Javascript
[05:49]DOTA2-DPC中国联赛 正赛 Elephant vs LBZS 选手采访
2021/03/11 DOTA
Windows下使Python2.x版本的解释器与3.x共存的方法
2015/10/25 Python
Python实现字符串格式化的方法小结
2017/02/20 Python
Python编程之基于概率论的分类方法:朴素贝叶斯
2017/11/11 Python
python实现手机通讯录搜索功能
2018/02/22 Python
python网络爬虫学习笔记(1)
2018/04/09 Python
Python线程条件变量Condition原理解析
2020/01/20 Python
Python3中的f-Strings增强版字符串格式化方法
2020/03/04 Python
TensorFlow的环境配置与安装教程详解(win10+GeForce GTX1060+CUDA 9.0+cuDNN7.3+tensorflow-gpu 1.12.0+python3.5.5)
2020/06/22 Python
详解CSS3 弹性布局快速入门
2019/06/06 HTML / CSS
德国旅行、体验和活动的预订平台:Watado
2019/12/04 全球购物
外包公司软件测试工程师
2014/11/01 面试题
专业求职信撰写要诀
2014/02/18 职场文书
乡镇交通安全实施方案
2014/03/29 职场文书
优秀教研组申报材料
2014/12/26 职场文书
2015年人事科工作总结
2015/04/28 职场文书
小学英语教学经验交流材料
2015/11/02 职场文书
民事纠纷协议书
2016/03/23 职场文书
JavaScript 中for/of,for/in 的详细介绍
2021/11/17 Javascript
Vite + React从零开始搭建一个开源组件库
2022/06/25 Javascript