Помогите скачать аудио-капчу SolveMedia

konfuciy

Client
Регистрация
07.05.2014
Сообщения
1 402
Благодарностей
131
Баллы
63
Помогите скачать аудио-капчу солвмедиа на компьютер, как это можно реализовать?
 

rostonix

Известная личность
Регистрация
23.12.2011
Сообщения
29 067
Благодарностей
5 705
Баллы
113
а в чем сложность? найти в DOM путь к файлу, указать спаршенный урл в GET запросе
 

konfuciy

Client
Регистрация
07.05.2014
Сообщения
1 402
Благодарностей
131
Баллы
63
а в чем сложность? найти в DOM путь к файлу, указать спаршенный урл в GET запросе
не могу найти адрес аудио-файла.
не могу определить расширение файла.
я нахожу адреса такого типа -
Код:
https://api-secure.solvemedia.com/papi/media?c=2@D-u7ZI7ObqfedKfx3nt7WYN5sL8MmqK3@UvTExNR1MRgENU8bgrS.HH9APTC4lJjo7lc4TYOvQzhIEJcPrQBILXZzzsRQW1QSQWI4LtqlDuncPN-e.Ay950no-VoB5KJl93K2GfdoZqDfztIao7.xgoSLEl5oxs1EtcKOTsq8JPYVjLPGWPb2C.twTV0YzSfSBpzJ6lhgFPXhu9x16h60b3qmCL.qgz3GFsgJM1G78lKXTS5UnOFkDqWQI6uSmoR.sImIsPMI2zbisPiyNv3MOISrrUlBEtfWx4alu5vNtMMmSEVcgrS6gA

по такому адресу ничего не скачивается.
точнее скачивается картинка с ошибкой, а не аудио-файл
 

evgen_po

Client
Регистрация
27.08.2013
Сообщения
847
Благодарностей
527
Баллы
93

konfuciy

Client
Регистрация
07.05.2014
Сообщения
1 402
Благодарностей
131
Баллы
63

evgen_po

Client
Регистрация
27.08.2013
Сообщения
847
Благодарностей
527
Баллы
93

konfuciy

Client
Регистрация
07.05.2014
Сообщения
1 402
Благодарностей
131
Баллы
63

konfuciy

Client
Регистрация
07.05.2014
Сообщения
1 402
Благодарностей
131
Баллы
63
все, нашел решение
 

rostonix

Известная личность
Регистрация
23.12.2011
Сообщения
29 067
Благодарностей
5 705
Баллы
113

konfuciy

Client
Регистрация
07.05.2014
Сообщения
1 402
Благодарностей
131
Баллы
63
В чем была проблема?
Проблема описана выше, ГЕТ запрос не выкачивает капчу. В этом плане ничего не изменилось. ГЕТом ничего не выкачать. Надо идти через нажатие кнопки. Собственно решение, как получить эту капчу, было описано вами же в другой ветке.
 
Последнее редактирование:

samsonnn

