Подписка

добавить на Яндекс

Наши проекты

Delphi+Google

Google API

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

Chrono

Chrono

Хронометр - программа для ведения списка задач.

ODFProc

ODFProc

ODFProc - работа с документами OpenOffice в Lazarus и FreePascal.

Поддержка блога

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

Публикации

Год назад

Случайный пост

Последние

Сообщения форума

Комментарии

Свежие комментарии

Социальные сети

Google

Facebook

Twitter

Опрос

Вы сейчас или в ближайшем обозримом будущем планируете разрабатывать кроссплатформенное приложение с использованием Firemonkey?



Loading ... Loading ...

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

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


Пока собираюсь с мыслями по поводу написания одной большой статьи про использование 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, выбираете и дело в шляпе.

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

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

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].
Если код большой, то воспользуйтесь Вставкой кода на отдельной странице и оставьте в комментарии ссылку на исходник