Подписка

Проекты

Сборник идей для разработок в Delphi и использования их в Интернет. Участвуй в работе коллективного разума!

Google API в Delphi - проект с открытым исходным кодом.


А тут я коплю на лицензию Delphi 2011. Сумма пожертвования не фиксирована.

Друзья блога

Блоги и сообщества

DelphiFeeds.ru - Все Delphi-блоги Рунета О раскрутке блога по программированию Сообщество умных людей VR-Online.RU Бесплатный журнал для программистов и всех, кто интересуется IT Статьи и уроки по Delphi Статьи по Delphi

Счётчики


Анализ веб сайтов

Рейтинг блогов




Система Orphus

  • 16Jan

    Пока собираюсь с мыслями по поводу написания одной большой статьи про использование Ribbon Controls решил между делом поразбираться с различными API.

    Но прежде, чем предоставлю модуль для работы с API, спрошу Вас вот что.

    Суть проблемы такова: есть 3 компьютера – 2 стационара и 1 ноутбук. На стационарах стоят винды XP (SP3, все обновления совпадают), на ноуте – стоит винда XP SP-2 и Ubuntu 9.10.  Стационары подключены к Интернету через одного и того же провайдера. На первом стационаре  не грузятся все страницы вида http://code.googele/… На втором стационаре от Гуглы работает только поиск.Подключаю к инету ноутбук, запускаю Windows, открываю Гугл – работает всё кроме переводчика и FeedBurner’а. Под Ubuntu – работает все.

    Вопрос: что за фигня происходит? ' '

    Пробую разобраться уже с неделю, попеременял все браузеры, какие только есть в природе, чистил кэши, куки. Пересоздавал подключение, причём не только к инету, но и менял IP-адрес для локалки, через которую выхожу в Инет. Сегодня переставил сетевуху на одном из стационаров – нихрена. На ноуте сносил винду – тоже не помогло. Такое ощущение, что в винде млять чёрная дыра в которую Гулу засасывает. Если кто в курсе в чём проблема – подскажите плз, так как очень неудобно сидеть за двумя компами и перетыкать туда-сюда сетевой кабель :)

    Ну, а теперь преступиим к главному – API Яндекс.Спеллера.

    Во-первых, следует объяснить тем, кто не в курсе, что это за API.

    Яндекс.Спеллер – это сервис проверки правописания, который помогает находить и исправлять орфографические ошибки. Работа сервиса основана на использовании орфографических словарей для трех языков – русского, украинского и английского.

    В принципе, для тех, кто большую часть времени работает в офф-лайне этот сервис особо не пригодиться. Другое дело – использовать его в своих он-лайн проектах и программах, ориентированных на работу в Сети.

    В целом, работа с API Яндекса никогда не вызывали, по крайней мере у меня, особых осложнений. В основном вся работа основывается на работе с двумя-тремя методами, у которых пара-тройка входных параметров. Самое “сложное” – это правильно разобрать ответ сервера.

    Судя по тому, что написано в документации к Яндекс.Спеллеру, для нас наиболее важно научиться использовать метод checkText.. Его мы сегодня и рассмотрим.

    Метод checkText Яндекс.Спеллера

    Метод проверяет орфографию в указанном отрывке текста. Для использования метода допустимо использовать как GET так и POST запросы. При этом размер передаваемого текста в POST-запросе не должен превышать 10000 символов.

    Чтобы лишний раз не копипастить документацию я просто приведу ссылку на описание метода.  Судя по тому, что сказано в документации, наша работа с сервисом будет состоять из двух частей:

    1. Отправка POST-запроса с текстом для проверки
    2. Получение ответа и парсинг XML.

    Для работы нам понадобиться совсем немного модулей: SysUtils, Classes,  XMLIntf,xmldom, XMLDoc;

    Ну и для отправки запросов я использовал httpsend из библиотеки synapce. Вы, если хотите, можете использовать тот же IdHTTP из Indy.

    Первое, что делаем – это объявляем все константы, которые могут потребоваться нам для работы, а именно:

    • Коды ошибок Яндекс.Спеллера
    • Константы настроек Яндекс.Спеллера
    • Ну и, чтобы вообще было хорошо – создадим несколько ресурсных строк для описания ошибок

    У меня получилось следующее:

    resourcestring
      rcERROR_TEXT_LENGTH = 'Общая длина передаваемого текста превышает 10000 символов!';
      rcERROR_UNKNOWN_WORD = 'Слова нет в словаре';
      rcERROR_REPEAT_WORD = 'Повтор слова';
      rcERROR_CAPITALIZATION = 'Неверное употребление прописных и строчных букв';
      rcERROR_TOO_MANY_ERRORS = 'Текст содержит слишком много ошибок';
     
    const
      IGNORE_UPPERCASE = 1;
      IGNORE_DIGITS = 2;
      IGNORE_URLS = 4;
      FIND_REPEAT_WORDS = 8;
      IGNORE_LATIN = 16;
      NO_SUGGEST = 32;
      FLAG_LATIN = 128;
     
      ERROR_UNKNOWN_WORD = 1;
      ERROR_REPEAT_WORD = 2;
      ERROR_CAPITALIZATION = 3;
      ERROR_TOO_MANY_ERRORS = 4;

    Теперь договоримся как будем хранить сообщения об орфографических ошибках. Чтобы все было точно как задумано в сервисе, будем хранить всю информацию об ошибке как есть. Для этого вводим новый тип данных:

    type
    TBadWord = record
      Word: string;//слово с ошибкой
      ErrCode: integer;//код ошибки
      ErrMsg : string;//описание ошибки
      Pos:integer;//позиция слова с ошибкой (отсчет от 0);
      Row:integer;//номер строки (отсчет от 0)
      Col:integer;//номер столбца (отсчет от 0);
      Len:integer;//длина слова с ошибкой
      Variants: TStringList; //варианты правильного написания
    end;

    И ещё пару типов

    type
      TBadWords = array of TBadWord;
    type
      TTextFormat = (tfPlain, tfHTML);

    Теперь мжно отправлять данные на сервер и анализировать ответ. Для этого я создал такую функцию:

    function CheckGrammar(const aText:string; Options:integer=0;lang:string='ru,en';format:TTextFormat=tfPlain):TBadWords;
     
    implementation
     
    function CheckGrammar(const aText:string; Options:integer;lang:string;format:TTextFormat):TBadWords;
    var Query: TStringStream;
      Doc: IXMLDocument;
      List,Variant: IDOMNodeList;
      i,j:integer;
    begin
    try
      Query:=TStringStream.Create('');
      Query.WriteString('text='+aText+'?='+lang+'&options='+inttostr(Options));
      case format of
        tfPlain: Query.WriteString('&format=plain&ie=1251');
        tfHTML:  Query.WriteString('&format=html&ie=1251');
      end;
      if Length(Query.DataString)>10000 then
        raise Exception.Create(rcERROR_TEXT_LENGTH);
      with THTTPSend.Create do
        begin
           Document.LoadFromStream(Query);
           MimeType:='application/x-www-form-urlencoded';
           if HTTPMethod('POST','http://speller.yandex.net/services/spellservice/checkText') then
             begin
               Doc:=NewXMLDocument();
               Doc.LoadFromStream(Document);
               List:=Doc.DOMDocument.getElementsByTagName('error');//получаем список ошибок
               SetLength(Result,List.Length);//устанавливаем длину массива
               for i:=0 to List.length-1 do
                 begin
                   //запоминаем атрибуты ошибки
                   with List.item[i] do
                     begin
                       Result[i].ErrCode:=StrToInt(attributes.getNamedItem('code').nodeValue);
                       Result[i].Pos:=StrToInt(attributes.getNamedItem('pos').nodeValue);
                       Result[i].Row:=StrToInt(attributes.getNamedItem('row').nodeValue);
                       Result[i].Col:=StrToInt(attributes.getNamedItem('col').nodeValue);
                       Result[i].Len:=StrToInt(attributes.getNamedItem('len').nodeValue);
                     end;
                    case Result[i].ErrCode of
                      ERROR_UNKNOWN_WORD:Result[i].ErrMsg:=rcERROR_UNKNOWN_WORD;
                      ERROR_REPEAT_WORD:Result[i].ErrMsg:=rcERROR_REPEAT_WORD;
                      ERROR_CAPITALIZATION:Result[i].ErrMsg:=rcERROR_CAPITALIZATION;
                      ERROR_TOO_MANY_ERRORS:Result[i].ErrMsg:=rcERROR_TOO_MANY_ERRORS;
                    end;
    //читаем дочерние элементы
                   Variant:=List.item[i].childNodes;
                   Result[i].Word:=(List.item[i].firstChild as IDOMNodeEx).text;
                   Result[i].Variants:=TStringList.Create;
                   for j:=1 to Variant.length-1 do //оставшиеся дочерние узлы - варианты
                     Result[i].Variants.Add((Variant.item[j]as IDOMNodeEx).text);
                 end;
       end;
    end;
    finally
    FreeAndNil(Query);
    end;
    end;

    Разберемся, что здсь происходит. Вначале создается тело нашего POST-запроса в зависимости от входных параметров. При этом, обратите внимание на последний необязательный параметр: ie=1251. Можно было бы обойтись и без него, но для этого необходимо переводить наш параметр aText в кодировку utf-8.

    Далее проводится проверка длины текста в теле запроса. Если длина превышает 10000 символов, то работа функции завершается, иначе переходим к следующему шагу – отправке запроса.

    MimeType:='application/x-www-form-urlencoded';

    Определяет заголовок (Headers) Content-Type. Если не использовать заголовок или использовать другое его значение – сервис вернет нам ошибку “Unrecognized Content Type … “. Отправляем запрос и анализируем XML-документ.

    Анализ как таковой проводится элементарно:

    1. Получаем список всех узлов error – размер списка и будет размером массива, который возвращает функция
    2. Далее проходим по порядку по каждому из узлов списка (цикл по i) и читаем все атрибуты попутно занося в элемент массива описание ошибки в зависимости от значения атрибута code.
    3. Получаем для каждого узла List.item[i] список дочерних узлов.
    4. Исходя из описания API первым дочерним узлом всегда является слово с ошибкой – читаем первый дочерний узел и заносим его значение в поле Word
    5. Остальные дочерние узлы (если они имеются) – это варианты правильного написания слова. Создаем цикл по j и читаем значения оставшихся узлов.

    Вот и все. Остается продемонстрировать работу функции на примере. Использовать можно, например так:

    CheckGrammar('синхрафазатрон в дубне', 5);

    При этом приверка будет проходить с использованием опций: IGNORE_UPPERCASE и IGNORE_URLS.

    Можно вызвать метод и так:

    CheckGrammar('синхрафазатрон в дубне', IGNORE_UPPERCASE+ IGNORE_URLS, 'ru');

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

    Вот пажалуй и все :) Готовый модуль, рассмотренный в этом посте + пример его использования можно скачать здесь.

    ----------------------------
    Если не знаете, что почитать - посмотрите рецензии на книги по интересующему Вас жанру или автору - так будет проще определиться с ответом на вопрос "Что почитать" ;)

    Сегодня купить паркет в Санкт-Петербург стало ещё проще - заходите на pret-a-parquet.ru, выбираете и дело в шляпе.

    Интернет - это такая большая штука где можно за минуту узнать не только какая погода в Риме сегодня, но и прочитать отзывы о Пекине, заказать путёвку и даже купить настоящую (не электронную) книгу. Что же нас ждёт в будущем? :)
    ----------------------------

    Related posts:

    1. Простейший компонент Delphi 2010 для парсинга выдачи Яндекс.
    2. Определение тИЦ Яндекс. Компонент Delphi 2010.
    3. Компонент Delphi 2010 для проверки наличия сайта в Яндекс.Каталог, DMOZ и Yahoo Directory
    4. Модуль FeedBurner API для Delphi 2010.

    Автор Vlad в 5:04 pm

    Метки: , , , ,