Client
Регистрация
02.06.2015
Сообщения
1 630
Благодарностей
1 303
Баллы
113
Проблема описана выше, ГЕТ запрос не выкачивает капчу. В этом плане ничего не изменилось. ГЕТом ничего не выкачать. Надо идти через нажатие кнопки. Собственно решение, как получить эту капчу, было описано вами же в другой ветке.
Получается как не крути, а из за капчи, прийдется к шаблону который на пост гет запросах, прикручивать загрузку страницы в браузере? Беда печаль =(
 

Roman*

Client
Регистрация
25.09.2013
Сообщения
1 649
Благодарностей
652
Баллы
113
Может, все таки кто понял, как эмулировать плагины и расскажет, как гетом скачивать файлик?
 

swiniks

Client
Регистрация
19.02.2015
Сообщения
244
Благодарностей
171
Баллы
43
Попытался скачать аудио-капчу SolveMedia через GET запрос. В браузере загрузил страничку с капчей и увидел три GET запроса капчи. Третий запрос формируется на основе двух первых.
C#:
1. http://api.solvemedia.com/papi/challenge.script?k=(Ключ формы капчи)
2. http://api.solvemedia.com/papi/_puzzle.js
3. http://api.solvemedia.com/papi/_challenge.js?k=(Ключ формы капчи);
f=_ACPuzzleUtil.callbacks%5B0%5D; // Есть в ответе puzzle.js - _ACPuzzleUtil.callbacks[0] (%5B0%5D - это [0])
l=en; // Есть в ответе первого запроса - Язык капчи
t=img; // Есть в ответе первого запроса - Тип капчи
s=standard; // Есть в ответе первого запроса - Размер size
c=js,h5c,h5ct,svg,h5v,v/ogg,v/webm,h5a,a/mp3,a/ogg,ua/firefox,ua/firefox47,os/nt,os/nt6.1,expand,fwv/PCir2g.islh74,jslib/jquery,htmlplus;
// Есть в ответе puzzle.js - Но надо составлять
am=pFs8xmXuDXWYc4pTZe4NdQ; // Есть в ответе первого запроса
ca=script; // Есть в ответе первого запроса
ts=1482543039; // Время UNIX - Текущее на данный момент
ct=1482543856; // Есть в ответе первого запроса - Время UNIX - Старое
th=white; // Есть в ответе первого запроса - Тема оформления
r=0.3989319945381731 // Mach.Random() - Случайное число от 0 до 1 из скрипта puzzle.js
Все три запроса делаются без куков, подставляется только значение referer. И только в третем запросе присваиваются куки. Конвертация времени UNIX онлайн в помощь. Повторил всё это дело без браузера, на чистых GET запросах. Итог: Первые два запроса отрабатывают отлично, возвращают правильные ответы, а вот с третим у меня совсем беда пока, ответ получен, но не верный. Все параметры спарсил и подставил в третий запрос, кроме одного вот этого (c=) , просто лень было собирать его, попытался в парить как отловил ранее. Но увы не сработало, возможно из за этого параметра (c=). Может второй запрос делаю не правильно, но ответ правильный вроде. Если смотреть на ответ первого запроса, то полученный скрипт делает второй GET запрос и возможно передает туда параметры не силён в Java. Кто знает Java, подскажите и расскажите что да как. Будем думать, как скачать аудио файл.
Java:
var ACPuzzleOptions;
var ACPuzzleInfo = {
    ckey:           '(Ключ формы капчи)',
    protocol:       !window.location.protocol.match(/^https?:$/) ? 'http:' : '',
    apiserver:      '//api.solvemedia.com',
    mediaserver:    '//api.solvemedia.com',
    magic:          'pFs8xmXuDXWYc4pTZe4NdQ',
    chalapi:        'script',
    chalstamp:       1482543856,
    lang:           'en',
    size:           'standard',
    theme:          'white',
    type:           'img',
    onload:         function(){ ACPuzzle.script_init() }
};
document.write('<' + 'scr' + 'ipt type="text/javascript" s' + 'rc="' +
(ACPuzzleInfo.protocol || '') + ACPuzzleInfo.apiserver + '/papi/_puzzle.js"><' + '/scr' + 'ipt' + '>');
В принципе, после остаётся ещё два запроса, первый(4) переключится на аудио и второй(5) уже выдаст сам файл. Первый(4) похож на третий(3), такие же параметры с учётом переключения t=img на t=aud. Если кто то, получит правильный результат третего запроса, отпишитесь, как, что и почему. Будем думать дальше, как скачать аудио файл. Всем спасибо.
 
Последнее редактирование:

alexandro3337

Client
Регистрация
26.08.2015
Сообщения
11
Благодарностей
2
Баллы
3
Тоже интересует информация по скачиванию get запроса солве-медиа. Подскажите кто нибудь как это осуществить!!!
 

Moadip

Client
Регистрация
26.09.2015
Сообщения
509
Благодарностей
823
Баллы
93
Попытался скачать аудио-капчу SolveMedia через GET запрос. В браузере загрузил страничку с капчей и увидел три GET запроса капчи. Третий запрос формируется на основе двух первых.
...
Прочитал, вроде порядок действий норм, где у тебя там ошибка, так проблематично сказать.

В общем порядок действий такой.
1. Get запрос формата http://api.solvemedia.com/papi/challenge.script?k=HmjWW-mdW2kwRzrXIOURB3zqUBk5aV0p

2. Из ответа вытаскиваются данные ckey, magic, chalapi, chalstamp, lang, size, theme, type,


3. Get запрос http://api.solvemedia.com/papi/_puzzle.js
Из полученного скрипта вытаскиваем ts, а также генерим с, на основе алгоритма как в скрипте


4. Get запрос на http://api.solvemedia.com/papi/_challenge.js? + все параметры которые наковыряли, type=img, _str это и есть с, которую генерили


5. Из ответа вытаскиваем chid и mediatype


6. Проверка что лежит в mediatype, если там нихрена - бан по ip


7. Повторяем запрос из пункта 4 но теперь уже type=aud, остальное все без изменений(за исключением рандома для r), затем пункт 5, чтобы получить новый chid, на mediatype уже похер.

8. Запрос аудио. Вот тут то и нужен chid(вообще он нужен не только для аудио), который меняется при каждом запросе.
Получаем ответ в виде массива байтов.


9. Скармливаем монстру


10. Профит!8-)



Пункты 4, 5, 6, 7.
Можно сразу отправлять запрос с type=aud, без первого запроса с img.

Но я бы так не стал делать, по нескольким причинам.

Первая. Т.к первый запрос из браузера автоматом уходит именно с img, и только потом, когда переключается капча на аудио, уходит с aud, т.е если не делать первого запроса с img, это лишнее палево.

Вторая. При первом запросе с img, там может прийти несколько вариантов ответов, и некоторые очень интересные, но это уже отдельная тема и не относится к аудио.:D

chid, постоянно надо получать новый, при каждом новом запросе с aud или img.
Т.е взяли аудио, не разгадалось/не подошло, посылается новый запрос для получения нового chid, чтобы скачать новое аудио.

Но я так не рекомендую делать. Ip моментально задрачивается, качество аудио становится еще хуже чем было(которое и так пздц), что наврядли повысит процент успешного разгадывания.:-)
 

