不自重者,取辱。不自长者,取祸。不自满者,受益。不自足者,博闻。

   空间买下来已近很久了,一直没有时间来倒腾,这两天抽空来倒腾这个个人博客,从前端到后端,统统设计再实现一遍-_-!工作量确实还是不小的!


   前端那点儿东西,实现起来倒是没有什么障碍,就是日常工作中用到的Smarty3+HTML+Javascript+CSS。


   始终不是纯搞后端的,这个得承认,写了一篇文章,入库之前,需要先生成摘要,于是,这个摘要该怎么生成?算法怎么写?

一开始图省事儿,就网上随便找了一段PHP版本的摘要自动生成代码,贴过来以后发现各种BUG,生成出来的摘要简直没法用。

   没放弃,继续又找了好几个,效果都非常差,实在忍不住了!!!


   分析一下,摘要的生成,重点就是:

       1、不能简单的进行strip_tags处理,这样的摘要显示出来无格式,阅读体验很差

       2、不能简单的进行substring处理,这样会造成一些标签不能正确闭合,影响页面布局

   

   综合这两点来考虑,其实就没那么复杂了,只需要对富文本源码进行一次HTML词法分析,然后对分析结果进行逐一处理,最后根据具体的长度限制,将结果拼接起来,将未闭合的标签都闭合掉,就可以了。

   

   东西,还是用自家的习惯。咱银总搞的FCP功能很强大,Fl就能够实现这个词法分析的功能,要生成摘要,只需要稍加处理。


   改造后的Fl,生成摘要的核心算法,代码如下:

/**
 * 生成摘要
 * @param  string  $content='' 富文本内容源码
 * @param  integer $length=3000 摘要字数限制
 * @return [type]
 */
public function generateDigest($content='',$length=3000) {
    // 实例化Fl
    $flInstance = self::getInstance();
    // HTML词法分析
    $analyticResult = $flInstance->analytic_html($content);
 
    $result = '';
    $htmlTagStack = array();
 
    // 遍历词法分析的结果
    foreach ($analyticResult as $key => $item) {
        // 分析单个标签
        $tagAttr = $flInstance->analytic_html($item[0],2);
 
        // 开始标签,如:<p>、<div id="xx">
        if($item[1] == FL::HTML_TAG_START) {
            // 将不能自动闭合的标签压栈
            if(!$flInstance->analytic_html($tagAttr[1],4)) {
                $htmlTagStack[] = $tagAttr[1];
            }
        }
        // 结束标签
        elseif($item[1] == FL::HTML_TAG_END) {
            // 当前结束标签和栈顶的标签相同,则出栈该标签
            if($tagAttr[1] == $htmlTagStack[count($htmlTagStack) - 1]) {
                array_pop($htmlTagStack);
            }
        }
 
        // 拼接摘要
        $result .= $item[0];
 
        // 字数控制
        if(strlen($result) >= $length) {
            break;
        }
    }
 
    // 将没有闭合的标签,都闭合起来
    for ($i=count($htmlTagStack) - 1; $i >= 0 ; $i--) { 
        $result .= ('</' . $htmlTagStack[$i] . '>');
    }
 
    // 生成最终摘要
    return $result;
}