Предыстория


Для импорта слов в Lingualeo.com есть несколько решений:

  • Приложения для браузера или телефонов:
  • Добавление слов на сайте.

Минусы этих способов в том, что вносить слова можно только по одному. Нам необходима реализация, которая позволит добавлять несколько слов за раз.

Должно же быть API?


Официального api найти не удалось. НО! Есть расширения для браузера, а это отличный способ найти внутренний api для сервиса.
Заходим в Google Chrome и топаем на сайт сервиса. Внизу страницы предлагаются приложения и расширения. Выбираем для Chrome. Браузер устанавливает расширение в папку Extensions (полный путь не указываю, зависит от OS). Внутри директории будет несколько папок с хешами в виде названий. Выбираем последнюю по дате. Внутри можно найти файл config.js — в нем и хранятся все пути к API проекта. Нас интересуют только три из них:

  • /api/login
  • /gettranslates
  • /addword

На чем писать?


Выбрал python, т.к. устанавливается по умолчанию на большинство OS. Модули берем те, которые не требуют дополнительной установки. Реализуем решение для работы с api.

service.py
import urllib
import urllib2
import json
from cookielib import CookieJar


class Lingualeo:
    def __init__(self, email, password):
        self.email = email
        self.password = password
        self.cj = CookieJar()

    def auth(self):
        url = "http://api.lingualeo.com/api/login"
        values = {
            "email": self.email,
            "password": self.password
        }

        return self.get_content(url, values)

    def add_word(self, word, tword, context):
        url = "http://api.lingualeo.com/addword"
        values = {
            "word": word,
            "tword": tword,
            "context": context,
        }
        self.get_content(url, values)

    def get_translates(self, word):
        url = "http://api.lingualeo.com/gettranslates?word=" + urllib.quote_plus(word)

        try:
            result = self.get_content(url, {})
            translate = result["translate"][0]
            return {
                "is_exist": translate["is_user"],
                "word": word,
                "tword": translate["value"].encode("utf-8")
            }
        except Exception as e:
            return e.message

    def get_content(self, url, values):
        data = urllib.urlencode(values)

        opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cj))
        req = opener.open(url, data)

        return json.loads(req.read())


Изначальное решение было только для текстовых файлов. Каждое слово должно быть на новой строке. Но в процессе написания кода, решил добавить реализацию для Kindle, т.к. переодически с него тоже необходимо забирать слова.

handler.py
class Word:
    text = '';
    context = '';

    def __init__(self, text):
        self.text = text

class Base(object):
    data = []

    def __init__(self, source):
        self.source = source

    def get(self):
        return self.data

    def read(self):
        raise NotImplementedError('Not implemented yet')


class Kindle(Base):
    def read(self):
        conn = sqlite3.connect(self.source)
        sql = 'select word, usage from words LEFT JOIN LOOKUPS ON words.id = LOOKUPS.word_key where words.lang="en" GROUP BY word ORDER BY word;'
        for row in conn.execute(sql):
            if isinstance(row[0], unicode):
                word = Word(row[0])
                if isinstance(row[1], unicode):
                    word.context = row[1]
                self.data.append(word)
        conn.close()


class Text(Base):
    def read(self):
        f = open(self.source)
        for word in f.readlines():
            self.data.append(Word(word))
        f.close()


И реализация самого скрипта для экспорта/импорта слов:

export.py
import handler
import config
import service
import sys

email = config.auth.get('email')
password = config.auth.get('password')

export_type = sys.argv[1]

if export_type == 'text':
    word_handler = handler.Text(config.sources.get('text'))
elif export_type == 'kindle':
    word_handler = handler.Kindle(config.sources.get('kindle'))
else:
    raise Exception('unsupported type')

word_handler.read()

lingualeo = service.Lingualeo(email, password)
lingualeo.auth()

for word_dto in word_handler.get():
    word = word_dto.text.lower().encode('utf-8')
    translate = lingualeo.get_translates(word)

    if translate["is_exist"]:
        print "Already exists: " + word.strip()
    else:
        context = word_dto.context.encode('utf-8')
        lingualeo.add_word(word, translate["tword"], context)
        print "Add word: " + word.strip()


Запуск и установка


Скачиваем код с github. Создаем файл config.py из config.py.dist. Прописываем путь до файла со словами. В случаем с kindle до sqlite базы внутри kindle.

python export.py text #Для текстовых файлов
python export.py kindle #Для kindle

Исходники


GitHub: lingualeo.export.

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


  1. olen
    09.02.2016 13:30

    А не у кого нет наработок по экспорту из Lingualeo?
    Хочу перенести слова в Анки, т.к. в Lingualeo нет интервальных повторов.


    1. tundrawolf_kiba
      09.02.2016 14:09

      А что именно под интервальными повторами понимаете? Просто по моему пониманию — уже год как есть.


      1. olen
        09.02.2016 15:53

        Новые слова, добавленные в словарь, я учу с помощью соотвествующей тренировки. Затем, слова несколько раз повторяются в других тренировках и после этого становятся изученными.
        Я бы хотел, чтобы через некоторое время слова снова повторялись (как это сделано в Анки).


        1. tundrawolf_kiba
          09.02.2016 16:05

          Ну собственно то, что вы описали — уже год как есть у них — каждый день выбирается до 30 слов, которые стоят в очереди на повторение. С каждым правильным ответом — интервал увеличивается, с неправильным — уменьшается. Дважды неправильно ответили за одну сессию — слово отправляется обратно на изучение. Вы видимо давно не заходили на дэшборд сервиса — т.к. там эта тренировка всегда первой идет. Второй — брейншторм. Далее идут остальные тренировки, и только после них — тексты/видео. Возможно вы не в курсе — но у них есть еще новые тренировки на грамматику. Примерно такие же, как в тренажере от «Полиглот»


          1. olen
            09.02.2016 16:23

            Проблема в том, что в этой тренировке надо за 5 секунд выбрать правильный перевод из двух вариантов. Если не смотреть на предложенные варианты и попытаться вспомнить значение слова, то времени мало (для многих слов). А если смотреть, то очень легко выбрать правильный даже для тех слов, которые подзабыл.
            Брейнштормом постоянно пользуюсь для запоминания слов — действительно очень хороший способ.

            Есть еще «Словарные карточки», но если слово уже изучено, то оно туда не попадает. А если это новое слово, то я его не знаю, и надо сначала запомнить.


            1. tundrawolf_kiba
              09.02.2016 16:28

              >А если смотреть, то очень легко выбрать правильный даже для тех слов, которые подзабыл.
              Так собственно это и задача тренировки — не проверить вас, а освежить ассоциативную связку. Насколько могу судить — вполне помогает. Конечно идеальным знанием слов сложно похвастаться, но то что словарный запас поддерживается и увеличивается — это определенно, и проверенно на большом количестве текстов.


              1. olen
                09.02.2016 16:33

                А у меня как раз обратный опыт: слова считаются изученными, хотя я их уже забыл :-(