amyboose

Client
Регистрация
21.04.2016
Сообщения
2 312
Благодарностей
1 190
Баллы
113
Прочитал, вроде порядок действий норм, где у тебя там ошибка, так проблематично сказать.

В общем порядок действий такой.
1. Get запрос формата http://api.solvemedia.com/papi/challenge.script?k=HmjWW-mdW2kwRzrXIOURB3zqUBk5aV0p

2. Из ответа вытаскиваются данные ckey, magic, chalapi, chalstamp, lang, size, theme, type,


3. Get запрос http://api.solvemedia.com/papi/_puzzle.js
Из полученного скрипта вытаскиваем ts, а также генерим с, на основе алгоритма как в скрипте


4. Get запрос на http://api.solvemedia.com/papi/_challenge.js? + все параметры которые наковыряли, type=img, _str это и есть с, которую генерили


5. Из ответа вытаскиваем chid и mediatype


6. Проверка что лежит в mediatype, если там нихрена - бан по ip


7. Повторяем запрос из пункта 4 но теперь уже type=aud, остальное все без изменений(за исключением рандома для r), затем пункт 5, чтобы получить новый chid, на mediatype уже похер.

8. Запрос аудио. Вот тут то и нужен chid(вообще он нужен не только для аудио), который меняется при каждом запросе.
Получаем ответ в виде массива байтов.


9. Скармливаем монстру


10. Профит!8-)



Пункты 4, 5, 6, 7.
Можно сразу отправлять запрос с type=aud, без первого запроса с img.

Но я бы так не стал делать, по нескольким причинам.

Первая. Т.к первый запрос из браузера автоматом уходит именно с img, и только потом, когда переключается капча на аудио, уходит с aud, т.е если не делать первого запроса с img, это лишнее палево.

Вторая. При первом запросе с img, там может прийти несколько вариантов ответов, и некоторые очень интересные, но это уже отдельная тема и не относится к аудио.:D

chid, постоянно надо получать новый, при каждом новом запросе с aud или img.
Т.е взяли аудио, не разгадалось/не подошло, посылается новый запрос для получения нового chid, чтобы скачать новое аудио.

Но я так не рекомендую делать. Ip моментально задрачивается, качество аудио становится еще хуже чем было(которое и так пздц), что наврядли повысит процент успешного разгадывания.:-)
надеюсь тебе не заспамили личку фразами "есть готовое решение?" :D
 

Moadip

Client
Регистрация
26.09.2015
Сообщения
509
Благодарностей
823
Баллы
93
надеюсь тебе не заспамили личку фразами "есть готовое решение?" :D
А это разве не готовое?:-)
Мне бы кто такой гайд подкинул, когда я SM капчу ковырял.
Вся аналитическая работа проделана, расписано что, откуда, куда, и почему, шаг за шагом.
Осталось только чутка поднапрячься и собрать все это.
Ну а кому уж совсем лениво, ок, пусть пишут в личку, поди договоримся, напрягусь за них.:D
 
  • Спасибо
Реакции: Kazarang и swiniks

amyboose

Client
Регистрация
21.04.2016
Сообщения
2 312
Благодарностей
1 190
Баллы
113
А это разве не готовое?:-)
Мне бы кто такой гайд подкинул, когда я SM капчу ковырял.
Вся аналитическая работа проделана, расписано что, откуда, куда, и почему, шаг за шагом.
Осталось только чутка поднапрячься и собрать все это.
Ну а кому уж совсем лениво, ок, пусть пишут в личку, поди договоримся, напрягусь за них.:D
ну для меня это почти готовое решение, для 95% форума тут ниче непонятно даже, так что уж точно щас начнется смак "покажи", да "научи" :-)
P.S. а так по сути ты проделал огромную работу по разбору капчи, которой мало кто поделился бы даже за деньги
 

swiniks

Client
Регистрация
19.02.2015
Сообщения
244
Благодарностей
171
Баллы
43
Прочитал, вроде порядок действий норм, где у тебя там ошибка, так проблематично сказать.

В общем порядок действий такой.
1. Get запрос формата http://api.solvemedia.com/papi/challenge.script?k=HmjWW-mdW2kwRzrXIOURB3zqUBk5aV0p

2. Из ответа вытаскиваются данные ckey, magic, chalapi, chalstamp, lang, size, theme, type,


3. Get запрос http://api.solvemedia.com/papi/_puzzle.js
Из полученного скрипта вытаскиваем ts, а также генерим с, на основе алгоритма как в скрипте


4. Get запрос на http://api.solvemedia.com/papi/_challenge.js? + все параметры которые наковыряли, type=img, _str это и есть с, которую генерили


5. Из ответа вытаскиваем chid и mediatype


6. Проверка что лежит в mediatype, если там нихрена - бан по ip


7. Повторяем запрос из пункта 4 но теперь уже type=aud, остальное все без изменений(за исключением рандома для r), затем пункт 5, чтобы получить новый chid, на mediatype уже похер.

8. Запрос аудио. Вот тут то и нужен chid(вообще он нужен не только для аудио), который меняется при каждом запросе.
Получаем ответ в виде массива байтов.


