Почему я не могу получить изображение AOL CAPTCHA в моей программе Delphi?

StackOverflow https://stackoverflow.com/questions/2724233

  •  02-10-2019
  •  | 
  •  

Вопрос

Новый демонстрационный код:

Я пытаюсь получить изображение CAPTCHA из AOL, и я продолжаю получать ошибку 418.

unit imageunit;
///
///  https://new.aol.com/productsweb/
///
interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, IdIOHandler, IdIOHandlerSocket, IdIOHandlerStack, IdSSL,
  IdSSLOpenSSL, IdIntercept, IdZLibCompressorBase, IdCompressorZLib,
  IdCookieManager, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
  IdHTTP,jpeg,GIFImg, ExtCtrls, PerlRegEx;

type
  TForm2 = class(TForm)
    IdHTTP1: TIdHTTP;
    IdCookieManager1: TIdCookieManager;
    IdCompressorZLib1: TIdCompressorZLib;
    IdConnectionIntercept1: TIdConnectionIntercept;
    IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL;
    Panel1: TPanel;
    Image1: TImage;
    Panel2: TPanel;
    Button1: TButton;
    PerlRegEx1: TPerlRegEx;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

function getaimcaptchaimage(data:string):string;
var
    Regex: TPerlRegEx;
    ResultString: string;
begin
Regex := TPerlRegEx.Create(nil);
Regex.RegEx := '<img src="/productsweb/WordVerImage?(.*?)"';
Regex.Options := [preCaseless];
Regex.Subject := data;
if Regex.Match then begin
    if Regex.SubExpressionCount >= 1 then begin
        ResultString := Regex.SubExpressions[1];
    end;
  result:=Resultstring;
end;
end;


procedure TForm2.Button1Click(Sender: TObject);
var
  JPI : TJPEGImage;
  streamdata:TMemoryStream;
  SStream: Tstringstream;
  website:string;
begin
  streamdata := TMemoryStream.Create;
  SStream := tstringstream.Create ( '' );

  try
  idhttp1.Get('https://new.aol.com/productsweb/',SStream);
  memo1.Text:=UTF8ToWideString ( SStream.DataString );
  website:='https://new.aol.com/productsweb/WordVerImage'+getaimcaptchaimage( UTF8ToWideString ( SStream.DataString ));
  form2.Caption:=website;
  idhttp1.Get(website, Streamdata);
          Except
          { Handle exceptions }
          On E : Exception Do
               Begin
                MessageDlg('Exception: '+E.Message,mtError, [mbOK], 0);
               End;

          End;

  //https://new.aol.com/productsweb/WordVerImage?20890843
  //https://new.aol.com/productsweb/WordVerImage?91868359


  ///
  ///  gives error 418 unused
  ///

  streamdata.Position := 0;
  JPI := TJPEGImage.Create;
  Try
  JPI.LoadFromStream ( streamdata );
  Finally
  Image1.Picture.Assign ( JPI );
  JPI.Free;
  streamdata.Free;
  End;

end;

end.

Форма:

object Form2: TForm2
  Left = 0
  Top = 0
  Caption = 'Form2'
  ClientHeight = 247
  ClientWidth = 480
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Panel1: TPanel
    Left = 0
    Top = 41
    Width = 480
    Height = 206
    Align = alClient
    TabOrder = 0
    object Image1: TImage
      Left = 1
      Top = 1
      Width = 478
      Height = 115
      Align = alClient
      ExplicitLeft = 5
      ExplicitTop = 17
      ExplicitWidth = 200
      ExplicitHeight = 70
    end
    object Memo1: TMemo
      Left = 1
      Top = 116
      Width = 478
      Height = 89
      Align = alBottom
      TabOrder = 0
      ExplicitLeft = 80
      ExplicitTop = 152
      ExplicitWidth = 185
    end
  end
  object Panel2: TPanel
    Left = 0
    Top = 0
    Width = 480
    Height = 41
    Align = alTop
    TabOrder = 1
    object Button1: TButton
      Left = 239
      Top = 6
      Width = 75
      Height = 25
      Caption = 'Button1'
      TabOrder = 0
      OnClick = Button1Click
    end
  end
  object IdHTTP1: TIdHTTP
    Intercept = IdConnectionIntercept1
    IOHandler = IdSSLIOHandlerSocketOpenSSL1
    MaxAuthRetries = 100
    AllowCookies = True
    HandleRedirects = True
    RedirectMaximum = 100
    ProxyParams.BasicAuthentication = False
    ProxyParams.ProxyPort = 0
    Request.ContentLength = -1
    Request.Accept = 
      'image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-s' +
      'hockwave-flash, application/cade, application/xaml+xml, applicat' +
      'ion/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-' +
      'application, */*'
    Request.BasicAuthentication = False
    Request.Referer = 'http://www.yahoo.com'
    Request.UserAgent = 
      'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.1) Gecko/201001' +
      '22 firefox/3.6.1'
    HTTPOptions = [hoForceEncodeParams]
    CookieManager = IdCookieManager1
    Compressor = IdCompressorZLib1
    Left = 40
    Top = 160
  end
  object IdCookieManager1: TIdCookieManager
    Left = 360
    Top = 136
  end
  object IdCompressorZLib1: TIdCompressorZLib
    Left = 408
    Top = 56
  end
  object IdConnectionIntercept1: TIdConnectionIntercept
    Left = 304
    Top = 72
  end
  object IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL
    Intercept = IdConnectionIntercept1
    MaxLineAction = maException
    Port = 0
    DefaultPort = 0
    SSLOptions.Mode = sslmUnassigned
    SSLOptions.VerifyMode = []
    SSLOptions.VerifyDepth = 0
    Left = 192
    Top = 136
  end
  object PerlRegEx1: TPerlRegEx
    Options = []
    Left = 120
    Top = 56
  end
