Perché non è possibile recuperare un'immagine captcha AOL nel mio programma Delphi?
Domanda
Il nuovo codice demo:
Sto cercando di ottenere l'immagine captcha da un'AOL, e io continuo a ricevere un errore 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.
Modulo:
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
Se si va a https://new.aol.com/productsweb/ si noterà l'immagine captcha ha un url del tipo https://new.aol.com/productsweb/ WordVerImage? 91868359
ho messo l'URL nella casella di modifica e ottenere un errore.
Cosa c'è di sbagliato con questo codice?
Soluzione
i miei vecchi progetti ero captcha readed dal web. Ho fatto questo con le procedure di cache componente del browser Web incorporato. quindi se si può leggere i file temporanei Internet dal proprio codice è possibile leggere i dati di immagine dalla cache. ho aggiunto un semplice codice al di sotto,
il GetCachedFileFromURL e funzioni ClearAllEntries è declarated nell'unità TEmbeddedWebBrowser. Ero abituata solo il mio codice copiato nella mia soluzione per dimensione exe inferiore. ma è possibile utilizzare sorgente aggiornato componente. il componente è open source.
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;
utilizzo
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;
Altri suggerimenti
C'è un cookie coinvolti. Se si va dritto al captcha URL https://new.aol.com/productsweb/WordVerImage?91868359 in un browser che non ha visitato https://new.aol.com/productsweb/ quindi si ottiene (dopo un refresh):
<!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>
Ma se si visita https://new.aol.com/productsweb/ prima, poi si otterrà un'immagine. Chiaro il cookie e si ottiene di nuovo l'errore (anche se, come Francois ha sottolineato, si ottiene alcuna risposta, e poi su Aggiorna si ottiene l'immagine.)
supporti Indy cookie, quindi sarà necessario per aggiungere il supporto per i cookie, e poi o ottenere il cookie visitando il productsweb prima, o simulare da un valore noto.
Si noterà che l'immagine generata non è basato sul numero passato come parametro solo, ma anche il cookie. Avere due browser diversi (Chrome e Firefox) che hanno ciascuno un cookie diverso, e quindi visitare lo stesso URL captcha e si ottengono due immagini diverse.
Curioso ciò che si sta cercando di realizzare con questo.
Credo che significa "andare via". In qualche modo, attraverso le intestazioni o qualcosa del genere nella vostra richiesta, è determinante che puzzi come un bot. Forse perché si sta chiedendo per un'immagine che si sa che non si è limitato a fare per te. Sì, questo è probabilmente. Se vado al tuo URL nel browser, ricevo un 418 anche.
Non è il tuo codice. provare in un browser ....
(È, ovviamente, necessario rimuovere gli spazi vuoti da 'h t t p s' ...)
Questa https://new.aol.com/productsweb/
URL deve evidentemente essere chiamato prima di poter ottenere un'immagine captcha. In caso contrario, si ottiene un (impropria) 418 Unused
errore.
A volte ho dovuto provare due volte con l'immagine # come ho ottenuto un errore di 420 Unused
...
È meglio chiedere loro, come loro API non sembra veramente stabile ...
RE: il http 418 scherzo. Se volete un po 'di divertimento con il http codici di errore di lettura su Developer A Web e la sua ragazza (s)