9. Скармливаем монстру


10. Профит!8-)



Пункты 4, 5, 6, 7.
Можно сразу отправлять запрос с type=aud, без первого запроса с img.

Но я бы так не стал делать, по нескольким причинам.

Первая. Т.к первый запрос из браузера автоматом уходит именно с img, и только потом, когда переключается капча на аудио, уходит с aud, т.е если не делать первого запроса с img, это лишнее палево.

Вторая. При первом запросе с img, там может прийти несколько вариантов ответов, и некоторые очень интересные, но это уже отдельная тема и не относится к аудио.:D

chid, постоянно надо получать новый, при каждом новом запросе с aud или img.
Т.е взяли аудио, не разгадалось/не подошло, посылается новый запрос для получения нового chid, чтобы скачать новое аудио.

Но я так не рекомендую делать. Ip моментально задрачивается, качество аудио становится еще хуже чем было(которое и так пздц), что наврядли повысит процент успешного разгадывания.:-)
Большое спасибо Moadip за пример, плохо что в картинках, если не тяжело кинь шаблон пример или вставь как текст пожалуйста. А то начал в ручную перепечатывать в кубик C# и на первом же коде куча ошибок, так и не смог даже первый код запустить. Или его нужно набирать OwnCode в общий код, а потом вызывать как функцию? Или это всё в один кубик C# и добавить запросы ? Не много не врубился.
 

Moadip

Client
Регистрация
26.09.2015
Сообщения
509
Благодарностей
823
Баллы
93
Дело в том, что это не шаблон.
Весь код находится в своей проге, и просто так выдрать не получится, там есть зависимости от других классов и библиотек.

Собственно поэтому и куски кода, которые показывают ключевые моменты, в которых могут быть траблы, а также пошаговое решение, а не целиком все.
Карочь нет готового шаболона.))
Это надо адаптировать весь код по зенку, прям сейчас это лениво делать, может потом.

Пиши в личку, ты я так понял шаришь, т.к. в своем посте посути все и описал, не хватало только пару шагов. Помогу с адаптацией, не придется все с нуля разжевывать.
 

swiniks

Client
Регистрация
19.02.2015
Сообщения
244
Благодарностей
171
Баллы
43
Да конечно не парся, если надо время тратить что бы выложить. Шарю громко сказано так не много понимаю что то, а что нет. Вот с общим кодом и вызовами в кубиках пока не сталкивался и не до конца понимаю, GET и POST запросы на C# в принципе освоил на троечку. Отписал в личку. Набросать может миши-шаб пример моего варианта на кубиках?
 

swiniks

Client
Регистрация
19.02.2015
Сообщения
244
Благодарностей
171
Баллы
43
Что бы заработал 3, 4 и 5 запрос. Делаем костыль, заменяем 3 GET запрос, на POST запрос и 4 GET запрос, на POST запрос.
url post запроса: (http://api.solvemedia.com/papi/challenge.script?)
Остальное в из GET запроса в данные POST запроса. А 5 запрос как обычно GET запросом сохраняем аудио файл.
 

Moadip

Client
Регистрация
26.09.2015
Сообщения
509
Благодарностей
823
Баллы
93
Адаптировал код под зенку. Не думал конечно что столько геммора будет.
Т.к. по сути адаптация заключалась в том, что убрать зависимости от других либ, и поменять свои методы для работы с запросами на зенковские.
А делал их по образу и подобию зенковских. Сигнатуры практически один в один.
Т.е теоретически надо было только поменять мои названия методов, на названия зенковских.

Это было в теории. А дальше началась практика.:D

Первая проблема.
http://zennolab.com/discussion/threads/get-zapros-urlencode-tam-gde-ne-nado.33838/
Х.з. может я не умею готовить ZennoPoster.HttpGet но у меня так и не получилась, чтобы урл отправлялся в том формате, в котором он был в коде, как бы я не извращался.
Если кто знает что не так, ткните носом.

На это было угроблена большая часть времени. Код перенесен, названия методов поменяны, но код работает не так как надо.
Все было проверено под дебагом, класс для зенки дебажился через CodeCreator и параллельно оригинальный код.
Все один в один, все переменные один в один, но с моими методами для работы с запросами все работает, а с зенковскими нет.

WTF?!?!

Посмотрев через фидлер, стало понятно что ZennoPoster.HttpGet делает urlEncode для ссылки, в этом и была проблема.

В процессе общения с @swiniks он нашел вариант, если заменить Get на Post, отправлять урл без параметров, а параметры пихать в тело запроса, то все отрабатывает так как надо.
Собственно об этом данный пост.
Что бы заработал 3, 4 и 5 запрос. Делаем костыль, заменяем 3 GET запрос, на POST запрос и 4 GET запрос, на POST запрос.
url post запроса: (http://api.solvemedia.com/papi/challenge.script?)
Остальное в из GET запроса в данные POST запроса. А 5 запрос как обычно GET запросом сохраняем аудио файл.

Вторая проблема.
При вытаскивании аудио через post запрос, ответ приходит в string, ответ не в Base64String, который нужен для CapMonster, а в каком то другом формате/кодировке.
Опять же, как не извращался, так и не понял как перегнать string от post в Base64String.

Можно конечно результат post запроса сохранить на винт, потом его прочитать, конвертнуть и скормить CapMonster, но это лишний геммор, в виде дерганья винта.

Меня такой вариант не устраивал. Стало понятно, что только зенковскими методами для работы с запросами не обойтись.
Пугать народ своим "велосипедом" для работы с запросами не хотелось(доп. лишний код, и доп. потенциальные непонятки.)
Поэтому взял готовый "велосипед".
xNet - https://github.com/X-rus/xNet
Почитать что это такое - https://habrahabr.ru/post/146475/

С помощью данной либы и был переделан код для работы с запросами.
C#:
public class SolveMediaCaptcha
{
    private enum RandomType
    {
        Num,
        Chars,
        NumAndChars
    }

    /// <summary>
    /// Тип прокси.
    /// </summary>
    public enum ProxyTypeEnum
    {
        Http,
        Socks
    }

    /// <summary>
    /// Ответ распознавания или описание ошибки.
    /// </summary>
    public string Answer { get; private set; }

    /// <summary>
    /// Токен распознанной капчи
    /// </summary>
    public string AnswerToken { get; private set; }

    /// <summary>
    /// Прокси, в виде ip:port или name:passoword@ip:port
    /// </summary>
    public string Proxy { get; set; }

    /// <summary>
    /// Тип прокси. По умолчанию http.
    /// </summary>
    public ProxyTypeEnum ProxyType { get; set; }

    /// <summary>
    /// UserAgent
    /// </summary>
    public string UserAgent { get; set; }

    /// <summary>
    /// Referer, урл сайта на котором находится капча
    /// </summary>
    public string Referer { get; set; }

    /// <summary>
    /// Адрес CM, в виде ip
    /// </summary>
    public string CapMonsterAddress { get; set; }

    /// <summary>
    /// Ключ(если есть) CM
    /// </summary>
    public string CapMonsterKey { get; set; }

    private readonly string _siteKey;
    private CookieDictionary _cookieDictionary = new CookieDictionary();

    public SolveMediaCaptcha(string siteKey)
    {
        _siteKey = siteKey;

        Answer = "";
        AnswerToken = "";

        Proxy = "";
        ProxyType = ProxyTypeEnum.Http;
        UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36";
        Referer = "";
    }

    /// <summary>
    /// Распознать капчу.
    /// </summary>
    /// <returns>True, при успехе, в Answer будет записан ответ. False, при неуспехе, в Answer будет записано описание ошибки.</returns>
    public bool Recognize()
    {
        string response = ResponseFirst();
        if (response == null) return false;
        GetValuesFirst(response);

        response = ResponsePuzzle();
        if (response == null) return false;
        if (!GetValuesPuzzle(response)) return false;

        response = ResponseChallenge("img");
        if (response == null) return false;
        if (!GetValuesChallenge(response)) return false;

        if (_mediatype == "")
        {
            Answer = "ip ban";
            return false;
        }

        response = ResponseChallenge("aud");
        if (response == null) return false;
        if (!GetValuesChallenge(response)) return false;

        var mp3Array = ResponseGetAudio();
        if (mp3Array == null) return false;

        if (RecognizeAudio(mp3Array)) return true;

        return false;
    }

    private string ResponseToString(string url)
    {
        var res = (string)SendGet(url, "ToString");

        if (string.IsNullOrEmpty(res)) return null;

        return res;
    }

    private byte[] ResponseToByteArray(string url)
    {
        var res = (byte[])SendGet(url, "ToBytes");

        if (res == null) return null;

        return res;
    }

    private object SendGet(string url, string convert)
    {
        object response = null;

        try
        {
            var request = new HttpRequest();
            request.Proxy = SetProxy();
            request.EnableEncodingContent = true;
            request.ConnectTimeout = 15000;
            request.Cookies = _cookieDictionary;
            request.UserAgent = UserAgent;
            request.AllowAutoRedirect = true;
            request.MaximumAutomaticRedirections = 3;
            request.KeepAlive = true;
            request.Referer = Referer;

            request["Accept"] = "*/*";
            request["Accept-Language"] = "ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4";

            if (convert == "ToString")
            {
                response = request.Get(url).ToString();
            }

            if (convert == "ToBytes")
            {
                response = request.Get(url).ToBytes();
            }

            request.Close();
        }
        catch (HttpException e)
        {
            switch (e.Status)
            {
                case HttpExceptionStatus.Other:
                    Answer = "Неизвестная ошибка";
                    break;

                case HttpExceptionStatus.ProtocolError:
                    Answer = Answer = "Код состояния: " + (int)e.HttpStatusCode;
                    break;

                case HttpExceptionStatus.ConnectFailure:
                    Answer = "Не удалось соединиться с HTTP-сервером";
                    break;

                case HttpExceptionStatus.SendFailure:
                    Answer = "Не удалось отправить запрос HTTP-серверу";
                    break;

                case HttpExceptionStatus.ReceiveFailure:
                    Answer = "Не удалось загрузить ответ от HTTP-сервера";
                    break;
            }
        }

        return response;
    }

    private string ResponseFirst()
    {
        var url = "http://api.solvemedia.com/papi/challenge.script?k=" + _siteKey;

        var response = ResponseToString(url);

        if (response == null)
        {
            return null;
        }

        var result = response;

        return result;
    }

    private string _cKey;
    private string _magic;
    private string _chalapi;
    private string _chalstamp;
    private string _lang;
    private string _size;
    private string _theme;
    private string _type;

    private void GetValuesFirst(string response)
    {
        var pattern = "(?<=var\\ ACPuzzleInfo\\ =\\ \\{)[\\w\\W]*(?=};)";

        var match = Regex.Match(response, pattern).Value.Trim('\r', '\n');
        var split = match.Split(',');

        var dic = new Dictionary<string, string>();

        foreach (var s in split)
        {
            var str = s.Trim('\n', '\r', ' ');
            var innerSplit = str.Split(':');

            dic.Add(innerSplit[0], innerSplit[1].Trim('\t', ' ', '\''));
        }

        _cKey = dic["ckey"];
        _magic = dic["magic"];
        _chalapi = dic["chalapi"];
        _chalstamp = dic["chalstamp"];
        _lang = dic["lang"];
        _size = dic["size"];
        _theme = dic["theme"];
        _type = dic["type"];
    }

    private string ResponsePuzzle()
    {
        var url = "http://api.solvemedia.com/papi/_puzzle.js";

        var response = ResponseToString(url);

        if (response == null)
        {
            return null;
        }

        var result = response;

        return result;
    }

    private string _str;
    private string _ts;

    private bool GetValuesPuzzle(string response)
    {
        var patternKey = "(?<=caps=caps\\+',).*?(?='\\+'\\.'\\+String\\.fromCharCode)";
        var patternTs = "(?<=;ts=).*(?='\\+')";

        var match = Regex.Match(response, patternKey).Value;
        if (match == "")
        {
            Answer = "error GetValuesPuzzle";
            return false;
        }

        var key = match;

        match = Regex.Match(response, patternTs).Value;
        if (match == "")
        {
            Answer = "error GetValuesPuzzle";
            return false;
        }

        _ts = match;

        _str = string.Format(
            "c=js,h5c,h5ct,svg,h5v,v/h264,v/ogg,v/webm,h5a,a/mp3,a/ogg," +
            "ua/chrome," +
            "ua/chrome52," +
            "os/nt," +
            "os/nt6.1," +
            "expand,swf22,swf22.0,swf," +
            "{0}," +
            "jslib/jquery,htmlplus;",
            key + "." + GenerateRandom(RandomType.Chars, 4) + new Random().Next(11, 100)); // "fwv/M.Mosg.hidi11"

        return true;
    }

    private string ResponseChallenge(string type)
    {
        var url = string.Format(
            "http://api.solvemedia.com/papi/_challenge.js?" +
            "k={0};" +
            "f=_ACPuzzleUtil.callbacks%5B0%5D;" +
            "l={1};" +
            "t={2};" +
            "s={3};" +
                _str +
            "am={4};" +
            "ca={5};" +
            "ts={6};" +
            "ct={7};" +
            "th={8};" +
            "r=0." + GenerateRandom(RandomType.Num, 16), // 0.3483017170539391
            _cKey,
            _lang,
            type,
            _size,
            _magic,
            _chalapi,
            _ts,
            _chalstamp,
            _theme);

        var response = ResponseToString(url);

        if (response == null)
        {
            return null;
        }

        var result = response;

        return result;
    }

    private string _chid;
    private string _mediatype;

    private bool GetValuesChallenge(string response)
    {
        try
        {
            var pattern = "(?<=\"ACChallengeResult\":\\ \\{)[\\w\\W]*(?=\\ \"media_size\")";

            var match = Regex.Match(response, pattern).Value.Trim('\r', '\n');
            var split = match.Split(new[] { ",\n" }, StringSplitOptions.None);

            _chid = split[0].Split(':')[1].Trim(' ', '"');
            _mediatype = split[3].Split(':')[1].Trim(' ', '"');
        }
        catch (Exception e)
        {
            Answer = "error GetValuesChallenge";
            return false;
        }

        return true;
    }

    private byte[] ResponseGetAudio()
    {
        var url = string.Format(
            "http://api.solvemedia.com/papi/media?" +
            "c={0};" +
            "w=300;" +
            "h=150;" +
            "fg=000000;" +
            "bg=f8f8f8",
            _chid);

        var response = ResponseToByteArray(url);

        if (response == null)
        {
            return null;
        }

        return response;
    }

    private bool RecognizeAudio(byte[] mp3Array)
    {
        if (mp3Array.Length < 1000)
        {
            Answer = "bad mp3Array";
            return false;
        }

        var recognize = CapMonsterRecognize(mp3Array, CapMonsterKey, CapMonsterAddress);

        if (recognize == null) return false;

        Answer = recognize;
        AnswerToken = _chid;

        return true;
    }

    private string CapMonsterRecognize(byte[] mp3Array, string key, string address)
    {
        try
        {
            var boundary = GenerateRandom(RandomType.NumAndChars, 15);
            var mc = new MultipartContent(boundary)
            {
                {new StringContent("post"),  "method"},
                {new StringContent("19"),  "soft_id"},
                {new StringContent(key), "key"},
                {new StringContent("ZennoLab.AudioSolveMedia"), "CapMonsterModule"},
                {new BytesContent(mp3Array),  "file", "Captcha.png", "audio/mp3"}
            };

            var request = new HttpRequest();
            request.UserAgent = "TubeCast v1.0";
            request["Accept"] = "*/*";
            request["Accept-Language"] = "ru";
            request.Proxy = SetProxy();

            var response = request.Post(string.Format("http://{0}/in.php", address), mc).ToString();
            request.Close();

            if (response == "" || !response.Contains("OK"))
            {
                Answer = "CapMonster, error on post";
                return null;
            }

            var id = response.Split('|')[1];

            //---

            request = new HttpRequest();
            request.UserAgent = "TubeCast v1.0";
            request["Accept"] = "*/*";
            request["Accept-Language"] = "ru";
            request.Proxy = SetProxy();

            response = request.Get(string.Format("http://{0}/res.php?key={1}&action=get&id={2}", address, key, id)).ToString();
            request.Close();

            if (response == "" || !response.Contains("OK"))
            {
                Answer = "CapMonster, error on get";
                return null;
            }

            return response.Split('|')[1];
        }
        catch (HttpException e)
        {
            switch (e.Status)
            {
                case HttpExceptionStatus.Other:
                    Answer = "Неизвестная ошибка";
                    break;

                case HttpExceptionStatus.ProtocolError:
                    Answer = "Код состояния: " + (int)e.HttpStatusCode;
                    break;

                case HttpExceptionStatus.ConnectFailure:
                    Answer = "Не удалось соединиться с HTTP-сервером";
                    break;

                case HttpExceptionStatus.SendFailure:
                    Answer = "Не удалось отправить запрос HTTP-серверу";
                    break;

                case HttpExceptionStatus.ReceiveFailure:
                    Answer = "Не удалось загрузить ответ от HTTP-сервера";
                    break;
            }
        }
        catch (Exception e)
        {
            Answer = e.ToString();
        }

        return null;
    }

    private string GenerateRandom(RandomType type, int count)
    {
        char[] chars;

        switch (type)
        {
            case RandomType.Num:
                {
                    chars = "1234567890".ToCharArray();
                    break;
                }

            case RandomType.Chars:
                {
                    chars = "abcdefghijklmnopqrstuvwxyz".ToCharArray();
                    break;
                }

            default:
                {
                    chars = "1234567890abcdefghijklmnopqrstuvwxyz".ToCharArray();
                    break;
                }
        }

        var buf = new StringBuilder();
        var rnd = new Random();

        for (var i = 0; i < count; i++)
        {
            buf.Append(chars[rnd.Next(chars.Length)]);
        }

        return buf.ToString();
    }

    private ProxyClient SetProxy()
    {
        if (Proxy == "") return null;

        ProxyClient wp;

        var split = Proxy.Split('@');

        if (split.Length == 1)
        {
            var address = split[0].Split(':');

            var ip = address[0];
            var port = int.Parse(address[1]);

            if (ProxyType == ProxyTypeEnum.Socks)
            {
                wp = new Socks5ProxyClient(ip, port);
            }
            else
            {
                wp = new HttpProxyClient(ip, port);
            }
        }
        else
        {
            var credential = split[0].Split(':');
            var address = split[1].Split(':');

            var ip = address[0];
            var port = int.Parse(address[1]);

            var user = credential[0];
            var password = credential[1];

            if (ProxyType == ProxyTypeEnum.Socks)
            {
                wp = new Socks5ProxyClient(ip, port, user, password);
            }
            else
            {
                wp = new HttpProxyClient(ip, port, user, password);
            }
        }

        return wp;
    }
}

Как использовать
1. Закинуть в ExternalAssemblies xNet.dll

2. Добавить в рефы проекта эту dll


3. Добавить в OwnCode класс SolveMediaCaptcha, и добавить using xNet;


4. Создать объект типа SolveMediaCaptcha, инициализировать свойства необходимыми значениями и вызвать метод Recognize()


Что такое siteKey


Если капча разгадана, то в Answer будет находится ответ.
Если нет, то там же будет лежать описание ошибки.

Что такое AnswerToken.
Это токен нужен при отправке разгаданной капчи.
Т.е. помимо ответа, надо отправлять еще и его.

Еще одна плюшка.
Работа с CapMonster идет без использования зенковских методов, напрямую с помощью запросов.
Т.е. класс SolveMediaCaptcha не привязан к зенке, не используется ни одного ее метода.
Поэтому данный класс можно юзать как в зенке, так и перенести в свою прогу.

PS: Для тех кому лень делать копипаст прикладываю готовый шаб.))
 

Вложения

Artem1977

Client
Регистрация
31.10.2015
Сообщения
22
Благодарностей
2
Баллы
3
Подскажите, не могу понять почему когда вставляю в код прокси c логином и паролем smc.Proxy = "login:[email protected]:8888" выдается ответ "Не удалось соединиться с HTTP-сервером"? Без прокси все работает. Прокси рабочие, пробовал и соксы и шттп. Причем через простые гет запросы как здесь человек расписал, все работает.
 

swiniks

Client
Регистрация
19.02.2015
Сообщения
244
Благодарностей
171
Баллы
43
Разобрались сами это хорошо!
 
Последнее редактирование:

Artem1977

Client
Регистрация
31.10.2015
Сообщения
22
Благодарностей
2
Баллы
3
del
 
Последнее редактирование:

Artem1977

Client
Регистрация
31.10.2015
Сообщения
22
Благодарностей
2
Баллы
3
Разобрался. Нужно было в общем коде убрать прокси при обращении к капмонстру. Спасибо за наводку.
 

Dresskod

Client
Регистрация
08.09.2016
Сообщения
390
Благодарностей
139
Баллы
43
Вы будете удивлены, Но

2. Из ответа вытаскиваются данные ckey, magic, chalapi, chalstamp, lang, size, theme, type,
lang, size, theme, type - этот хлам вытаскивать не нужно. Он всегда один и тот же. Правда на кране Мовилбитс я встречал lang - es, хотя всюду он eng, но это роли не играет.

