В данной статье рассмотрим создание авторегистрации 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;
 

Скачивает и записывает файл в поток MemoryStream.

function recognize(Picture: TMemoryStream; apikey: string; is_phrase: boolean; is_regsense: boolean; is_numeric: boolean; min_len: integer; max_len: integer): string;
var
ftype,tmpstr,captcha_id: String;
i: integer;
http: TIdHTTP;
multi: Tidmultipartformdatastream;
begin
ftype:='image/pjpeg';
multi:=Tidmultipartformdatastream.Create;
multi.AddFormField('method','post');
multi.AddFormField('key',apikey);
multi.AddObject('file','image/pjpeg',Picture,'file.jpeg');

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:

{
    "input_login":"",
    "input_login_status":"",
    "logins":[
        "name.family2011",
        "family.name2010",
        "family.name2011",
        "f.name2010",
        "f.name2011"
    ],
    "reqid":"273228"
}
 

logins содержит в себе набор возможных логинов. Для выбора какого-либо логина предусмотрена функция YaMail. Нажимаем на кнопку "Дальше" для продолжения регистрации. Через анализатор видно, что в запросе присутствует ещё одна переменная idkey:

idkey=16o1266857610h7J1vaa_c
step=one
filled=yes
fresh=5
iname=family
fname=name
login=name.family2011
done=%D0%94%D0%B0%D0%BB%D1%8C%D1%88%D0%B5%C2%A0%E2%86%92

Она содержит в себе ключ, который можно найти из строки "<input type="hidden" name="idkey" value="16o1266857610h7J1vaa_c" />". Для этого достаточно воспользоваться функцией ereg_value:

ereg_value('"idkey" value="(.*?)"',content,1);
 

После передачи параметров на сервер получаем новую страницу, на которой необходимо ввести логин, пароль, секретный вопрос/ответ и капчу.
Изображение содержит в своём адресе ключ idkey. Адрес изображения вычисляется аналогичную предыдущему действию:

image:='http://passport.yandex.ru/digits?idkey='+ereg_value('idkey=([^"]+)',content,1);
 

Теперь нужно скачать изображение, и отправить его на сервер 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);
 

Пароль, имя и фамилию создадим аналогично ответу на секретный вопрос:

name:=NameGen;
family:=NameGen;
password:=NameGen(10);
 

Теперь, когда все приготовления сделаны, подготовим запрос. Выглядит он следующим образом:

idkey=10j1266858322kM4ZKKHZ7 // idkey
step=two
filled=yes
login=name.family2011 //mail
fname=name // name
iname=family // family
time=1266857108941 // time, отправим 0
gmt_offset=-180
passwd=123123 // пароль
passwd2=123123 // подтверждение
hintq=1 // номер вопроса
udhintq=
hinta=123123 // ответ на вопрос
hintasave=123123
questnum=1
hintqsave=
email=
phonenumber=
code=456486 // введённый код
agreed=yes
newform=%D0%97%D0%B0%D1%80%D0%B5%D0%B3%D0%B8%D1%81%D1%82%D1%80%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C

Составленный запрос:

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')
 

Для проверки успешной регистрации, посмотрим есть ли на странице капча. Если она есть - значит при запросе возникла ошибка, если нет - значит сохраним новой логин и пароль в файл.

Полная процедура регистрации:

 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.

// инициализация, и сохранение в файл save.txt
 


Скачать исходный код и библиотеки

Если Вам нужен компьютер или ноутбук, обратитесь в интернет магазин компьютерной техники по адресу shop.bigmir.net. Здесь Вы сможете собрать себе компьютер, и купить оргтехнику.