StanfordCoreNLP 踩过的坑(python,java)

python--stanfordcorenlp

stanford core nlp 是一个用于nlp的工具库。它是用java写的,但是现在也为python提供了接口。前段时间笔者尝试在python中使用它:
首先引入stanfordcorenlp的包
在python文件中引用:

from stanfordcorenlp import StanfordCoreNLP

stanfordcorenlp 中只有 StanfordCoreNLP 一个类
获得StanfordCoreNLP 的对象:
创建StanfordCoreNLP 对象需要传入一个路径参数,从而获得一个存放相应jar包的文件夹:该文件夹下载地址:https://stanfordnlp.github.io/CoreNLP/download.html
笔者使用的是:stanford-corenlp-full-2016-10-31

nlp = StanfordCoreNLP(path)  # 这里的path即是stanford-corenlp-full-2016-10-31 的路径

使用
它的使用非常简单

from stanfordcorenlp import StanfordCoreNLP
nlp = StanfordCoreNLP(path)
sentence = "i 've had the player for about 2 years now and it still performs nicely with the exception of an occasional wwhhhrrr sound from the motor ."
print(nlp.dependency_parse(sentence))
nlp.close()

但是直接运行会出错

$ python WordFormation.py
Traceback (most recent call last):
  File "WordFormation.py", line 1, in <module>
    from stanfordcorenlp import StanfordCoreNLP
ModuleNotFoundError: No module named 'stanfordcorenlp'

或是:

PermissionError: [Errno 1] Operation not permitted

因此使用root权限运行:成功获得dependency

$ sudo python WordFormation.py
[('ROOT', 0, 3), ('nsubj', 3, 1), ('aux', 3, 2), ('det', 5, 4), ('dobj', 3, 5), ('case', 9, 6), ('advmod', 8, 7), ('nummod', 9, 8), ('nmod', 5, 9), ('advmod', 3, 10), ('cc', 3, 11), ('nsubj', 14, 12), ('advmod', 14, 13), ('conj', 3, 14), ('advmod', 14, 15), ('case', 18, 16), ('det', 18, 17), ('nmod', 14, 18), ('case', 23, 19), ('det', 23, 20), ('amod', 23, 21), ('compound', 23, 22), ('nmod', 18, 23), ('case', 26, 24), ('det', 26, 25), ('nmod', 23, 26), ('punct', 3, 27)]

其中的那些数字代表的是第几个单词,但是它是从1开始数的,('ROOT', 0, 3) 中的0不代表sentence中的单词

StanfordCoreNLP 还有一些功能,比如词性标注等都可以使用

但是笔者没有从StanfordCoreNLP 类中获得可以进一步获得dependency的方法:比如复合名词修饰 nmod 在这里我只能获得 nmod 而不能获得修饰用的介词 nmod:for 的形式

笔者没能找到合适的方法,因此我决定改用java尝试一下

JAVA--stanfordcorenlp

java 的话,语句相应会复杂一些

首先引入相应的jar包:
由于笔者建的maven项目
pom.xml 中加入:

    <properties>
        <corenlp.version>3.9.2</corenlp.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>edu.stanford.nlp</groupId>
            <artifactId>stanford-corenlp</artifactId>
            <version>${corenlp.version}</version>
        </dependency>

        <dependency>
            <groupId>edu.stanford.nlp</groupId>
            <artifactId>stanford-corenlp</artifactId>
            <version>${corenlp.version}</version>
            <classifier>models</classifier>
        </dependency>

    </dependencies>

开始运行:

import edu.stanford.nlp.ling.CoreAnnotations;
import java.util.Properties;
public class StanfordEnglishNlpExample {
    public static void main(String[] args) {
        Properties props = new Properties();
        // 设置相应的properties
        props.put("annotators", "tokenize,ssplit,pos,parse,depparse");
        props.put("tokenize.options", "ptb3Escaping=false");
        props.put("parse.maxlen", "10000");
        props.put("depparse.extradependencies", "SUBJ_ONLY");
        StanfordCoreNLP pipeline = new StanfordCoreNLP(props); // 获得StanfordCoreNLP 对象

        String str = "i 've had the player for about 2 years now and it still performs nicely with the exception of an occasional wwhhhrrr sound from the motor .";
        Annotation document = new Annotation(str);
        pipeline.annotate(document);
        CoreMap sentence = document.get(CoreAnnotations.SentencesAnnotation.class).get(0);
        SemanticGraph dependency_graph = sentence.get(SemanticGraphCoreAnnotations.CollapsedCCProcessedDependenciesAnnotation.class);  // 获得依赖关系图
        System.out.println("\n\nDependency Graph: " + dependency_graph.toString(SemanticGraph.OutputFormat.LIST));
    }// 直接打印关系
}

获得结果:

Dependency Graph: root(ROOT-0, had-3)
nsubj(had-3, i-1)
aux(had-3, 've-2)
det(player-5, the-4)
dobj(had-3, player-5)
case(years-9, for-6)
advmod(2-8, about-7)
nummod(years-9, 2-8)
nmod:for(player-5, years-9)
advmod(had-3, now-10)
cc(had-3, and-11)
nsubj(performs-14, it-12)
advmod(performs-14, still-13)
conj:and(had-3, performs-14)
advmod(performs-14, nicely-15)
case(exception-18, with-16)
det(exception-18, the-17)
nmod:with(performs-14, exception-18)
case(sound-23, of-19)
det(sound-23, an-20)
amod(sound-23, occasional-21)
compound(sound-23, wwhhhrrr-22)
nmod:of(exception-18, sound-23)
case(motor-26, from-24)
det(motor-26, the-25)
nmod:from(sound-23, motor-26)
punct(had-3, .-27)

在这里面就可以看到nmod:with nmod:of 这样的依存关系了

但是其实还是有问题的:
对于以上代码中的SemanticGraph 对象 dependency_graph 来说
如果想要获得它的对象的依存关系

List<SemanticGraphEdge> list = dependencies.edgeListSorted();

这时候就会发现,这个list中没有root的关系
实际上,如果想要root 关系,只能通过从 dependency_graph 再获取root关系列表,这样的话,没有很好的顺序关系

因此用另一种方法来获得:
为了将工作做的更完整一些,这里笔者将完成词性标注工作
想要使用词性标注器,首先需要获得english-left3words-distsim.tagger文件,这个文件在stanford-corenlp-2016-10-31 中有,可以直接用。但是很有可能由于引用的jar包和使用的tagger文件的版本不一致导致错误。

实际上,在我们引入的stanford-corenlp-models的jar包里就有这个tagger文件,但是想要将它读出来需要一点工作

URL url = new URL("jar:file:"+ path +
                "!/edu/stanford/nlp/models/pos-tagger/english-left3words/" +
                "english-left3words-distsim.tagger"); 
# 这里的path是jar包的路径,!后面的是tagger文件在jar包内部路径
JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();

由于词性标注器,MaxentTagger 类构造器,可以传入路径,也可以传入InputStream 对象:

MaxentTagger tagger = new MaxentTagger(jarURLConnection.getInputStream());

成功获得对象:

    public static void main(String[] args) throws java.net.MalformedURLException, IOException {

        URL url = new URL("jar:file:"+ path +
                "!/edu/stanford/nlp/models/pos-tagger/english-left3words/" +
                "english-left3words-distsim.tagger");
        JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();

        MaxentTagger tagger = new MaxentTagger(jarURLConnection.getInputStream());
        DependencyParser parser = DependencyParser.loadFromModelFile(DependencyParser.DEFAULT_MODEL); // 依存关系解析器

        String review = "i 've had the player for about 2 years now and it still performs nicely with the exception of an occasional wwhhhrrr sound from the motor .";
        String result = "[";
        DocumentPreprocessor tockenizer = new DocumentPreprocessor(new StringReader(review)); // 将一段话,分成多个句子
        for(List<HasWord> sentence: tockenizer){
            List<TaggedWord> tagged = tagger.tagSentence(sentence); // 对句子中的词打标签
            GrammaticalStructure gs = parser.predict(tagged);
            List<TypedDependency> tdl = gs.typedDependenciesCCprocessed(); // 获得依赖关系
            for(TypedDependency td: tdl){
                result = result.concat(td.reln()+"("+td.gov()+", "+td.dep()+"),");
            }
        }
        System.out.println(result.substring(0,result.length()-1)+"]");
    }

获得结果:

[nsubj(had/VBD, i/FW),aux(had/VBD, 've/VBP),root(ROOT, had/VBD),det(player/NN, the/DT),dobj(had/VBD, player/NN),case(years/NNS, for/IN),advmod(2/CD, about/IN),nummod(years/NNS, 2/CD),nmod:for(player/NN, years/NNS),advmod(had/VBD, now/RB),cc(had/VBD, and/CC),nsubj(performs/VBZ, it/PRP),advmod(performs/VBZ, still/RB),conj:and(had/VBD, performs/VBZ),advmod(performs/VBZ, nicely/RB),case(exception/NN, with/IN),det(exception/NN, the/DT),nmod:with(performs/VBZ, exception/NN),case(sound/NN, of/IN),det(sound/NN, an/DT),amod(sound/NN, occasional/JJ),compound(sound/NN, wwhhhrrr/NN),nmod:of(exception/NN, sound/NN),case(motor/NN, from/IN),det(motor/NN, the/DT),nmod:from(sound/NN, motor/NN),punct(had/VBD, ./.)]

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容