Я пошел еще дальше. magic - нахер не нужен. По моим наблюдениям - он создает грязь в картинке. В аудио - не могу сказать. Но мой шаб работает без него. Параметр С - внагляк пустой. То есть без него можно обойтись.

Наша цель - получить ЧИД. Кстати, ЧИД - это зашифрованный ответ. То есть если в капче пишет I LOVE YOU, то чид несет в себе этот ответ. По этому самому чиду сервер совлвемедия и сверяет ваш ответ.
 

Dresskod

Client
Регистрация
08.09.2016
Сообщения
390
Благодарностей
139
Баллы
43
Вот примеры трех разных ЧИДОВ, которые были получены для звукового файла из разных сайтов. При этом они были правильно разгаданы капмонстром. (В конце правильный ответ). НО почему они разные? Скорее всего они разные, потому что разный ІР сайта и временной штамп.

Код:
XKdYDtomrdIENU8bgrS8zX9APTC4lJjoVHVmZR.GHSjhE7.RI63KLRsRWzRv64S6sX-zSes4E560LdkVyQxuPOqqNnwJ31N1NmYoW4Lx8uTIPtEWBgyjcrboa0GWmFBql9RtxBvrQmwoxp1E8v9uGTI26rW3qjww2EaOMgRyF5R84P.8.1IkmXXNLGXK0yfGjjOZxmK4letnvDh8rNqBLih3uo0qln2vPS4DsuFv2d06bNoNTsChJx7ODQ5aB-TNr7XyIDxZvOQmSEVcgrS6gA*loveme

