2014-05-21 72 views
0

我正在面對Python正則表達式中的一些問題。
我已經Pos的文本標籤字的格式如下正則表達式在文本中提取名詞

('play', 'NN')|('2', 'CD')|('dvd', 'NN')|('2', 'CD')|('for', 'IN')|('instance', 'NN')|('i', 'PRP')|('made', 'VBD')|('several', 'JJ')|('back', 'NN')|('ups', 'NNS')|('of', 'IN')|('my', 'PRP$')|('dvd', 'NN')|('movies', 'NNS')|('using', 'VBG')|('dvd', 'NN')|('r', 'NN')|('w', 'NN')|('and', 'CC')|('r', 'NN')|('w', 'NN')|('and', 'CC')|('it', 'PRP')|('plays', 'VBZ')|('the', 'DT')|('dvds', 'NNS') 

我希望做的是提取這段文字一起出現的所有的名詞和所有的名詞(沒有它們之間存在的話)應該是在同一個字符串中。所有以NN開頭的標籤都是名詞。這裏是正則表達式我寫了這一點:

re.compile(r"(\|?\([\'|\"][\w]+[\'|\"]\, \'NN\w?\'\)\|?)+") 

我是新來書寫正則表達式的凌亂的表達式很抱歉,但這裏是它的產生ouptput:

["('play', 'NN')|", "|('dvd', 'NN')|", "|('instance', 'NN')|", "('ups', 'NNS')|", "('movies', 'NNS')|", "('w', 'NN')|", "('w', 'NN')|"] 

我要的是對於語料庫中的「備份」和「DVD電影」這樣的詞,即出現在一起的名詞應該一起出現在輸出中。

我做錯了什麼,誰能請sujjest!

+1

請不要使用正則表達式解析名詞。正則表達式不適合於這項任務,因爲他們無法理解給定語言的語義或語法。請考慮使用類似nltk的東西。 –

+2

@JamesMills - 我相信OP已經在標記語法語法中標記爲名詞......例如,僞元素中的第二個元素是'NN' – mgilson

+0

即使識別哪個位置標記的標記實際上是名詞,我仍然會在這裏使用nltk。 –

回答

0

你可以做到這一點,而不使用正則表達式?是不是隻是解析你想要的文字?

更新感謝mgilson的評論

import ast 
nouns = [] 
for word_and_tag in pos_tagged_words.split("|"): 
    word, tag = ast.literal_eval(word_and_tag) 
    if tag.startswith("NN"): 
     #do something? 
     #probably this... 
     nouns.append(word) 

#use nouns 
+1

'word,tag = ast.literal_eval(word_and_tag)'''''''可能會做一個技巧:-)然後''itertools.groupby'與'lambda t:t [1] .startswith('NN')'... – mgilson

+0

我不想根據「|」分詞因爲那樣我就不得不單獨檢查出現在一起的名詞並加入它們。我希望正則表達式能爲我做這個工作。 :P – loki

0

你也許可以做一些與此itertools很酷。假設你可以可靠地劈在|的話:

def word_yielder(word_str): 
    tuples = (ast.literal_eval(t) for t in word_str.split('|')) 
    for key, group in itertools.groupby(tuples, key=lambda t: t[1].startswith('NN')): 
     if key: # Have a group of nouns, join them together. 
      yield (' '.join(t[0] for t in group), 'NN') 
     else: # Have a group of non-nouns 
      for t in group: # python3.x -- yield from :-) 
       yield t 
+0

你的代碼正在工作,但它產生的所有單詞而不是名詞。但是我想要做的主要任務(加入名詞)正在發生。 我對itertools知之甚少,所以我想我會仔細研究它。謝謝。 :) – loki

+0

@ user2732789 - 如果是這樣的話,只要切斷'else'語句...那麼你只會有名詞。 – mgilson

0

這裏是一個pyparsing解決方案:

from pyparsing import * 

LPAR,RPAR,COMMA,VERT,QUOT = map(Suppress,"(),|'") 
nountype = Combine(QUOT + "NN" + Optional(Word(alphas)) + QUOT) 

nounspec = LPAR + quotedString.setParseAction(removeQuotes) + COMMA + nountype + RPAR 

# match all nounspec's that have one or more separated by '|'s 
noungroup = delimitedList(nounspec, delim=VERT) 

# join the nouns, and return a new tuple when a nounspec list is found 
noungroup.setParseAction(lambda tokens: (' '.join(tokens[0::2]), tokens[1])) 

# parse sample text 
sample = """('play', 'NN')|('2', 'CD')|('dvd', 'NN')|('2', 'CD')|('for', 'IN')|('instance', 'NN')|('i', 'PRP')|('made', 'VBD')|('several', 'JJ')|('back', 'NN')|('ups', 'NNS')|('of', 'IN')|('my', 'PRP$')|('dvd', 'NN')|('movies', 'NNS')|('using', 'VBG')|('dvd', 'NN')|('r', 'NN')|('w', 'NN')|('and', 'CC')|('r', 'NN')|('w', 'NN')|('and', 'CC')|('it', 'PRP')|('plays', 'VBZ')|('the', 'DT')|('dvds', 'NNS')""" 
print sum(noungroup.searchString(sample)).asList() 

打印:

[('play', 'NN'), ('dvd', 'NN'), ('instance', 'NN'), ('back ups', 'NN'), ('dvd movies', 'NN'), ('dvd r w', 'NN'), ('r w', 'NN'), ('dvds', 'NNS')]