В данной статье рассмотрим создание авторегистрации email-ов на Яндексе. Для начала подготовим нужные для этого модули и функции:
RegExpr - класс для регулярных выражений SwinHttp - класс для работы с протоколами http и https uLkJSON - модуль для парсинга JSON
Функции:
function NameGen(count: integer=7): string; const a: array[0..1] of string=('aeiouy','bcdfghjklmnpqrstvwxz'); var i: integer; nm: byte; begin result:=''; for i := 0 to count-1 do begin nm:=Random(2); result:=result+a[nm][1+random(length(a[nm]))]; end; end;
Генерирует строку из случайных символов
function ereg_value(p,text: string; index: integer): string; var r: TRegExpr; begin result:=''; r:=TRegExpr.Create; try r.Expression:=p; if(r.Exec(text))then result:=r.Match[index]; finally r.Free; end; end;
Производит поиск выражения в строке, и возвращает найденное совпадение
function QueryHttps(url: string; post: string=''): AnsiString; var http:TSwinHttp; begin http:=TSwinHttp.Create(nil); http.InThread:=false; //Позволяет выводить запрос в отдельный поток. http.Request.Agent:='Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.0.15) Gecko/2009101601 Firefox/3.0.15'; http.Request.Headers.Add('Accept:image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, */*'); http.Request.Headers.Add('Accept-Language:ru'); http.Request.Headers.Add('Accept-Encoding:deflate'); try if post='' then http.Get(url) else begin http.Request.Headers.Add('Content-Type:application/x-www-form-urlencoded'); http.Post(url,post); end; SetLength(result,http.Response.Content.Size); http.Response.Content.Read(result[1],http.Response.Content.Size); finally http.Free; end; end;
Позволяет отправлять POST и GET запросы на веб-сервер
function YaMail(Text: string): string; var json,item:TlkJSONbase; i: integer; list: TlkJSONObject; begin result:=''; json:= TlkJSON.ParseText(Text); for i:=0 to json.Count-1 do begin item:=TlkJSONObject(json).child[i]; if TlkJSONobjectmethod(item).Name<>'logins' then Continue; list:=TlkJSONobject(TlkJSONobjectmethod(item).Objvalue); if TlkJSONobject(list).count=0 then exit; result:=VarToStr(tlkJSONlist(list).Child[random(TlkJSONobject(list).count-1)].Value); end; end;
Функция парсит JSON-выражение, и возвращает случайный элемент
procedure ToFile(str, filename: string); var f: TextFile; begin AssignFile(f,filename); Append(f); Writeln(f,str); CloseFile(f); end;
Записывает строку "str" в файл "filename"
function QueryFiles(url: string; var memory: TMemoryStream): boolean; var http:TSwinHttp; begin result:=false; http:=TSwinHttp.Create(nil); http.InThread:=false; http.Request.Agent:='Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.0.15) Gecko/2009101601 Firefox/3.0.15'; http.Request.Headers.Add('Accept:image/png,image/*;q=0.8,*/*;q=0.5'); http.Request.Headers.Add('Accept-Language:ru,en-us;q=0.7,en;q=0.3'); http.Request.Headers.Add('Accept-Encoding:gzip,deflate'); http.Request.Headers.Add('Accept-Charset:windows-1251,utf-8;q=0.7,*;q=0.7'); http.Request.Headers.Add('Connection:keep-alive'); try http.Get(url); if http.Response.Code=200 then begin memory.LoadFromStream(http.Response.Content); result:=true; end; finally http.Free; end; end;
if is_phrase=true then multi.AddFormField('phrase','1'); if is_regsense=true then multi.AddFormField('regsense','1'); if is_numeric=true then multi.AddFormField('numeric','1'); if min_len>0 then multi.AddFormField('min_len',inttostr(min_len)); if max_len>0 then multi.AddFormField('max_len',inttostr(max_len));
http:=TIdHTTP.Create(nil); tmpstr:=http.Post('http://antigate.com/in.php',multi); http.Free; captcha_id:=''; if strpos(Pchar(tmpstr),'ERROR_')<>nil then begin result:=tmpstr; exit; end; if strpos(Pchar(tmpstr),'OK|')<>nil then captcha_id:=AnsiReplaceStr(tmpstr,'OK|',''); if captcha_id='' then result:='ERROR: bad captcha id'; for i:=0 to 20 do begin sleep(3000); http:=TIdHttp.Create(nil); tmpstr:=http.Get('http://antigate.com/res.php?key='+apikey+'&action=get&id='+captcha_id); http.Free; if strpos(Pchar(tmpstr),'ERROR_')<>nil then begin result:=tmpstr; exit; end; if strpos(Pchar(tmpstr),'OK|')<>nil then begin result:=AnsiReplaceStr(tmpstr,'OK|',''); exit; end; end; result:='ERROR_TIMEOUT'; end;
Стандартная функция взятая из исходников предоставленых сервисом antigate. Позволит распознавать капчу Яндекса.
Предварительные подготовки совершены, можно приступить к созданию основной составляющей. Откроем в браузере адрес http://passport.yandex.ru/passport?mode=register, введём произвольные данные в поля, и с помощью Http Analyzer посмотрим на запрос. После ввода имени и фамилии, страница посылает запрос, подбирая логин на основе наших данных. Ответом на это является страница, состоящая из описания на языке JSON:
logins содержит в себе набор возможных логинов. Для выбора какого-либо логина предусмотрена функция YaMail. Нажимаем на кнопку "Дальше" для продолжения регистрации. Через анализатор видно, что в запросе присутствует ещё одна переменная idkey:
Она содержит в себе ключ, который можно найти из строки "". Для этого достаточно воспользоваться функцией ereg_value:
ereg_value('"idkey" value="(.*?)"',content,1);
После передачи параметров на сервер получаем новую страницу, на которой необходимо ввести логин, пароль, секретный вопрос/ответ и капчу. Изображение содержит в своём адресе ключ idkey. Адрес изображения вычисляется аналогичную предыдущему действию:
Теперь нужно скачать изображение, и отправить его на сервер antigate:
if QueryFiles('http://passport.yandex.ru/digits?idkey='+ereg_value('idkey=([^"]+)',content,1),image) then begin code:=recognize(image,antigate,false,false,true,6,6); end;
После того, как антигейт возвратил значение, проверим есть ли в нём приставка "ERROR", чтобы приостановить или продолжить регистрацию. После успешной проверки необходимо создать ещё два параметра - ответ на секретный вопрос, и собственно сам вопрос. Количество вопросов в яндексе ограничено, и они содержат номера от 1 до 9, значит просто присвоим переменной случайное значение, а ответ создадим с помощью функции NameGen:
q:=1+random(9); hint:=NameGen(5);
Пароль, имя и фамилию создадим аналогично ответу на секретный вопрос:
Для проверки успешной регистрации, посмотрим есть ли на странице капча. Если она есть - значит при запросе возникла ошибка, если нет - значит сохраним новой логин и пароль в файл.
Полная процедура регистрации:
type TYandex=record login: string; password: string; end; // тип данных, содержит логин и пароль
function YaReg(antigate: string): TYandex; // antigate - ключ для работы с сервисом var content: string; idkey: string; name: string[7]; family: string[7]; mail: string; code: string[6]; password: string[10]; hint: string[5]; q: byte; image: TMemoryStream; begin result.login:=''; content:= QueryHttps('http://passport.yandex.ru/passport?mode=register'); // первый запрос, для получения idkey idkey:=ereg_value('"idkey" value="(.*?)"',content,1); name:=NameGen; family:=NameGen; mail:=YaMail(QueryHttps( 'http://passport.yandex.ru/passport?mode=constructlogin&login=&iname='+ name+'&fname='+family)); // находим idkey, генерируем имя и фамилию, создаём логин if mail='' then exit; // step2 content:= QueryHttps('https://passport.yandex.ru/passport?mode=register' ,'idkey='+idkey+'&step=one&filled=yes&fresh=1&iname='+ name+'&fname='+family+'&login='+mail+'&done='+AnsiToUtf8('Дальше')); // переходим на второй шаг if pos('digits?idkey',content)<>0 then begin //если картинка присутсвует на странице, значит можно продолжить image:=TMemoryStream.Create; try if QueryFiles('http://passport.yandex.ru/digits?idkey='+ ereg_value('idkey=([^"]+)',content,1),image) then begin code:=recognize(image,antigate,false,false,true,6,6); if pos('ERROR',code)<>0 then exit; password:=NameGen(10); hint:=NameGen(5); q:=1+random(9); content:= QueryHttps('https://passport.yandex.ru/passport?mode=register', 'idkey='+ereg_value('idkey=([^"]+)',content,1)+ '&step=two&filled=yes&login='+mail+'&fname='+ family+'&iname='+name+'&time=0'+ '&gmt_offset=-180&passwd='+password+ '&passwd2='+password+'&hintq='+ IntToStr(q)+'&udhintq='+ '&hinta='+hint+'&hintasave='+hint+'&questnum='+IntToStr(q)+ '&hintqsave=&email=&phonenumber='+ '&code='+code+'&agreed=yes'); // распознаём картинку, генерируем пароль, ответ на вопрос, // и отправляем страницу на сервер if pos('digits?idkey',content)=0 then begin result.login:=mail; result.password:=password; // Если капчи на странице больше нет, значит регистрация успешна end; end; finally image.Free; end; end; end;
var r: TYandex;
begin randomize; r:=YaReg(ваш_код_antigate); if r.login<>'' then ToFile(r.login+':'+r.password,'save.txt'); readln; end.