我很难在上拆分字符串\n。我将一个约138M长的日语字符串传递到标记器/单词标记器中,并得到“AttributeError:'NoneType'对象没有属性'split'”错误
标记器的名称是MeCab,它的作用是获取一个字符串,查找其中的单词,然后返回一个具有单词特征(名词、粒子、阅读等)的字符串。字符串中标记器标记的单词被“\n”拆分,因此我想使用新行将其拆分为一个列表
字符串的前25个字符:
str_text[:25]
输出:
'このページは以下にある削除依頼の議論を保存したもの'
当我使用下面的代码拆分前100万个字符时,我没有错误,但是当我将其扩展到1000万个字符时,我得到了上面提到的错误
前25个字符的编码和输出:
import MeCab
#opening the file containing the long string with Japanese text
file = open('output_text.txt')
str_text = file.read()
#passing string into the MeCab tokenizer/tagger and splitting the long string into a list based on
tagger = MeCab.Tagger()
words = tagger.parse(str_text[:25]).split('\n')[:-2] #last two entries are just some tagger info
for word in words:
temp_str = word.split('\t')
print(temp_str)
输出(第一个元素是单词,第二个元素包含关于单词的信息):
['この', '連体詞,*,*,*,*,*,この,コノ,コノ']
['ページ', '名詞,一般,*,*,*,*,ページ,ページ,ページ']
['は', '助詞,係助詞,*,*,*,*,は,ハ,ワ']
['以下', '名詞,非自立,副詞可能,*,*,*,以下,イカ,イカ']
['に', '助詞,格助詞,一般,*,*,*,に,ニ,ニ']
['ある', '動詞,自立,*,*,五段・ラ行,基本形,ある,アル,アル']
['削除', '名詞,サ変接続,*,*,*,*,削除,サクジョ,サクジョ']
['依頼', '名詞,サ変接続,*,*,*,*,依頼,イライ,イライ']
['の', '助詞,連体化,*,*,*,*,の,ノ,ノ']
['議論', '名詞,サ変接続,*,*,*,*,議論,ギロン,ギロン']
['を', '助詞,格助詞,一般,*,*,*,を,ヲ,ヲ']
['保存', '名詞,サ変接続,*,*,*,*,保存,ホゾン,ホゾン']
['し', '動詞,自立,*,*,サ変・スル,連用形,する,シ,シ']
['た', '助動詞,*,*,*,特殊・タ,基本形,た,タ,タ']
['もの', '名詞,非自立,一般,*,*,*,もの,モノ,モノ']
我替换了str_文本文件中出现的所有“\n”,因此这不是问题所在。字符串不能通过一个字符传递到标记器/标记器中,因为它根据长字符串确定str是单词。它对前100万个字符有效,但在10万个字符时失败,这一事实告诉我,这可能是一千万次中的一次。我已经寻找了几个小时的解决方案,但找不到任何有助于解决这个问题的方法。我可能会将字符串分为100万个块传递,但在可能有解决方案的情况下,丢失那么多数据是错误的
任何帮助都将不胜感激
@Ivanlima先生谢谢你修改了我帖子的语法
@Karl Knechtel advise在评论中为我的问题找到了解决办法。谢谢大家!
对于那些感兴趣的人,以下是最终有效的完整代码:
%%time
#load the txt file with Japanese characters:
file = open('output_text.txt')
str_text = file.read()
#boundries for the text blocks used in the below for loop
lower = 0
upper = 100000
#dictionary for words and kanji characters
counts_words = dict()
counts_kanji = dict()
word_counter = 0
#tokenizer/tagger
tagger = MeCab.Tagger()
#splits strings into a list, used for words that have more than one character to get individual characters
def splitter(word):
return list(word)
#break condition for the loop
condition = 'no'
while True:
if condition == 'yes':
break
#this is for the last block of 100k increments
elif lower > 133400001:
#initiate break condition
condition = 'yes'
words = tagger.parse(str_text[lower:]).split('\n')[:-2]
print('Last block, chief!',lower,':',upper)
lower+=100000
upper+=100000
for word in words:
temp_str = word.split('\t')
word_counter+=1
counts_words[temp_str[0]+' '+temp_str[1]] = counts_words.get(temp_str[0]+' '+temp_str[1], 0) + 1
if len(temp_str[0])>1:
for i in splitter(temp_str[0]):
counts_kanji[i] = counts_kanji.get(i, 0) + 1
break
else:
counts_kanji[temp_str[0]] = counts_kanji.get(temp_str[0], 0) + 1
break
else:
#pass string 100k long string block into a tokenizer/tagger
words = tagger.parse(str_text[lower:upper]).split('\n')[:-2]
#increment the lower and upper boundries of the str blocks
lower+=100000
upper+=100000
#iterate through each word parsed by the tokenizer
for word in words:
temp_str = word.split('\t') #split each word data by tab, [word, info]
word_counter+=1 #count number of words
#check if the entry exists in the words dict, either add or increment the counts
counts_words[temp_str[0]+' '+temp_str[1]] = counts_words.get(temp_str[0]+' '+temp_str[1], 0) + 1
#check if the word has more than one character, if yes split it and add each character to the kanji dict
if len(temp_str[0])>1:
for i in splitter(temp_str[0]):
#check if the entry exists in the words dict, either add or increment the counts
counts_kanji[i] = counts_kanji.get(i, 0) + 1
else:
counts_kanji[temp_str[0]] = counts_kanji.get(temp_str[0], 0) + 1
输出:
Last block, chief! 133500000 : 133600000
CPU times: user 3min 7s, sys: 2.83 s, total: 3min 10s
Wall time: 3min 10s
我是mecab-python3的开发者
我想你可能已经就此给我发了邮件,但请不要传递MeCab 1M字符串。它是在假设输入是一个句子的情况下发展起来的。它很健壮,并且可以处理更长的字符串——例如,你在处理段落时不会遇到问题——但你基本上是在毫无益处地进入未经测试的领域
在将输入文本传递给MeCab之前,将其拆分为段落或句子
此外,关于这一点:
传递较短的字符串不会丢失任何数据。我不知道你指的是什么
相关问题 更多 >
编程相关推荐