Php 如何在字符串中找到专有名词?

Php 如何在字符串中找到专有名词?,php,Php,我试图在用户提交的3-4句的段落中识别专有名词。我同意这个功能有点缺陷,因为我有一个版主团队来验证几乎所有的东西 下面是输入段落的示例 尼克·斯威谢尔在第一局中击出詹姆斯·希尔兹的本垒打,打出五分,纽约洋基队在周二晚上以8-3击败坦帕湾队,在艾尔东部以2 1/2的比分领先雷人队 我想让函数去掉以下关键词/专有名词 尼克·斯威舍,詹姆斯·希尔兹,纽约扬基队,坦帕湾,雷队,艾尔东部 我在想我可以把字符串分解,用空格把单词分开。然后我会检查每个单词,看第一个字母是否大写。如果是,请退回。如果没有,请转

我试图在用户提交的3-4句的段落中识别专有名词。我同意这个功能有点缺陷,因为我有一个版主团队来验证几乎所有的东西

下面是输入段落的示例

尼克·斯威谢尔在第一局中击出詹姆斯·希尔兹的本垒打,打出五分,纽约洋基队在周二晚上以8-3击败坦帕湾队,在艾尔东部以2 1/2的比分领先雷人队

我想让函数去掉以下关键词/专有名词

尼克·斯威舍,詹姆斯·希尔兹,纽约扬基队,坦帕湾,雷队,艾尔东部

我在想我可以把字符串分解,用空格把单词分开。然后我会检查每个单词,看第一个字母是否大写。如果是,请退回。如果没有,请转到下一个单词

但是多词关键词/专有名词呢?如何让函数在已找到首字母大写的单词后检查单词

所以函数会找到Nick,但是我如何告诉它也检查下一个单词呢?因此,请检查next是否已封顶,如果已封顶,请返回Nick Swisher。如果没有,就把尼克还给我


再进一步说,如果是一个三个单词的短语呢?纽约被发现了,纽约被发现了,我怎样才能找到北方佬呢

不久前,我在一个项目中使用了这项服务。可能对你有用。您必须编写一个简单的脚本,才能将文本上载到服务器。查看他们的API,了解如何配置etc

通常,这样做是不容易的

如果他忘了将专有名词大写怎么办?“星期四”怎么样?“只有我这个人”这句话怎么样


最简单的方法可能是检测大写字母,一系列大写字母将被视为专有名词。最难的方法是对英语句子进行(语言)语法分析,这很难做到。

试试像theese这样的正则表达式:

[A-Z]{1,1}[a-z]*([\s][A-Z]{1,1}[a-z]*)*

但一定要检查区分大小写

这将匹配以大写字母开头的单词,甚至多个后续单词:

$text = 'Nick Swisher homered off James Shields to key a five-run burst in the first inning and the New York Yankees beat Tampa Bay 8-3 on Tuesday night, opening a 2 1/2-game lead over the Rays in the AL East.';

$matches= array();
preg_match_all('/([[:upper:]]+[[:lower:]]*(\W|$))+/', $text, $matches);
print_r($matches);

请注意,
$matches[0]
中的字符串都以
$matches[2]
中的字符结尾。这可以通过
foreach
cleanup语句轻松解决,也可以通过修改正则表达式来解决。

我认为您不能依赖于大写。即使您不需要使用英语以外的其他语言(例如,德语将所有名词大写),也有相当一部分用户根本不大写,或者不一致

我怀疑任何基于语法规则的尝试都会失败——你的3个单词组合问题就指向了这一点。真正的问题是,你可能找不到一个有用的、不含糊的语法定义来定义“专有名词”到底是什么


另一种方法是使用已知专有名词(城市名称、给定名称、姓氏)列表,并假设如果您发现其中两个或多个专有名词仅以空格分隔,则它是一个复合名词。

下面是一个脚本,在您的段落上运行时,该脚本将生成一个具有以下值的数组:

阵列([0]=>Nick Swisher[1]=>James Shields[2]=>New York Yankees[3]=>Tampa Bay[4]=>周二[5]=>Rays[6]=>AL East。)

这有用吗

$proper_nouns = Array();
$words = explode(' ', $paragraph);
for ($i = 0; $i < count($words); $i++) {
    if (preg_match('/[A-Z]/', $words[$i]) > 0) {
        $proper_noun = $words[$i];
        $index = 1;
        while (true) {
            if ($i + $index < count($words)) {
                if (preg_match('/[A-Z]/', $words[$i + $index]) > 0) {
                    $proper_noun = $proper_noun." ".$words[$i + $index];
                    $index++;
                }
                else {
                    $i = $i + $index - 1;
                    break;
                }
            }
            else {
                break;
            }
        }
        array_push($proper_nouns, $proper_noun);
    }
}
$property_nomes=Array();
$words=爆炸(“”,$段落);
对于($i=0;$i0){
$property_noon=$words[$i];
$index=1;
while(true){
如果($i+$index0){
$property_noon=$property_noon.““$words[$i+$index];
$index++;
}
否则{
$i=$i+$index-1;
打破
}
}
否则{
打破
}
}
数组推送($专有名词,$专有名词);
}
}

不确定您使用的是哪种语言,但这里有一个查找专有名词的方法。它使用的不仅仅是大写字母。即使不使用php,也可以将其用作所用语言的模型。以下是描述:


专有名词类可以使用基于首字母大写、单词在句子中的位置等句法线索的启发式方法从给定文本中查找和提取专有名词。它可以尝试使用连词组合专有名词以查找多个单词专有名词。这个类提供了定制,因此它可以应用于其他语言,这些语言的语法使用相同的启发式方法。

如果您需要的不仅仅是正则表达式,最好的方法是使用一个自然语言处理器,如openNLP,它构建在Solr之上

第一步是安装ApacheSolr/Lucene

您可以下载Solr并在几分钟内开始运行。然后安装/构建openNLP


这听起来很吓人,但它将为您提供强大的功能和真正可扩展的解决方案,如专有名词提取等

检查雅虎术语提取器这将自动返回流行字符串。希望经过一些修改后它能正常工作。{1,1}感觉没有必要,特别是因为如果省略它,它是默认值。它也不会正确地匹配“AL East”,但最好像你一样重复这句话,而不是我的解决方案,捕捉结尾空格/点/等等。是的,你是对的,只是我用kodos的笔尖写的东西,但这应该是朝着正确的方向推进谢谢你们。Emil,我希望我也能检查一下你的答案。我应该详细说明一下,但是我指向php类的链接不仅仅是为了大写,还有更多。考虑它是否是句子的第一个单词,放弃常用的大写形式,如“I”,并考虑诸如名称标题之类的东西,即使没有大写,也会表示名称。这是预演