根据另一个缺少单词的句子从文本中提取句子

时间:2016-05-24 17:39:54

标签: php

因此,对于我的大学毕业论文,我选择构建一个Web应用程序,从文章(摘要应用程序)中提取主要想法。它是用PHP构建的。

但是我已经达到了一种我认为没有可能的解决方案的情况,也许你们可以给我一个想法或解决问题的方法。

所以基本上app依赖于提取算法,我做的是: 首先,我"消毒"文本,这意味着我删除所有停用词,我干掉这些词,删除任何可能包含'的缩写词或缩写词。'这可以改变我的文本,而不是正确地分解成句子。 之后,我通过.标记爆炸文本将文本分成句子,然后我得到一个数组中的所有句子。 现在来到我和#34;句子是评级,基本上这就是我发现文章中最相关的句子的方式,评分最高的句子通常是包含文章主要思想的句子。

但是我的问题现在开始了,我评价的句子就是我应用了所有'消毒'而且不是原来的形式。我想采用评分最高的句子,并根据我要从该评级句子匹配的文本中提取原始句子。我尝试将它与正则表达式匹配,但它并不总是有效。我需要100%的工作方法,根据评分最高的句子从文章中提取原始句子。

我不知道怎么做到这一点,因为评级句子错过了它的话。 我希望你理解我的观点。谢谢。

编辑: 这是我现在用来匹配文章中原始句子的功能,但我并不总是有效:

private function get_original_sentence($s, $t)
    {
        $s = preg_replace("/[^A-Za-z0-9 ]/", '', $s);
        $s = trim($s);

        $arr = explode(" ",$s);
        $f_word = $arr[0];
        $l_word = $arr[count($arr)-1];

        preg_match('~(?<=\.)([a-zA-Z ]*)'.$f_word.'(.*?)'.$l_word.'([a-zA-Z ]*)(?=\.)~i', $t, $matches);

        if(empty($string))
        {
            preg_match('~(?<=\.)([^\.]*)'.$f_word.'(.*?)'.$l_word.'([^\.]*)(?=\.)~i', $t, $matches);
        }

        return $matches[0] ? $matches[0] : false;
    }

$s参数是摘要后的评级句子,$t是完整的原始文章。

编辑2:缩写删除功能,它实际上不仅仅是缩写,而是对整个文本进行清理。

static private function _remove_abbrev($subject)
    {
        $domains = '\.ro|\.com|\.edu|\.org|\.gov';

        foreach(self::$abrv as $abrv)
        {
            $not.= strtolower(str_replace('.', '\.', $abrv)).'|';
            $not.= strtolower(trim(str_replace('.', '\.', $arbv))).'|';
        }

        $not = substr($not, 0, -1);

        //$subject = preg_replace('~(\".*?\")~u', '', strtolower($subject));//replaces " " from text.
        $subject = preg_replace('~(?<=\.|^)(?![^\.]{60,})[^\.&]*\&[^\.]*\.?~u', '', strtolower($subject));
        $subject = preg_replace('~\b\s?[\dA-za-z\-\.]+('.$domains.')~u', '', strtolower($subject));
        $subject = preg_replace('~\s*\(.*?\)\s*~u', '', strtolower($subject));
        $subject = preg_replace('~\b('.$not.')~u', '', strtolower($subject));
        $subject = preg_replace('~(?<=[^a-z])[A-Za-z]{1,5}+\.[\s\,]*(?=[a-z]|[0-9])~u', '', strtolower($subject));
        $subject = preg_replace('~(?<=[\s\,\.\:])([A-Za-z]*(\.)){2,}+(.)(?=.*)~u', '', strtolower($subject));
        $subject = preg_replace('~(\d)+\.(\d)*(\s)~u', '', strtolower($subject));

        return $subject;
    }

这是缩写数组:

static public $abrv = array(
        ' alin.', ' art.', ' A.N.P', ' A.V.A.B', ' A.V.A.S.', ' B.N.R', ' c.', ' C.A.S', ' C.civ.', ' C.com.', ' C.fam.', ' C.pen.', ' C.pr.civ.', ' C.pr.pen', ' C.N.C.D', ' C.N.V.M', ' C.N.S.A.S', ' C.S.M', ' C.S.J', ' D.G.F.P', ' D.G.P.M.B', ' D.N.A', ' D.S.V', 'Ed.', ' etc.', ' H.G.', ' I.G.P.F', ' I.G.P.R', ' I.N.M.L.', ' I.P.J', ' I.C.C.J', ' lit.', ' M.Ap.N.', ' art.', ' M.J.', ' M.Of.', ' nr.', ' O.G.', ' O.U.G.', ' p.', ' P.N.A.', ' par.', ' pct.', ' R.A.A.P.P.S.', ' subl. ns.', ' S.C.', ' S.A.', ' S.P.P.', ' S.R.I.', ' S.R.L.', 'U.N.B.R.', ' urm.', ' str.', ' sec.', ' pag.', ' a.c.', ' dv.', ' dvs.', ' prof.', ' conf.', ' dr.', ' drd.', ' mrd.', ' s.a.m.d'
    );

2 个答案:

答案 0 :(得分:0)

这种方法怎么样:

  1. 首先使用preg_match_all将所有匹配提取到带有数字索引的数组中$ substitutions
  2. 然后用一个唯一的标记替换它们,使用preg_replace的4变量:$ count,其值指向$ substitutions数组
  3. 粗略的代码草图:

    $count = 0;
    $substitutions = array();
    foreach ($patterns as $pattern) {
        $matches = array();
        preg_match_all($pattern, $subject, $matches);
        preg_replace($pattern, $subject, '__'.$count.'__', -1, $count);
    
        foreach ($matches[???] as $match) {
            $substiutions[] = $match;
        }
    }
    

    我不确定我是否搞砸了引用$ count作为引用调用的语法(例如文档中的&amp; $)。

    我认为这种方法的关键是从$ matches数组中提取正确的值。有一些选项,如何提取匹配。也许另一种方法可能不是使用来自preg_replace的$ count,而是来自$ matches

    的相应子数组

答案 1 :(得分:0)

Type功能看起来效果不佳。它删除了像&#34; art&#34;在句子的末尾,但没有删除缩写,例如&#34; C.A.S。&#34; (因为它已经删除了&#34; c。&#34;)。它还至少有一个拼写错误(_remove_abbr),并且在连接之前不会定义$arbv

尽管如此,如何使用空格字符替换它们而不是删除缩写,URL等?这样,当您将文本拆分为句子时,它们仍然具有与原始文本相同的长度,因此您可以存储句子开始和结束的位置。如有必要,此时您可以将多个空格转换为单个空格,但您仍然知道它们来自原始文本的位置。

你只需要一个回调函数来实现这个目标:

$not