Пользователь
0,0
рейтинг
27 мая 2014 в 22:03

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

По жизни или по работе иногда приходится сталкиваться с текстами на иностранном языке, знания которого еще далеки от совершенства. Чтобы прочесть и понять, о чем идет речь (и, в лучшем случае, выучить несколько новых слов), я обычно использовал два варианта. Первый — это перевод текста в браузере, второй — перевод каждого слова по отдельности с помощью, например, 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))

Alexander Malayrev @Alex118
карма
5,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (14)

  • +3
    Интересно. Можно перед прочтением статьи запускать такую программу и просматривать новые слова, которые после заносятся в базу и больше не показываются. Таким образом через некоторое время большинство слов окажутся в базе и можно будет перед прочтением статьи проверять её на наличие новых слов… Правда нужно ли это? Я, например, использую расширение LinguaLeo для Chrome — выполняет ту же функцию, только слова в изучение отправляются по двойному щелчку + щелчок, а перевод показывается просто по двойному щелчку. Очень удобно. Правда, пока языков не очень много — а расширение, возможно, и вовсе только для английского.
  • НЛО прилетело и опубликовало эту надпись здесь
    • +3
      А пользователям OS X повезло ещё больше, system-wide.

      image

      Вообще говоря, полезнее всего узнавать не перевод, а именно толкование иными словами. Заметил огромный бонус к запоминанию слов, значение которых получено именно таким образом.
    • 0
      Для линукса использую горячие клавишы (глобальные) и вот такой скрипт:
      #!/bin/bash
      
      selection=$(xsel -o | sed 's/\.$//g' | sed 's/\,$//g' | sed 's/\:$//g')
      #notify-send "Process: "$selection;
      case $1 in
        g) xdg-open https://www.google.com/?q="$selection";;
        y) xdg-open http://yandex.ru/yandsearch?text="$selection";;
        t) xdg-open http://www.lingvo-online.ru/ru/Translate/en-ru/"$selection";;
        w) xdg-open http://en.wikipedia.org/wiki/"$selection";;
        p) xdg-open http://ru2.php.net/manual-lookup.php?pattern="$selection";;
        u) google-chrome "$selection";;
        o) opera "$selection";;
      esac
      

      Соответственно, при нажатии ALT + T открывается онайлн словарь Лингво с переводом выделенного слова.

      • 0
        Все-таки дело не совсем в простом переводе выделенного слова, тренингах и фрикадельках (LinguaLeo знает, о чем речь). Основная идея была в том, чтобы добиться максимального понимания текста за минимальное время. Поэтому был реализован подсчет слов — чтобы запомнить эти слова в первую очередь. И именно поэтому я хотел, чтобы выводился перевод всех слов сразу в том же порядке, что и в тексте, т.к. щелканье по каждому слову потребовало бы некоторого дополнительного времени. К тому же, это удобно и тем, что я могу посмотреть перевод определенного слова/группы слов до того, как я встречу его/их в тексте.

        Естественно, если вы владеете языком на неплохом уровне, полезность от этой программы навряд ли выше обычного переводчика. Но поэтому я и не пользуюсь ей для английского. Как я постарался показать в тестах, максимальная предельная полезность именно на начальных этапах изучения языка — когда прочтение 6% слов соответствует пониманию 12-17% текста. Попробуйте, например, скопировать какую-нибудь статью из Mercure de France (если вы не владеете французским) и сравнить, что удобней — плагин или эта программа.

        В этом и есть отличие, и поэтому эта программа удобней в некоторых аспектах. Хотя безусловно, разумно использовать все подручные средства — и переводчики, и плагины, и все остальное.
        • 0
          В свое время писала скрипт, который парсит сабы к сериалам/фильмам, очень полезно до просмотра пробежаться по незнакомым словам и по тексту, чтобы посмотреть контекст для новых слов и смотреть уже без сабов, только слушая.
          Озвученную ниже идею про словоформы надо бы добавить =)
  • +2
    При подсчете слов в тексте, хорошо бы еще приводить их к начальной форме. Что в списке не было одновременно слов дерево, деревья, деревьев и т.д (если мы парсим русский текст).
    • 0
      Точно! По идее, более менее универсальным решением был бы подсчет количества «основ» (например, слова без последних двух букв, если слово длиннее каких-нибудь 4 знаков). Спасибо, обязательно добавлю эту идею в код. Возможно, есть какое-нибудь готовое решение, но скорее всего оно зависит от языка.
  • +3
    Использую для перевода неизвестных слов/фраз/предложений плагин к firefox Quick Translator. Всё, что нужно — это выделить требуемую фразу.
    P.S. Плагин использует переводчик от гугла.
  • +1
    Есть еще бесплатная программа QTranslate, которая позволяет переводить любые выделенные слова и не только в браузере. При чтении pdf очень помогает. Правда она только для Win
    • +1
      А под линукс (и не только) есть замечательный Litetran
  • +1
    Кстати, ваша идея про очистку от ненужных слов в задаче кластеризации имеет свое решение — TF-IDF
    Сам занимаюсь компьютерным анализом русскоязычных текстов. Данная мера позволяет легко от подобного мусора избавиться. Вкратце, можно отсеивать слова, которые встречаются реже всего (вероятнее всего являются ошибкой или очень специфичным словом, например, ссылка, адрес почты, число и тд) и слова, которые есть практически везде (the, is, a, be ....).
    В моих задачах это нужно, чтобы у кластера в образующих элементах не попадалось этого мусора и не образовывался слишком огромный, обобщенный кластер. У вас я думаю можно проделать то же самое.
    • 0
      А вот это очень круто! Спасибо за подсказку, думаю, это несложно будет сделать, т.к. есть готовые библиотеки на python.
  • 0
    >> Избавиться от них можно, создав специальный список наиболее употребляемых слов, чтобы при формировании словаря исключать все слова, которые находятся в этом списке.

    Всё уже написано до нас xgu.ru/wiki/new-words

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.