为什么我无法在 Delphi 程序中获取 AOL 验证码图像?
新的演示代码:
我试图从 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/ 您会注意到验证码图像的网址类似于 https://new.aol.com/productsweb/ WordVerImage?91868359
我将该 URL 放入编辑框中并收到错误。
这段代码有什么问题?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这里涉及到一个cookie。如果您直接访问验证码 URL https://new.aol.com/productsweb/WordVerImage?91868359 在未访问过 https://new.aol.com/productsweb/ 然后你会得到(刷新后):
但是如果你访问 https://new.aol.com/productsweb/ 首先,你会得到一张图像。清除 cookie,您会再次收到错误(尽管正如 Francois 指出的,您首先没有得到任何响应,然后在刷新时您会得到图像。)
Indy 支持 cookie,因此您需要添加对 cookie 的支持,然后要么得到首先访问 productsweb 来获取 cookie,或者从已知值模拟它。
您会注意到,生成的图像不仅基于作为参数传递的数字,还基于 cookie。有两个不同的浏览器(Chrome 和 Firefox),每个浏览器都有不同的 cookie,然后访问相同的验证码 URL,您将获得两个不同的图像。
好奇你想用这个来完成什么。
There is a cookie involved. If you go straight to the captcha URL https://new.aol.com/productsweb/WordVerImage?91868359 in a browser that has not visited https://new.aol.com/productsweb/ then you get (after a refresh):
But if you visit https://new.aol.com/productsweb/ first, then you will get an image. Clear the cookie and you get the error again (although as Francois pointed out, you get no response first, and then on refresh you get the image.)
Indy supports cookies, so you will need to add support for cookies, and then either get the cookie by visiting the productsweb first, or simulate it from a known value.
You will notice that the image generated is not based on the number passed as a parameter alone, but also the cookie. Have two different browsers (Chrome and Firefox) that each have a different cookie, and then visit the same captcha URL and you will get two different images.
Curious what you are trying to accomplish with this.
我认为这意味着“走开”。不知何故,通过标头或请求中的某些内容,它确定您闻起来像机器人。也许是因为你要求一张图片,它知道它不仅仅适合你。
是的,大概就是这样。如果我在浏览器中访问您的 URL,也会收到 418。
I think it means "go away". Somehow, through headers or something in your request, it's determining that you smell like a bot. Maybe because you're asking for an image that it knows it didn't just make for you.
Yeah, that's probably it. If I go to your URL in my browser, I get an 418 too.
这不是你的代码。在浏览器中尝试...
(显然,您需要删除“http s”中的空白...)
显然需要先调用此 URL
https://new.aol.com/productsweb/
,然后才能获取验证码图像。否则,您会收到(不正确的)错误418 Unused
。有时我不得不对图像尝试两次,因为我第一次收到
420 Unused
错误...你最好问他们,因为他们的 API 看起来不太稳定...
RE:http 418 笑话。如果您想了解 http 错误代码,请阅读一位 Web 开发人员和他的女朋友(s)
It's not your code. try in a browser....
(You obviously need to remove the blanks from 'h t t p s'...)
This URL
https://new.aol.com/productsweb/
apparently needs to be called before you can get a captcha image. Otherwise you get an (improper) error418 Unused
.Sometimes I had to try twice with the image # as I first got a
420 Unused
error...You better ask them, as their API does not really seem stable...
RE: the http 418 joke. If you want some fun with the http error codes read on A Web Developer and His Girlfriend(s)
在我的旧项目中,我从网络上读取了验证码。我通过嵌入式网络浏览器组件缓存程序完成了此操作。因此,如果您可以从代码中读取临时互联网文件,您就可以从缓存中读取图像数据。我在下面添加了一个简单的代码,
GetCachedFileFromURL 和 ClearAllEntries 函数在 TEmbeddedWebBrowser 单元中声明。我在解决方案中仅使用了复制的代码,以减小 exe 大小。但您可以使用组件更新源。该组件是开源的。
用法
at my old projects i was readed captcha from web. i done this with embedded web browser component cache procedures. so if you can read temporary internet files from your code you can read the image data from cache. i added a simple code to below,
the GetCachedFileFromURL and ClearAllEntries functions is declarated in TEmbeddedWebBrowser unit. i was used only my copied code in my solution for lower exe size. but you can use component updated source. the component is open source.
usage