在Python和NLTK中删除单引号但保留撇号
我正在尝试制作一份诗歌的词频列表。我的代码可以读取一个.txt文件,并生成一个.csv文件来存储这些数据。
我现在遇到的问题是如何去掉文本中不相关的标点符号。我目前的相关代码是:
import nltk
raw = open('file_name.txt', 'r').read()
output = open('output_filename.csv','w')
txt = raw.lower()
pattern = r'''(?x)([A_Z]\.)+|\w+(-\w+)*|\.\.\|[][.,;"'?():-_`]'''
tokenized = nltk.regexp_tokenize(txt,pattern)
这个代码几乎完美地工作,因为它保留了像chimney-sweeper这样的单词中的连字符,但它也把缩写词拆成了两个单独的词,这不是我想要的。
例如,我的文本文件(试运行的是威廉·布莱克的《无邪之歌》)中有这样的行:
'Pipe a song about a Lamb!'
我希望它变成:
Pipe | a | song | about | a | Lamb
我之前使用的代码保持了缩写词的完整性,但也让我得到了带有单引号的单词:
for punct in string.punctuation:
txt = txt.replace(punct,' ')
re.sub(r'\r+',' ',txt)
所以我得到的是:
'Pipe | a | song | about | a | Lamb'
我想找到这两者之间的折中方案,因为我需要保留像O'er这样的单词中的撇号和连字符,但想去掉其他所有的标点。
我知道这个话题在论坛上似乎已经讨论得很透彻,但我花了四天时间尝试每个提供的例子,却没有一个能按预期工作,所以我决定发个问题,而不是把自己急得抓狂。
编辑:
看起来标准的分词器在我的文本上不工作的原因是一些撇号的位置有点奇怪。我通过使用一堆.replace()
指令得到了我想要的结果:
txt = txt.replace("\n", " ")
#formats the text so that the line break counts as a space
txt = txt.replace("”", " ")
#replaces stray quotation marks with a space
txt = txt.replace("“", " ")
#replaces stray quotation marks with a space
txt = txt.replace(" ’", " ")
#replaces a right leaning apostrophe with a space if it follows a space(which now includes line breaks)
txt = txt.replace(" ‘", " ")
#replaces a left leaning apostrophe with a space if it follows a space
我相信有办法把这些都合并成一行代码,但我现在只想说我很高兴它都能正常工作!
1 个回答
9
与其直接替换标点符号,不如先根据空格把句子分开,然后再去掉每个单词开头和结尾的标点符号:
>>> import string
>>> phrase = "'This has punctuation, and it's hard to remove!'"
>>> [word.strip(string.punctuation) for word in phrase.split(" ")]
['This', 'has', 'punctuation', 'and', "it's", 'hard', 'to', 'remove']
这样做可以保留单词内部的撇号和连字符,同时去掉单词开头或结尾的标点符号。
需要注意的是,单独的标点符号会被替换成一个空字符串 ""
:
>>> phrase = "This is - no doubt - punctuated"
>>> [word.strip(string.punctuation) for word in phrase.split(" ")]
['This', 'is', '', 'no', 'doubt', '', 'punctuated']
这很容易过滤掉,因为空字符串在判断时会被看作 False
:
filtered = [f for f in txt if f and f.lower() not in stopwords]
# ^ excludes empty string