end

Если вы идете в https://new.aol.com/productsweb/Вы заметите, что CAPTCHA Image имеет URL, как https://new.aol.com/productsweb/wordverimage?91868359.

Я положил этот URL в поле редактирования и получите ошибку.

Что не так с этим кодом?

Это было полезно?

Решение

У моих старых проектов я был прочитан CAPTCHA из Интернета. Я сделал это со встроенным веб-процедурами компонентов веб-браузера. Поэтому, если вы можете прочитать временные интернет-файлы из вашего кода, вы можете прочитать данные изображения из кэша. Я добавил простой код ниже,

Функции GetCachedFileFlfromurl и ClearallArsEntries объявляются в подразделении TembedDedWebBrowser. Я использовал только мой скопированный код в моем решении для более низкого размера EXE. Но вы можете использовать компонент обновленный источник. Компонент является открытым исходным кодом.

uses
 WinInet;

function GetCachedFileFromURL(strUL: string; var strLocalFile: string): Boolean;
var
   lpEntryInfo: PInternetCacheEntryInfo;
   hCacheDir: LongWord;
   dwEntrySize: LongWord;
   dwLastError: LongWord;
begin
   Result := False;
   dwEntrySize := 0;
  // Begin the enumeration of the Internet cache.
   FindFirstUrlCacheEntry(nil, TInternetCacheEntryInfo(nil^), dwEntrySize);
   GetMem(lpEntryInfo, dwEntrySize);
   hCacheDir := FindFirstUrlCacheEntry(nil, lpEntryInfo^, dwEntrySize);
   if (hCacheDir <> 0) and (strUL = lpEntryInfo^.lpszSourceUrlName) then
      begin
         strLocalFile := lpEntryInfo^.lpszLocalFileName;
         Result := True;
      end;
   FreeMem(lpEntryInfo);
   if Result = False then
      repeat
         dwEntrySize := 0;
      // Retrieves the next cache group in a cache group enumeration
         FindNextUrlCacheEntry(hCacheDir, TInternetCacheEntryInfo(nil^), dwEntrySize);
         dwLastError := GetLastError();
         if (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
            begin
               GetMem(lpEntryInfo, dwEntrySize);
               if (FindNextUrlCacheEntry(hCacheDir, lpEntryInfo^, dwEntrySize)) then
                  begin
                     if strUL = lpEntryInfo^.lpszSourceUrlName then
                        begin
                           strLocalFile := lpEntryInfo^.lpszLocalFileName;
                           Result := True;
                           Break;
                        end;
                  end;
               FreeMem(lpEntryInfo);
            end;
      until (dwLastError = ERROR_NO_MORE_ITEMS);
end;

procedure TForm1.ClearCache();
begin
  SearchPattern := spAll;
  ClearAllEntries;
end;

Применение

procedure TForm1.Button1Click(Sender: TObject);
var
 fname:string;
 jpImg:TJPEGImage;
begin
  ClearCache;
  try
   jpImg:=TJPEGImage.Create; 
   GetCachedFileFromURL('https://ebildirge.ssk.gov.tr/WPEB/PG',fname);
   jpImg.LoadFromFile(fname);
  finally
   FreeAndNil(jpgImg);
  end;
end;

Другие советы

Есть привлечение печенья. Если вы идете прямо к URL CAPTCHA https://new.aol.com/productsweb/wordverimage?91868359. в браузере, который не посетил https://new.aol.com/productsweb/ Тогда вы получаете (после обновления):

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> 
<html><head> 
<title>418 unused</title> 
</head><body> 
<h1>unused</h1> 
<p>The server encountered an internal error or
misconfiguration and was unable to complete
your request.</p> 
<p>Please contact the server administrator,
 null and inform them of the time the error occurred,
and anything you might have done that may have
caused the error.</p> 
<p>More information about this error may be available
in the server error log.</p> 
</body></html> 

Но если вы посетите https://new.aol.com/productsweb/ Сначала вы получите изображение. Очистить cookie, и вы снова получите ошибку (хотя, как указал Франсуа, вы не получаете ответа сначала, а затем на обновлении вы получаете изображение.)

Indy поддерживает файлы cookie, поэтому вам нужно будет добавить поддержку файлов cookie, а затем либо получить cookie, посещая ProductsSweb сначала или имитировать его из известного значения.

Вы заметите, что сгенерированный образ не основан на номере, передаваемом в качестве одного параметра, но и файла cookie. Имейте два разных браузера (Chrome и Firefox), которые у каждого есть разные файлы cookie, а затем посетите один и тот же URL CAPTCHA, и вы получите два разных изображения.

Любопытно, что вы пытаетесь сделать с этим.

Я думаю, что это означает «уйти». Как-то, через заголовки или что-то в вашем запросе, это определяет, что вы пахните как бот. Может быть, потому что вы просите образе, что он знает, это не просто сделало для вас. Да, это, наверное, это. Если я пойду к своему URL в моем браузере, я тоже получаю 418.

Это не ваш код. Попробуйте в браузере ....
(Вы, очевидно, нужно удалить пробелы из «HTTP S» ...)

Этот URL https://new.aol.com/productsweb/ Очевидно, нужно вызывать, прежде чем вы сможете получить изображение CAPTCHA. В противном случае вы получите (неправильную) ошибку 418 Unused.
Иногда я должен был попробовать дважды с изображением #, как я впервые получил 420 Unused ошибка...

Вам лучше спросить их, так как их API на самом деле не кажется стабильным ...

Re: шутка HTTP 418. Если вы хотите повеселиться с кодами ошибок HTTP, прочитанные на Веб-разработчик и его подруга

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top