XKSpGtolXMYENU8bgrS7vH9APTC4lJjo5eKD.I1EsSenFhcWH-Wf0CYHMJQ2qLA6cBtoeScSmY0pK5c5bBmNaA1x3uiKdVeddTB.RWcKgBzaUfj9PKf6BxmYoCuyJNCN12cTWy3u.4Mo7GIkIgYS6iOUZUdq.TWZqVqnU-7F78-38w5OrHaBmydkVC5aBiKsP.da5gWdczcCJieah6qCU5uy8pGKEtAhUsd2TtJCjJZnKKwK0lXnqoAarBmtvF8kmuhwdjzWWV0mSEVcgrS6gA*loveme

XKeKzdomfxEENU8bgrS8kH9APTC4lJjosM-pOCI3IT.R-iozU93cTWZd0WsTmLLY4R-Ea-nQVCi42uMD9ahT.IFoBG6cENsWcyZILUNHGL5GHFmvGgbMS-xLv-VeLyqfZAM26qponY1yX0GXtkUg-AzItzRtRWYMytieeMLoU7qYo8HP3VcYXo69GUedcw0vUm9xsyYScqEM4sYKqDDN9Zn2Z37inSFD8Gf5fm67c6cIoK4TExivxjhN4mcNe5rw6csNd4XWOBQmSEVcgrS6gA*loveme
 

Dresskod

Client
Регистрация
08.09.2016
Сообщения
390
Благодарностей
139
Баллы
43
В своих исследованиях я продвинулся еще дальше. Взял я к примеру первый ЧИД с ответом, который был свежим и отправил его на сайт еще раз, не обращая внимания, что Солвемедия мне дала другой вопрос и ЧИД.

В течении первых трех минут солвемедия отвечала, что ЭТОТ ответ уже использовался.
После трех минут отвечала - ваш ответ устарел. Это естественно.
Когда я в ЧИДЕ поменял одну цифру или букву, то отвечала - база данных потерпела крушение.

==============================================================

Она такая, солвемедия.

Кстати меня заинтересовало, как вы расшифровали этот скрипт. http://api.solvemedia.com/papi/_puzzle.js
Поделитесь секретом. Возможно в нем генерируется вопрос, который солвемедия нам рисует на картинке?
 

Кто просматривает тему: (Всего: 1, Пользователи: 0, Гости: 1)