Exemplo n.º 1
0
	def __init__(self, storage):
		os.environ['RML'] = AOT_DIR                 # нужно бинарникам АОТ для работы. Они тупые.
		self.morpher = Morpher()
		self.log = LOG_PATH
		self.log_strings = []
		self.rgramtab = Rgramtab()
		self.sentence_devider = SentenceDevider(AOT_DIR)
		self.storage = storage
Exemplo n.º 2
0
class Analyzer():
	''' Анализатор тональности текста '''

	def __init__(self, storage):
		os.environ['RML'] = AOT_DIR                 # нужно бинарникам АОТ для работы. Они тупые.
		self.morpher = Morpher()
		self.log = LOG_PATH
		self.log_strings = []
		self.rgramtab = Rgramtab()
		self.sentence_devider = SentenceDevider(AOT_DIR)
		self.storage = storage

	def ClearLog(self):
		self.log_strings = []

	def FlushLog(self):
		output = codecs.open(self.log, 'w', 'utf-8')
		output.writelines(self.log_strings)
		output.close()

	def WriteLog(self, info, msg=None):
		self.log_strings.append(unicode(info) + u'\n')
		if msg:
			self.log_strings.append(unicode(msg) + u'\n\n')

	def GetSentences(self, text):
		return self.sentence_devider.enumerate_sentences(unicode(text))

	def GetParagraphs(self, text, sentences):
		result = []

		for i,j in sentences:
			last_index = text.rfind(sentences[i])
			begin_index = text.rfind(sentences[i+1])
			paragraph_str = text[last_index:begin_index]
			result.append(paragraph_str)

		return result

	def Analyze(self, text):
		# очищаем лог
		self.ClearLog()
		self.WriteLog(u"Исходный текст:", text)

		sentences = self.GetSentences(text)
		render_text = []

		text_tone = 0
		total_word_count = 0
		for s in sentences:
			render_sentence, sentence_tone, word_count = self.AnalyzeSentence(s)
			total_word_count += word_count
			text_tone += sentence_tone
			render_text.append(render_sentence)

		html = self.RenderTextToHtml(render_text)

		# записываем изменения в лог-файл
		#self.WriteLog(u"Полученный текст:", html)
		text_tone /= total_word_count
		html += self.GetTotalRenderText(text_tone)
		self.FlushLog()
		return html, text_tone

	def GetTotalRenderText(self, text_tone):
		if text_tone > 0:
			result = u"<br><br><good>Текст окрашен положительно. Значение тональности: " + unicode(text_tone) + u"</good>"
		else:
			result = u"<br><br><bad>Текст окрашен отрицательно. Значение тональности: " + unicode(text_tone) + u"</bad>"
		return result

	def RenderTextToHtml(self, render_text):
		result = u''

		for sentence in render_text:
			for word in sentence:
				if self.CheckToBePunctuationMark(word):
					result = result[:len(result)-1]
				result  = result + word + u' '
		return result

	def CheckToBePunctuationMark(self, word):
		result = False
		if re.match("[.,!?:]", word):
			result = True
		return result

	def AnalyzeSentence(self, sentence):
		''' Анализ предложения на тональность '''
		self.WriteLog(u"==============================================\nТекущее предложение:", sentence)
		words = unicode(sentence).split(' ')
		word_count = len(words)

		render_sentence = []
		# список юникодных слов
		self.WriteLog(u"===== Первичная расстановка тональностей =====")
		tonal_words = self.GetPrimaryTonalWeights(words)

		# tonal_words содержит (слово, тональность)
		# анализируем слова с тональностью <>0

		# TODO: работа с тональностями! коррекция тональности
		self.WriteLog(u"===== Расстановка тональностей внутри предложения =====")
		tonal_words = self.Reanalyze(tonal_words)


		# печать
		sentence_tone = 0
		for w in tonal_words:
			if w[3] == 0:
				sentence_tone += w[1]
			render_word = self.GetRenderWord(w)
			render_sentence.append(render_word)
		return render_sentence, sentence_tone, word_count

	def Reanalyze(self, tonal_words):
		''' Реализация основного алгоритма '''
		i = len(tonal_words) - 1
		while i > 0:    #for i in range(len(tonal_words), 0, -1):
			# ищем слово из словаря тональностей
			if tonal_words[i][3] == None or tonal_words[i][3] > 0:
				i-=1
				continue
			self.WriteLog(u"Текущее эмоционально окрашенное слово: " + tonal_words[i][0])
			# нашли эмоционально окрашенное слово
			# пойдем вперед и посмотрим на слова
			correcting_value = 0
			need_to_invert = False
			k = 0 # сколько обработали слов
			for j in range(i-1, -1, -1):
				if not tonal_words[j][3]:   # если слово из обычного словаря
					break
				k += 1

				# находится ли в словаре повышения тональности?
				if tonal_words[j][3] == 1:
					correcting_value += tonal_words[j][1]
					if not tonal_words[j][1]:
					# надо инвертировать
						need_to_invert = not need_to_invert
						self.WriteLog(u"-" + unicode(k) + u": слово \'" + tonal_words[j][0] + u"\' инверитрует тональность!")
					else:
						self.WriteLog(u"-" + unicode(k) + u": слово \'" + tonal_words[j][0] + u"\' изменяет тональность на " + unicode(tonal_words[j][1]))

			result_tone_value = tonal_words[i][1] + correcting_value
			if need_to_invert:
				result_tone_value *= -1
			# присвоим всему обороту полученную окраску
			for j in range(i-k, i):
				tonal_words[j] = tonal_words[j][0], tonal_words[j][1], tonal_words[j][2], 3 # словарь = 3 - для того чтобы отличить слова повышения
			tonal_words[i] = tonal_words[i][0], result_tone_value, tonal_words[i][2], tonal_words[i][3]
			if k:
				i -= k
			else:
				i -= 1
		return tonal_words

	def GetRenderWord(self, tonal_word):
		'''  '''
		unicode_word, tone_value, norm_form, dict_numb = tonal_word
		render_word = self.GetWordToRender(unicode_word, tone_value, dict_numb)
		return render_word

	def GetPrimaryTonalWeights(self, unicode_words):
		''' Получить словарь слово, тональность '''
		result = []
		for w in unicode_words:
			result.append(self.AnalyzeWord(w))
		return result

	def AnalyzeWord(self, unicode_word):
		''' Анализ слова. Возвращаем (слово(норм), тональность). Если нет норм формы то (слово(юникод), 0) '''
		# проверка на знак пунктуации
		if re.match("[-\n.,!?:]", unicode_word):
			return unicode_word, 0, None, None

		# проверка на суффиксы и тд
		pre_tone_value = self.AnalyzeWordSuffix(unicode_word)
		result = None

		word_normform = self.GetWordNormForm(unicode_word)

		# структуру WordWrapper можно анализировать на часть речи и тд
		if word_normform:
			search_word = word_normform.GetNormForm()
		else:
			#self.WriteLog(u"Слово не имеет нормальной формы: " + unicode_word, "")
			search_word = unicode_word

		#if word_normform:
		tone_value, dict_numb = self.GetWordToneValue(unicode_word, search_word)
		if not tone_value:
			tone_value += pre_tone_value
		result = (unicode_word, tone_value, word_normform, dict_numb)
		self.WriteLog(u"Слово: " + unicode_word +  u';\nНормальная форма: ' + unicode(word_normform) + u";\nСловарь: " + unicode(dict_numb) +
					  u';\nТональность: '+ unicode(tone_value) + u";\n")
		#else:
		#    self.WriteLog(u"Слово не имеет нормальной формы: ", unicode_word)
		#    result = (unicode_word, pre_tone_value, None, None)
		return result

	def AnalyzeWordSuffix(self, unicode_word):
		''' Анализ слова на наличие суффиксов -еньк, -оньк, '''
		pre_tone_value = 0
		suffix = [u"еньк", u"оньк", u"чик", u"ошк", u"ушк", u"ышк", u"юшк"]
		for s in suffix:
			if re.search(s, unicode_word, re.IGNORECASE):
				pre_tone_value += 0.1

		return pre_tone_value

	def SelectMostPossibleWord(self, word_forms):
		''' Выбираем из форм слова наиболее возможную '''
		result = None
		max_weight = -1 # все значения положительные
		for w in word_forms:
			cur_weight = w.GetWordWeight()
			if w.GetWordWeight() > max_weight:
				max_weight = cur_weight
				result = w

		return result

	def GetWordToRender(self, word, tone_value, dict_numb):
		''' Получение слова для отображения '''
		if not tone_value or dict_numb == 1: # если не установлено значение тональности либо слово из повышающего словаря
			return word

		tag = u''
		if dict_numb == 3:
			tag = u"changing"
			#word = u"<changing>" + word + u"(" + unicode(tone_value) + u")" + u"</changing>"
		else:
			if tone_value > 0:
				#word = u'<good>' + word + u"(" + unicode(tone_value) + u")" + u'</good>'
				tag = u"good"
			else:
				#word = u'<bad>' + word + u"(" + unicode(tone_value) + u")" + u'</bad>'
				tag = u"bad"
		word = u"<" + tag + u">" + word + u"(" + unicode(tone_value) + u")" + u"</" + tag + u">"
		return word

	def GetWordNormForm(self, unicode_word):
		word_forms = self.morpher.GetWordForms(unicode_word)
		result_word = self.SelectMostPossibleWord(word_forms)
		return result_word

	def GetWordToneValue(self, unicode_word, norm_form):
		''' Проверка на наличие слова в тональном словаре. Возвращение значения тональности в случае успеха '''
		result, dict_numb = self.storage.GetWordToneValue(unicode_word, norm_form.lower())
		if result == None:
			result = 0
			dict_numb = None
		return result, dict_numb