[C#] Класс распознавания для antigate.com

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by GlooK, 25 Jan 2011.

  1. GlooK

    GlooK Elder - Старейшина

    Joined:
    20 Apr 2007
    Messages:
    172
    Likes Received:
    53
    Reputations:
    10
    По аналогии с 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
     
    2 people like this.
  2. PaCo

    PaCo Elder - Старейшина

    Joined:
    6 Feb 2008
    Messages:
    436
    Likes Received:
    138
    Reputations:
    25
    УжаШь какой-то, и так:
    1)Мм, string _key <- Не судьба сделать static что например в потоках не писат по многу раз одно и тоже.
    2)Есть такая штука называется Свойство (он же акцессор, ассесор)
    3)На.х.На это нужно то:
    у gif,jpeg,png есть сигнатуры который очень легко определить, ну на крайний случай использовать Image(тут же можно еще и разрешения проверить).
    4) Абсолютно не нужные эвенты :
    public event EventHandler<AnswerEventArgs> CaptchaNotAvailable;
    public event EventHandler<AnswerEventArgs> CaptchaNotReady;
     
    1 person likes this.
  3. GlooK

    GlooK Elder - Старейшина

    Joined:
    20 Apr 2007
    Messages:
    172
    Likes Received:
    53
    Reputations:
    10
    Ясно, буду иметь ввиду.
    Про них я знаю. На одном из форумов мне рекомендовали использовать для свойств, которые юзают только сеттеры, применять методы.
    На этот фейл мне уже не раз указывали =).
    Сам класс MultiPartForm писался не только для image.
    Добавил их чисто для информирования/добавления в лог

    P.S. Всегда рад здоровой критики.
     
  4. PaCo

    PaCo Elder - Старейшина

    Joined:
    6 Feb 2008
    Messages:
    436
    Likes Received:
    138
    Reputations:
    25
    Ну а если например будет такая ситуация что нужно узнать значения поля вне класса, а уровень доступа не дает - что писать еще один метод для получения значения? Поэтому лучше все же всегда использовать свойство и не закрывать get без крайне на то необходимости. А для опций антикапчи гораздо разумней будет использовать скажем - struct или class, а там уже использовать для каждой опции 1 поля и 2 свойство - 1 свойство будет возвращать значения поля как есть а 2 свойство уже в виде готовом для передачи как multipart или пустую строку если опция равна 0(и заодно сэкономить пару килобайт на траффе:)).
     
    1 person likes this.
  5. GlooK

    GlooK Elder - Старейшина

    Joined:
    20 Apr 2007
    Messages:
    172
    Likes Received:
    53
    Reputations:
    10
    Переделал класс, с учетом всех пожеланий.
    Также переделал класс MultiPartForm - теперь сторонняя библиотека не юзайтся.
     
    1 person likes this.
  6. CodeSender:)

    CodeSender:) Elder - Старейшина

    Joined:
    29 Jul 2010
    Messages:
    245
    Likes Received:
    115
    Reputations:
    23
    MD5 выпели, он совершенно не нужен.Сделай boundary = DateTime.Now.Ticks.ToString("x");
    Хз есть ли смысл делать : IDisposable, я по крайней мере его не вижу.Переменные с ошибками объявил хотя бы как enum...
     
    #6 CodeSender:), 28 Jan 2011
    Last edited: 28 Jan 2011
  7. GlooK

    GlooK Elder - Старейшина

    Joined:
    20 Apr 2007
    Messages:
    172
    Likes Received:
    53
    Reputations:
    10
    Boundary должен быть уникальным.
    MD5 это для меня гарантия того, что не будет совпадений.
    Люблю, чтобы все было четко.
    А то потом будешь недоумевать, почему периодически файл со временем загрузки timestamp, не загружается на сайт =).
    IDisposable - для того, чтобы не писать постоянно Close(), который добавляет завершающий boudary.
    С enum я как-то не разобрался, как хранить текстовые данные. Погуглил - вроде как нельзя, только числовые данные.
     
    #7 GlooK, 28 Jan 2011
    Last edited: 28 Jan 2011
  8. CodeSender:)

    CodeSender:) Elder - Старейшина

    Joined:
    29 Jul 2010
    Messages:
    245
    Likes Received:
    115
    Reputations:
    23
    Ты ещё не попробовал, а уже говоришь.Через мой способ генерируется уникальное значение.

    P.S и ещё вопрос отдалённый, а чего ты к переменным приписываешь _?Это с какого-то другого ЯП привычка?
     
    #8 CodeSender:), 28 Jan 2011
    Last edited: 28 Jan 2011
  9. GlooK

    GlooK Elder - Старейшина

    Joined:
    20 Apr 2007
    Messages:
    172
    Likes Received:
    53
    Reputations:
    10
    Не пробовал =)
    Тут уже дело вкуса. Можно даже рекламу своего сайта туда вставить ))
     
  10. GlooK

    GlooK Elder - Старейшина

    Joined:
    20 Apr 2007
    Messages:
    172
    Likes Received:
    53
    Reputations:
    10
    Пытаюсь придерживаться соглашения RSDN.
    http://www.rsdn.ru/article/mag/200401/codestyle.XML#EALAC
     
  11. PaCo

    PaCo Elder - Старейшина

    Joined:
    6 Feb 2008
    Messages:
    436
    Likes Received:
    138
    Reputations:
    25
    Ага в потоках он будет уникальный - Random randNum = new Random(), если уж использовать 4 Framework(FileStream.CopyTo) то почему бы не воспользоваться ThreadLocal:
     
  12. GlooK

    GlooK Elder - Старейшина

    Joined:
    20 Apr 2007
    Messages:
    172
    Likes Received:
    53
    Reputations:
    10
    Из этого предложения не совсем понятно, что вы имеете ввиду. В разных потоках может сгенерироваться одно и тоже случайное число?

    P.S. Обновил TAntigate для Delphi
     
    #12 GlooK, 28 Jan 2011
    Last edited: 29 Jan 2011
  13. CodeSender:)

    CodeSender:) Elder - Старейшина

    Joined:
    29 Jul 2010
    Messages:
    245
    Likes Received:
    115
    Reputations:
    23
    Зачем все эти if при отсылке капчи, можно ведь просто слать 0...Зачем делал методы с присваиванием значения переменной?Неужели нельзя просто сделать public переменную?Метод Recognize() неебически большой...Разбил бы на 2 части, не?Обработки ошибок вообще не вижу (юзеру ничего не говорится при ошибках).И да, если ты уж так сильно волнуешься об уникальности бондарьки то делай GUID как описал выше PaCo ибо MD5 не айс вообще.

    p.s заметь, я не придираюсь, просто указываю на недостатки.
     
    #13 CodeSender:), 29 Jan 2011
    Last edited: 29 Jan 2011
  14. GlooK

    GlooK Elder - Старейшина

    Joined:
    20 Apr 2007
    Messages:
    172
    Likes Received:
    53
    Reputations:
    10
    Решил, что лучше отфильтровать лишние параметры, которые установлены по дефолту.
    "Write-only свойства — плохая практика. Лучше заменить на метод вида SetUrl()."
    http://www.rsdn.ru/forum/dotnet/4111881.1.aspx
    Пока придерживаюсь этого стиля.
    Изначально так и было, но код выглядел как то убого и я решил объединить в один метод.
    Обработка ошибок ложится на пользователя.
    Если ошибка не критическая (CAPCHA_NOT_READY, ERROR_NO_SLOT_AVAILABLE), то выполнение продолжается, во всех остальных случаях вызывается событие CaptchaError, где пользователь может обработать ответ сервиса, как в примере в блоге.
     
  15. PaCo

    PaCo Elder - Старейшина

    Joined:
    6 Feb 2008
    Messages:
    436
    Likes Received:
    138
    Reputations:
    25
    Плохая практика делать методы для полей там где необходимо использовать свойства с get set, да даже по приведенной вами ссылке человек пишет:
    посему это изврат, да и это какой то....:
    а не проще ли в AddData проверять значения на "0" и делать return в случаи если это так.
     
  16. .::eX-Tezy::.

    .::eX-Tezy::. Elder - Старейшина

    Joined:
    28 Jun 2007
    Messages:
    13
    Likes Received:
    20
    Reputations:
    5
    Тема актуальна!
    Прошу помощи у тех кто работал с google!
    Выложите ту часть программы где вы перехватываете страницу с капчей, сохраняете в файл и отправляете запрос с результатом. Спасибо!