google translate script

    Всем привет. Все что изложено ниже — мой первый реально полезный (во всяком случае для меня) опыт использования питона. Буду благодарен если подскажете как улучшить/оптимизировать скрипт.



    С давних времен был у меня скриптик на баше которые переводил через гугл транслэйт все что ему кормишь
    translate 'test' en ru

    Мне захотелось чтоб он еще выдавал возможные альтернативы, как гугл недавно научился. Заодно решил устроить себе питон практику :)


    Вот что получилось:
    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    """This script allow users to translate a string
    from one language to another with Google translate"
    ""

    import sys
    import re
    import urllib
    import urllib2
    import json

    def print_params(data):
      """print parameters from list"""
      for val in data:
        if isinstance(val, basestring):
          print "\t " + val

    def main():
      """
      Usage:
        first arg - string to translate
        second arg - source lang
        third arg - target lang  
      Example:
        translate.py 'text to translate' en ru
        translate.py 'text to translate' ru en
      "
    ""
      
      url = "http://translate.google.com/translate_a/t?%s"
      list_of_params = {'client' : 't'
                        'hl' : 'en',
                        'multires' : '1', }  
      
      #all arguments given
      if len(sys.argv) == 4:
        list_of_params.update({'text' : sys.argv[1],
                               'sl' : sys.argv[2],
                               'tl' : sys.argv[3] })

        request = urllib2.Request(url % urllib.urlencode(list_of_params),
          headers={ 'User-Agent': 'Mozilla/5.0', 'Accept-Charset': 'utf-8' })
        res = urllib2.urlopen(request).read()

        fixed_json = re.sub(r',{2,}', ',', res).replace(',]', ']')  
        data = json.loads(fixed_json)
        
        #simple translation
        print "%s / %s / %s" % (data[0][0][0], data[0][0][1],
                    data[0][0][2] or data[0][0][3])
        
        #abbreviation
        if not isinstance(data[1], basestring):
          print data[1][0][0]
          print_params(data[1][0][1])
          
        #interjection  
        try:
          if not isinstance(data[1][1], basestring):
            print data[1][1][0]
            print_params(data[1][1][1])
        except Exception:
          print "no interjection"
      else:
        print main.__doc__
        
    if __name__ == '__main__':
      main()


    * This source code was highlighted with Source Code Highlighter.


    Скачать скрипт

    P.S.
    Спасибо за конструктивные комментарии. Обновил код и файл.
    Выдавал ошибку если фраза была типа how are you? # fixed

    P.P.S
    Спасибо всем за положительные отзывы и конструктивную критику.
    По заявкам написал еще один вариант скрипта, который переводит через гугл API v2. К сожалению API не предлагает несколько значений одного слова. Возможно в будущем эту функцию добавят.

    Для использования 2й версии скрипта нужно получить API key по ссылке code.google.com/apis/console/?api=translate и заменить в скрипте ***** на ваш ключ.

    Вот собственно сам скрипт:

    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    """This script allow users to translate a string
    from one language to another with Google Translate API
    You have to insert Your Translate API key
    Get your API key from here:
      code.google.com/apis/console/?api=translate
    Replace
      api_key = '**********' with your API key
    "
    ""

    import sys
    import urllib
    import urllib2
    import json

    def translate(list_of_params):
      """Translate given text"""    
      url = "https://www.googleapis.com/language/translate/v2?%s"    
      request = urllib2.Request(url % urllib.urlencode(list_of_params),
        headers={ 'User-Agent': 'Mozilla/5.0', 'Accept-Charset': 'utf-8' })
      res = urllib2.urlopen(request).read()
      translated = json.loads(res)
      for translations in translated['data']['translations']:          print translations['translatedText']  

    def main():
      """
      Usage:
        first arg - string to translate
        second arg - source lang
        third arg - target lang  
      Example:
        translate.py 'text to translate' en ru
        translate.py 'text to translate' ru en
        translate.py 'auto detect source language' ru
      "
    ""
      api_key = '**********'
      list_of_params = {'key' : api_key, }  
      
      if len(sys.argv) == 4:
        #both langs entered
        list_of_params.update({'q' : sys.argv[1],
                    'source' : sys.argv[2],
                    'target' : sys.argv[3] })
        translate(list_of_params)
      elif len(sys.argv) == 3:
        #auto source language
        list_of_params.update({'q' : sys.argv[1],
                    'target' : sys.argv[2] })
        translate(list_of_params)    
      else:
        print main.__doc__
        
    if __name__ == '__main__':
      main()

    * This source code was highlighted with Source Code Highlighter.


    Скачать скрипт

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 38

      +2
      def isstr(val):
          return str(data[1]) == data[1]

      А куда val дели? :)

      #if all arguments was typed

      ну и остальные комментарии

      — и заодно поставьте себе pep8 и PyLint

        0
        о-ё-ёй, спасибо, вот так ошибка, просмотрел (:
          +3
          А если нажимать на кнопку «ответить», а не сразу писать в окошко снизу, то можно избежать конфузов с ответом на свою-же статью, вместо комментария :)
            0
            Да я знаю, просто комент был всего один, я поторопился и думал что ответить уже нажата, т.к. текстария была снизу (:
          +4
          PEP 8 (Style Guide for Python Code):

          Indentation

          Use 4 spaces per indentation level.

          For really old code that you don't want to mess up, you can continue to
          use 8-space tabs.

          Maximum Line Length

          Limit all lines to a maximum of 79 characters.
            +2
            «Канонические» способы проверить тип в питоне:
            type(x) is str
            isinstance(x, str)

            Причём второй метод проверит принадлежность объекта не только к самому классу, но и к inherited классам.
              0
              Пожалуйста, прочтите любую хорошую книгу по питону

              Pythonic programming style that determines an object's type by inspection of its method or attribute signature rather than by explicit relationship to some type object («If it looks like a duck and quacks like a duck, it must be a duck.») By emphasizing interfaces rather than specific types, well-designed code improves its flexibility by allowing polymorphic substitution. Duck-typing avoids tests using type() or isinstance(). Instead, it typically employs the EAFP (Easier to Ask Forgiveness than Permission) style of programming.
                +1
                Конечно, «лучший способ проверить тип в питоне — не проверять тип». Но в топике автор если и использует подход duck typing, то довольно запутанно, простите.
                +2
                А-а-а, что я наделал, сказав автору топика про type()… Стало хуже.
                  0
                  :))))))
                    0
                    isinstance(str, basestring);
                      0
                      Я не очень понял мне ли вы ответили, но точно мог сказать, что в питоне ";" появляется только в очень кривом коде.
                        0
                        Наверное просто shift не нажал. Кстати basestring fixed (:
                          +1
                          Ну простите пожалуйста, очень важно не поставить точку с запятой в комментарии :)
                          В коде на пистоне я не ставлю, но сегодня я писал на javascript, мозг не переключился.
                            0
                            для разминки предлагаю убрать ";" в следующем коде:

                            python -c «import os; print 'Current working dir is %s' % os.getcwd()»
                              +4
                              Элементарно:

                              echo -e «import os\nprint 'Current working dir is %s' % os.getcwd()» | python

                              А вам, для разминки, предлагаю научиться различать oneliner'ы и полноценный код
                                0
                                Why So Serious?

                                Я конечно же не писал, что это невозможно, или сложно, я всего навсего клоню к тому, что фраза

                                >> точно мог сказать, что в питоне ";" появляется только в очень кривом коде

                                в некотором роде перегиб. Дети читают и повторяют такое бездумно. Ваш пример прекрасен, но я бы не стал использовать его, скажем, в инициализирующих систему shell-скриптах.

                                И я сдаюсь, представить даже не могу чем мой милый on-liner отличается от полноценного кода
                                  0
                                  Python is serious business! :)

                                  Про ";" — естественно в oneliner'ах ему самое место, а мои примеры это абстрактный конь в вакууме, который в реальной системе никто не будет использовать и написан как ответ на просьбу переписать код.

                                  Но мне казалось, что вы, прочитав мой комментарий, поймёте, что я говорил об коде который не является хаком/oneliner'ом/баше-заменителем.
                                0
                                Кстати, ничего не помешает выполнить код

                                python -c "import os
                                print 'Current working dir is %s' % os.getcwd()"

                                Например использовав Ctrl-v + Ctrl-j или копипаст из текстового редактора
                      0
                      Прекрасно информативный топик и максимально документированный код. Браво.
                        +2
                        Вы наверное красьненьким забыли покрасить.

                        Топик минусанул. И вот почему.

                        Информативность топика стремится к нулю, к тому же приведенный код является примером того, как не надо писать на питоне. Особенно если ориентирован на новичков.
                        Несоблюдение PEP8.
                        Использование исключений в таком виде:
                        try:
                        except Exception:
                            pass
                        

                        И в if засунули большой блок кода, хотя можно было поступить более красиво. Вывести справку и выйти.
                        0
                        # translate «hi» en ru

                        Я бы сделал как минимум два алиаса en2ru и ru2en, чем избавился бы от лишних ключей и от кавычек одновременно
                          0
                          сравните

                            0
                            # translate «hi» en ru

                            и

                            # en2ru hi
                            +1
                            А еще лучше, чтоб, если направление перевода не указано, то язык слова (русский или английский) автоматом определялся.
                            +5
                            Так выглядит чуть лучше, ИМХО:
                            #! /usr/bin/env python
                            # -*- coding: utf-8 -*-
                            
                            import sys
                            import re
                            import urllib
                            import urllib2
                            import json
                            
                            url = "http://translate.google.com/translate_a/t?client=t&text={0}&hl=en&sl={1}&tl={2}&multires=1"
                            
                            def printParams(data):
                                for x in data:
                                    print(u"\t{0}".format(x))
                            
                            
                            def tr(text, sourcelang, targetlang):
                                """
                                Translates given string(text) from sourcelang to targetlang
                                using Google Translate
                                """
                                request = urllib2.Request(url.format(text, sourcelang, targetlang),
                                  headers={ 'User-Agent': 'Mozilla/5.0', 'Accept-Charset': 'utf-8' })
                                response = urllib2.urlopen(request).read()
                                fixedJSON = re.sub(r',{2,}', ',', response).replace(',]', ']')
                                data = json.loads(fixedJSON)
                                result = {}
                                result["definition"] = data[0][0]
                                for row in data[1]:
                                    try:
                                        result[row[0]] = row[1]
                                    except:
                                        pass
                                return result
                            
                            
                            def main():
                                """
                                Usage:
                                first arg - string to translate
                                second arg - source lang
                                third arg - target lang
                                """
                                if len(sys.argv) == 4:
                                    text = urllib.quote(sys.argv[1])
                                    sl = sys.argv[2]
                                    tl = sys.argv[3]
                                    r = tr(text, sl, tl)
                                    print(u"{0} / {1} / {2}".format(r["definition"][0],
                                                                    r["definition"][1],
                                                                    r["definition"][2] or r["definition"][3]))
                                    del r["definition"]
                                    for key, val in r.iteritems():
                                        print(key)
                                        printParams(val)
                                else:
                                    print(main.__doc__)
                            
                            if __name__ == '__main__':
                                main()
                            
                              0
                              только printParams → print_params )
                              0
                              Чем улучшить…
                              1) использовать вместо urllib.quote urllib.urlencode() для генерации GET параметров из словаря (нагляднее, надежнее и, пожалуй, удобнее)
                              2) использовать официальный REST API code.google.com/intl/ru-RU/apis/language/translate/overview.html (хотя не понял есть ли там вывод альтернатив)
                                0
                                чуть-чуть улучшил :)
                                0
                                И еще придумал — можно сделать прием текста из stdin, чтоб можно было вызывать как
                                ./translate ru en — < ru_text.txt
                                или
                                cat ru_text.txt | ./translate ru en -
                                  0
                                  Интересная мысль, завтра после работы если силы останутся попробую реализовать :)
                                  +1
                                  Немного подправил под себя, может изменения будут интересны.
                                  @@ -11,0 +12,5 @@
                                  +# Set utf-8 for some stupid terminals
                                  +import codecs
                                  +if sys.stdout.encoding == None:
                                  +    sys.stdout = codecs.getwriter('utf8')(sys.stdout)
                                  +
                                  @@ -16 +21 @@
                                  -      print "\t " + val
                                  +      print "     " + val
                                  @@ -35,4 +40,5 @@
                                  -  if len(sys.argv) == 4:
                                  -    list_of_params.update({'text' : sys.argv[1],
                                  -                           'sl' : sys.argv[2], 
                                  -                           'tl' : sys.argv[3] })
                                  # You can run "gtrans en ru hello world" now
                                  +  if len(sys.argv) >= 4:
                                  +    list_of_params.update({'text' : " ".join(sys.argv[3:]),
                                  +                           'sl' : sys.argv[1], 
                                  +                           'tl' : sys.argv[2] })
                                    0
                                    восклицательный знак в исходном тексте режет весь дальнейший текст.

                                    translate «hi! bifidokk»
                                    привет! / hi! / privet!

                                    translate «hi bifidokk»
                                    привет bifidokk / hi bifidokk / privet bifidokk

                                      0
                                      Потому что надо писать в одинарных кавычках :) '
                                        0
                                        python translate.py 'hi! bifidokk goooooooogle' en ru

                                        аналогично, попробуйте сами
                                          0
                                          Ответ парсится неверно просто. Гугл отдает переводы по отдельным приложениям, а тут анализируется только первое. Если делать клиент для текстов с произвольным числом предложений, надо конечно же скорректировать алгоритм. Вот например для node.js вариант из моей либы:

                                                  response.on('end', function () {
                                                      data = data.replace(/,+/g, ',').replace(/,\]/g,']');
                                                      var obj = JSON.parse(data);
                                                      callback(obj[0].map(function (sentence) { return sentence[0]; }).join(''));
                                                  });
                                          
                                      +2
                                      Немного не в тему, но вот другой интересный вариант использования google translate в Linux консоли (увидел, кажется, на welinux.ru):
                                      
                                      mplayer "http://translate.google.com/translate_tts?tl=en&q=hello+world"
                                        0
                                        Ух ты! Спасибо.

                                      Only users with full accounts can post comments. Log in, please.