Работа с иностранными текстами. Как увеличить процент понимания и выучить язык?

от автора

По жизни или по работе иногда приходится сталкиваться с текстами на иностранном языке, знания которого еще далеки от совершенства. Чтобы прочесть и понять, о чем идет речь (и, в лучшем случае, выучить несколько новых слов), я обычно использовал два варианта. Первый — это перевод текста в браузере, второй — перевод каждого слова по отдельности с помощью, например, ABBYY Lingvo. Но у этих методов есть множество недостатков. Во-первых, браузер предлагает перевод предложениями, а значит, он может менять порядок слов и перевод может оказаться еще более непонятным, чем оригинальный текст. Во-вторых, браузер не предлагает ни альтернативных вариантов перевода, ни синонимов к словам, а значит, учить новые слова становится проблематично. Другие варианты и синонимы можно получить при поиске конкретного слова в переводчике, а это требует некоторого времени, особенно если таких слов много. Наконец, читая текст, мне хотелось бы знать, какие слова наиболее популярны в этом языке, чтобы я мог их запомнить и потом использовать в своей письменной или разговорной речи.

Я подумал, что иметь под рукой подобный «переводчик» было бы неплохо, и поэтому решил реализовать его на 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/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *