Я подумал, что иметь под рукой подобный «переводчик» было бы неплохо, и поэтому решил реализовать его на python. Всех, кого заинтересовало, прошу под кат.
Подсчет слов
При написании программы я руководствовался следующей логикой. Сначала необходимо переписать весь текст строчными буквами, убрать ненужные знаки и символы (.?! и т.д.) и подсчитать, сколько раз каждое слово встречается в тексте. Вдохновленный кодом от Google, я сделал это без малейшего труда, но полученные результаты решил записать в несколько ином виде, а именно {1: [group of words that is with frequency 1], 2: [--//-- with frequency 2], etc.}
. Это удобно, если требуется сортировка в том числе и внутри каждой группы слов, например, если мы хотим, чтобы слова шли в том же порядке, как в тексте. Итого, я хочу получить двойную сортировку: чтобы в начале шли наиболее часто встречающиеся слова, а если они встречаются с одинаковой частотой, то чтобы они были упорядочены в соответствии с исходным текстом. Эта идея получила отражение в следующем коде.
def word_count_dict(filename, dictList=de500): count = {} txt = re.sub('[,.!?":;()*]', '', open(filename, 'r').read().lower()) words = txt.split() for word in words: if not word in count: count[word] = 1 else: count[word] += 1 return {i: sorted([w for w in count if (count[w]==i and w not in dictList.values())], key=lambda x: txt.index(x)) for i in set(count.values())}
Отлично, все работает, как и хотелось, но есть подозрение, что в топе списка будут вспомогательные слова (типа the) и другие, перевод которых очевиден (например, you). Избавиться от них можно, создав специальный список наиболее употребляемых слов, чтобы при формировании словаря исключать все слова, которые находятся в этом списке. Почему это еще удобно? Потому что, выучив нужное слово, мы можем добавить его в список, и соответствующий перевод больше не будет показан. Обозначим список переменной dictList и забудем о нем на некоторое время.
Перевод слов
Потратив несколько минут на поиски удобного онлайн-переводчика, решено было проверить в действии Google и Yandex. Так как ровно 3 года и 1 день назад Google закрыл Translate API, то будем использовать обходной вариант, предложенный WNeZRoS. В ответе на запрос того или иного слова Google предлагает перевод, альтернативные варианты перевода и их обратный перевод (то есть, синонимы). Использование Yandex’a как обычно требует получения ключа, и в ответе на запрос можно найти не только перевод, но и примеры, и наверное, еще что-то. В обоих случаях ответ будет содержать список в формате json, довольно простой у Google, и несколько усложненный у Yandex. По этой причине, а также потому, что Google знает больше языков (и зачастую слов), решено было остановиться именно на нем.
Запросы будем отправлять с помощью замечательной библиотеки grab, а ответы записывать во вспомогательный текстовый файл (dict.txt). В нем попробуем найти основной перевод, альтернативные варианты и синонимы, и если они есть, напечатать их. Сделаем так, чтобы последние две опции можно было отключить. Соответствующий код будет выглядеть следующим образом.
def tranlsate(word, key, lan1='de', lan2='ru', alt=True, syn=True): g = Grab(log_file = 'dict.txt') link = 'http://translate.google.ru/translate_a/t?client=x&text='\ + word + '&sl=' + lan1 + '&tl=' + lan2 g.go(link) data = json.load(open('dict.txt')) translation, noun, alternatives, synonims = 0, 0, 0, 0 try: translation = data[u'sentences'][0][u'trans'] noun = data[u'dict'][0][u'pos'] alternatives = data['dict'][0]['terms'] synonims = data['dict'][0]['entry'][0]['reverse_translation'] except: pass if lan1=='de' and noun==u'имя существительное': word = word.title() if translation: print ('['+str(key)+']', word, ': ', translation) if alt and alternatives: [print (i, end=', ') for i in alternatives] print ('\r') if syn and synonims: [print (i.encode('cp866', errors='replace'), end=', ') for i in synonims] print ('\n')
Как можно заметить, дефолтный перевод настроен с немецкого на русский. Переменная key соответствует частоте слова в тексте. Ее будем передавать из другой функции, которая и будет вызывать перевод для каждого слова.
Вызов функции перевода
Здесь все просто: я хочу получить группы слов с соответствующей частотой в виде словаря (функция word_count_dict) и найти перевод каждого слова (функция tranlsate). Также я хочу, чтобы были показаны только первые n групп наиболее употребляемых слов.
def print_top(filename, n=100): mydict = word_count_dict(filename) mydict_keys = sorted(mydict, reverse=True)[0:n] [[tranlsate(word, key) for word in mydict[key]] for key in mydict_keys]
Список наиболее употребляемых слов
Отлично, программа практически готова, осталось только составить список наиболее употребляемых слов. Их легко найти в интернете, и я составил список 50, 100 и 500 наиболее употребляемых слов в немецком языке и записал его в отдельный файл, чтобы не засорять код.
Если кто-то захочет составить подобный список в английском или другом языке, я буду благодарен, если он или она поделится им, чтобы я мог добавить его в свой.
Предварительные результаты
Запустив программу, можно получить результаты приблизительно в следующем виде:
[частота повторения слова] слово: перевод альтернативный перевод, синонимы
Хорошо, код написан, программа работает, однако насколько это удобно и эффективно? Чтобы попытаться ответить на этот вопрос, я взял пару текстов на немецком языке для проверки.
Первая статья из Deutsche Welle посвящена теме финансирования добычи угля Deutsche Bank рядом с Австралией. Статья содержит 498 слов, из которых 15 наиболее часто встречаемых в тексте (воспользуемся списком 50 наиболее употребляемых немецких слов для исключения) соответствуют 16.87% всего текста. Грубо говоря, это означает, что если предположить, что человек не знает этих слов, то после прочтения перевода 6.67% всех слов, встречающихся в тексте, его уровень понимания увеличится почти на 17% (если измерять уровень понимания только количеством знакомых слов в тексте). На первый взгляд довольно неплохо.
Вторая статья из Spiegel рассказывает о том, как немецкий биржевой индекс DAX отреагировал на победу Порошенко в выборах президента на Украине (да-да, он вырос). Статья содержит 252 слова, из которых 8 наиболее встречаемых (6.06%) аналогично соответствуют 11.9% текста.
Кроме того, следует заметить, что если переводимый текст достаточно короткий, чтобы каждое слово встречалось только один раз (например, сообщение, полученное по электронной почте), то следовать предложенному переводу в том же порядке, как слова идут в тексте, весьма удобно.
Звучит красиво (es klingt schön), однако это очень грубые тесты, поскольку я ввел слишком много предпосылок. Думаю, что проверить, насколько эта идея может облегчить работу с текстами на иностранном языке, возможно лишь при некотором регулярном использовании этой программы, что, к сожалению, пока не очень удобно. Для того чтобы перевести текст нужно скопировать его сначала в .txt файл и присвоить имя файла переменной filename, а затем запустить функцию print_top.
Чего не хватает?
Вместо заключения хотелось бы поразмышлять, чего не хватает на данном этапе, и как это можно было бы улучшить.
Во-первых, как только что было сказано, удобства. Код использовать неудобно — нужно копировать текст, + зависимость от python и библиотеки grab. Что делать? Как вариант, написать расширение для браузера, чтобы можно было выбирать определенный элемент на странице (например, аналогично тому, как это реализовано в Reedy) и получать его перевод. Во-вторых, списка слов для исключения наиболее употребляемых на других языках. Наконец, возможны различные косяки с кодировками.
Скорее всего, в ближайшее время мои руки не дойдут до внесения вышеописанных изменений (так как код написан, пора приступать к более глубокому изучению языка!), поэтому если кто-то захочет присоединиться, я буду рад компании и помощи.
Весь код целиком можно найти под спойлером, а также на github.
# -*- coding: utf-8-sig -*- from __future__ import print_function import re import json from pprint import pprint from grab import Grab from dictDe import * def tranlsate(word, key, lan1='de', lan2='ru', alt=True, syn=True): """Prints the number of counts, word, translation, and example from lan1 to lan2 according to Translate.Google.""" # First, write down a translation in some auxiliary txt file # and load it in json format g = Grab(log_file = 'dict.txt') link = 'http://translate.google.ru/translate_a/t?client=x&text='\ + word + '&sl=' + lan1 + '&tl=' + lan2 g.go(link) data = json.load(open('dict.txt')) # Then, let's try to get all the necessary elements in json translation, noun, alternatives, synonims = 0, 0, 0, 0 try: translation = data[u'sentences'][0][u'trans'] noun = data[u'dict'][0][u'pos'] alternatives = data['dict'][0]['terms'] synonims = data['dict'][0]['entry'][0]['reverse_translation'] except: pass # German nouns should begin with capital letter if lan1=='de' and noun==u'имя существительное': word = word.title() # Finally, print out counts, word, translation with alternatives # and synonims, if applicable. Encoding is added up to allow # printing in cmd if you have a russian version of Windows if translation: print ('['+str(key)+']', word, ': ', translation) if alt and alternatives: [print (i, end=', ') for i in alternatives] print ('\r') if syn and synonims: [print (i.encode('cp866', errors='replace'), end=', ') for i in synonims] print ('\n') def word_count_dict(filename, dictList=de50): """Returns a dictionary with key being number of counts and value being a list of words with that key. dictList is an optional argument: it is to eliminate the most common words. Default is the dictionary of the 50 most common German words""" count = {} txt = open(filename, 'r').read().lower() txt = re.sub('[,.!?":;()*]', '', txt) words = txt.split() for word in words: if not word in count: count[word] = 1 else: count[word] += 1 return {i: sorted([w for w in count if (count[w]==i and w not in dictList.values())], key=lambda x: txt.index(x)) for i in set(count.values())} def print_top(filename, n=100): """Generates the top count groups for the given file. Default number equals 10. Drop reverse if you want to print the less frequent words in the text.""" mydict = word_count_dict(filename) mydict_keys = sorted(mydict, reverse=True)[0:n] [[tranlsate(word, key) for word in mydict[key]] for key in mydict_keys] filename = 'dictext.txt' print (print_top(filename))
ссылка на оригинал статьи http://habrahabr.ru/post/224301/
Добавить комментарий