13 Comments

WP_Cloudy
  • Tweets that mention API Яндекс.Спеллера в Delphi. | Delphi в Internet -- Topsy.com пишет:

    [...] This post was mentioned on Twitter by progg, Vlad and ru_webdev, monitorium. monitorium said: API Яндекс.Спеллера в Delphi. | Delphi в Internet: Встраиваем он-лайн проверку орфографии в наше прилож… http://bit.ly/5v7se6 /*progg.ru [...]

  • Гимаев Наиль пишет:

    Получается, что я Вас проэкслуатировал.
    Я сам пытался решить эту задачу, залез в поисках решения на этот блог.
    Сообщил, что эта задача мне интересна.
    И вот оно решение!
    Спасибо огромное!
    У меня всего час в неделю на программирование, и узучить XML на практике не успеваю.
    Ещё раз спасибо.
    С уважением, Гимаев Наиль.

  • Vlad пишет:

    :) Да как бы эксплуатации никакой не было – просто решил узнать, что Вас так заинтересовало в Яндекс.Спеллере. А прятать за пазухой решение и потом продавать – не в моих целях и планах. Пользуйтесь на здоровье. Будут проблемы с работой модуля – говорите – будем исправлять

  • Алексей Тимохин пишет:

    А для Spell-checker-a Гугла решение, случайно, не планируется? ;-)
    Всё-таки Гугл поддерживает намного больше языков.

  • Гимаев Наиль пишет:

    Для этого не нужно быть гуглом.
    Возможно в ближайшее время появится подражатель яндекса, который сделает сайт с поддержкой этого API. Прикрутит к нему HSpell (самый популярный на данный момент). Словари для всех языков можно скачать с сайта OpenOffice. Тогда все смогут пользоваться проверкой текстов на всех языках. Для профессионального веб-программиста работа на один день.

  • Алексей Тимохин пишет:

    Гимаев Наиль, спасибо за идею! Мне вдруг пришло в голову, что тогда проще использовать этот Spellchecker напрямую. =)

  • Vlad пишет:

    Алексей, я сейчас, признаться, вообще мало чего планирую, кроме работы на 2х работах :) Но ежели дадите ссылочку на API от Гугла, то в свободное от работы время (думаю скоро оно появится) поковыряюсь с их чекером…тем более, что в последнее время меня частенько пробивает поковыряться во всяких API

  • Алексей Тимохин пишет:

    Я погорячился. Api для Spellchecker-a гугла не опубликовано официально и не документировано.
     

  • Vlad пишет:

    А неофициальная версия есть?)

  • Алексей Тимохин пишет:

    Есть, конечно. Народ расковырял Google Toolbar, чтобы посмотреть как там реализована проверка правописания. =) Но толку-то? На такое решение нельзя полагаться – если протокол неофициальный, то он может быть изменён в любой момент.  Даже GoogleChrome использует для проверки правописания не сервисы гугла, а вышеупомянутый hunspell.
     
    Но если очень хочется поковыряться с API – то, вот идея. Для Google API ещё нет полной бесплатной библиотеки для Delphi. Есть решения и примеры для работы с отдельными сервисами, в основном через публичные методы. А полного API c авторизацией и поддержкой всех методов нет. С другой стороны, раз нет, значит никому и не нужно. =)

  • Vlad пишет:

    Ну на полное API Google как бэ действительно всем пофег, т.к. есть куча “прибамбасов”, которые в программах на Delphi будут выглядеть как у собаки пятая лапа, например. А так, что-то вздумалось спаять на досуге Яндекс.Спеллер+Google.Translate…ну и ещё чё-нить до кучи :)

    Посмотрел по ссылке пост…что-то мне этот чеккер очень сильно напомнил Спеллер :) Ждем поддержки тучи языков от Яндекса…

  • Алексей Тимохин пишет:

    Совсем полный – да, пофиг.  Мне, например, пофиг APIAdsense, AdWords, Analytics, Apps и многие другие. А интересны Calendar API (или любой способ для работы с Google Tasks), Translate API, Google Static Maps API.
    Google Calendar API, наверняка потребует реализовать Google Account Authentication и Google Data Protocol, а имея удобные базовые классы – по идее можно будет легко прикрутить и поддержку других сервисов. Но это так… мысли вслух. =)
     

  • Гимаев Наиль пишет:

    Никогда не задумывался, но AdWords – хороший способ превратить бесплатную но популярную программу в приносящую доход. Нужно только подключить рекламу от гугла к своей программе, и тогда популярность можно будет вернуть деньгами.

Ваш ответ

Внимание: Все комментарии модерируются, и это может вызвать задержку их публикации. Отправлять комментарий заново не требуется.

Пожалуйста, заключайте исходный код в тэги [code][/code].