По аналогии с Delphi решил написать класс для распознавания текста с картинок (captcha) на языке C#. Работает модуль через сервис antigate.com. Для загрузки картинки на сервис используется ранее написанный класс MultiPartForm. Пример использования: Code: Antigate antigate = new Antigate(); antigate.SetKey("6f2f440e5edaf8a8b970f79b1edd312c"); antigate.SetFile(@"C:\captcha.jpg"); Console.WriteLine(antigate.Recognize()); Класс - WebTools.Antigate
УжаШь какой-то, и так: 1)Мм, string _key <- Не судьба сделать static что например в потоках не писат по многу раз одно и тоже. 2)Есть такая штука называется Свойство (он же акцессор, ассесор) 3)На.х.На это нужно то: у gif,jpeg,png есть сигнатуры который очень легко определить, ну на крайний случай использовать Image(тут же можно еще и разрешения проверить). 4) Абсолютно не нужные эвенты : public event EventHandler<AnswerEventArgs> CaptchaNotAvailable; public event EventHandler<AnswerEventArgs> CaptchaNotReady;
Ясно, буду иметь ввиду. Про них я знаю. На одном из форумов мне рекомендовали использовать для свойств, которые юзают только сеттеры, применять методы. На этот фейл мне уже не раз указывали =). Сам класс MultiPartForm писался не только для image. Добавил их чисто для информирования/добавления в лог P.S. Всегда рад здоровой критики.
Ну а если например будет такая ситуация что нужно узнать значения поля вне класса, а уровень доступа не дает - что писать еще один метод для получения значения? Поэтому лучше все же всегда использовать свойство и не закрывать get без крайне на то необходимости. А для опций антикапчи гораздо разумней будет использовать скажем - struct или class, а там уже использовать для каждой опции 1 поля и 2 свойство - 1 свойство будет возвращать значения поля как есть а 2 свойство уже в виде готовом для передачи как multipart или пустую строку если опция равна 0(и заодно сэкономить пару килобайт на траффе).
Переделал класс, с учетом всех пожеланий. Также переделал класс MultiPartForm - теперь сторонняя библиотека не юзайтся.
MD5 выпели, он совершенно не нужен.Сделай boundary = DateTime.Now.Ticks.ToString("x"); Хз есть ли смысл делать : IDisposable, я по крайней мере его не вижу.Переменные с ошибками объявил хотя бы как enum...
Boundary должен быть уникальным. MD5 это для меня гарантия того, что не будет совпадений. Люблю, чтобы все было четко. А то потом будешь недоумевать, почему периодически файл со временем загрузки timestamp, не загружается на сайт =). IDisposable - для того, чтобы не писать постоянно Close(), который добавляет завершающий boudary. С enum я как-то не разобрался, как хранить текстовые данные. Погуглил - вроде как нельзя, только числовые данные.
Ты ещё не попробовал, а уже говоришь.Через мой способ генерируется уникальное значение. P.S и ещё вопрос отдалённый, а чего ты к переменным приписываешь _?Это с какого-то другого ЯП привычка?
Ага в потоках он будет уникальный - Random randNum = new Random(), если уж использовать 4 Framework(FileStream.CopyTo) то почему бы не воспользоваться ThreadLocal:
Из этого предложения не совсем понятно, что вы имеете ввиду. В разных потоках может сгенерироваться одно и тоже случайное число? P.S. Обновил TAntigate для Delphi
Зачем все эти if при отсылке капчи, можно ведь просто слать 0...Зачем делал методы с присваиванием значения переменной?Неужели нельзя просто сделать public переменную?Метод Recognize() неебически большой...Разбил бы на 2 части, не?Обработки ошибок вообще не вижу (юзеру ничего не говорится при ошибках).И да, если ты уж так сильно волнуешься об уникальности бондарьки то делай GUID как описал выше PaCo ибо MD5 не айс вообще. p.s заметь, я не придираюсь, просто указываю на недостатки.
Решил, что лучше отфильтровать лишние параметры, которые установлены по дефолту. "Write-only свойства — плохая практика. Лучше заменить на метод вида SetUrl()." http://www.rsdn.ru/forum/dotnet/4111881.1.aspx Пока придерживаюсь этого стиля. Изначально так и было, но код выглядел как то убого и я решил объединить в один метод. Обработка ошибок ложится на пользователя. Если ошибка не критическая (CAPCHA_NOT_READY, ERROR_NO_SLOT_AVAILABLE), то выполнение продолжается, во всех остальных случаях вызывается событие CaptchaError, где пользователь может обработать ответ сервиса, как в примере в блоге.
Плохая практика делать методы для полей там где необходимо использовать свойства с get set, да даже по приведенной вами ссылке человек пишет: посему это изврат, да и это какой то....: а не проще ли в AddData проверять значения на "0" и делать return в случаи если это так.
Тема актуальна! Прошу помощи у тех кто работал с google! Выложите ту часть программы где вы перехватываете страницу с капчей, сохраняете в файл и отправляете запрос с результатом. Спасибо!