如何在 TImage 上显示 Div 背景图像

How to show a Div background-image on TImage

我有一个从各个站点收集信息以填充我的数据库的应用程序。我被困在这个有验证码的 site 上。我需要为我的用户显示验证码。问题是图像在 DIV.

中的 background-image

DIV idcaptchaCodigo

我知道如何通过 ID 和名称获取元素,使用值等。但是我不知道如何获取这张图片或 url。

提前致谢

验证码非常具体,如果您使用他的网站 link,它会更改其文本。

我前几天解开了这个谜团,唯一的办法就是截图了..

这是我的几行代码(它不是很漂亮,我仍在进行微调,但工作完美):

主程序,将位图保存到 TImage:

 procedure TForm1.elscreenshot(var elid:string;imid:integer);  //elementID  and ImageID
    var
      doc : IHTMLDocument2;
      imgRange : IHTMLControlRange;
      img : IHTMLImgElement;
      render : IHTMLElementRender;

      bmp : TBitmap;
      _hdc : HDC;

      img_NameProp : string;
      img_idx,ii : Integer;
    begin
      doc := embeddedwb1.Document as IHTMLDocument2;
      imgRange := ( doc.body as HTMLBody ).createControlRange as IHTMLControlRange;

      for ii := imid to imid do
        begin
        img_idx:=ii;
    repeat
          img := doc.images.item( img_idx, EmptyParam ) as IHTMLImgElement;
          application.ProcessMessages;
          inc(img_idx);
    until pos('andom',img.href)>0;   // USUALLY CAPTCHA HAS "RANDOM" WORD IN ITS HREF   - IN YOUR CASE IT's name is uuidCaptcha 




   img_NameProp := Utf8ToAnsi( UTF8Encode( img.nameProp ) );


        begin
          render := ( img as IHTMLElementRender );

          bmp := TBitmap.Create;
          try
            bmp.Width := img.Width;
            bmp.Height := img.Height;

            _hdc := bmp.Canvas.Handle;

            render.DrawToDC( _hdc );

            Image1.Picture.Assign( bmp );   // <- HERE is happening the screenshot
             cxtextedit1.setfocus;  //focusing my edit box for user interaction
          finally
            bmp.Free;
          end;
          break;
        end;
    end;
end;

我需要的另一个代码(获取元素 ID 和图像 ID:

procedure TForm1.getcaptcha(var i:integer);

//过程体中的函数:

function GetElementsByClassName(ADoc: IDispatch; const strClassName: string): IHTMLElement;
var
  vDocument: IHTMLDocument2;
  vElementsAll: IHTMLElementCollection;
  vElement: IHTMLElement;
  I, ElementCount: Integer;
begin
  Result := nil;
  ElementCount := 0;
  if not Supports(ADoc, IHTMLDocument2, vDocument) then
    raise Exception.Create('Invalid HTML document');
  vElementsAll := vDocument.all;
  for I := 0 to vElementsAll.length - 1 do
    if Supports(vElementsAll.item(I, EmptyParam), IHTMLElement, vElement) then
      if SameText(vElement.className, strClassName) then
      begin
        Result := vElement;
      end;
end;

程序

  var
        x:integer;
           Doc3 :  IHTMLDocument3;
          cpt : ihtmlelement;
          el:string;
        begin

             Doc3 := EmbeddedWB1.Document as IHTMLDocument3;
        cpt:=nil;
        repeat application.processmessages;until embeddedwb1.ReadyState>2;
        repeat
        application.ProcessMessages;
          cpt:=getelementsbyclassname(doc3,'input-captcha input-text');  //here You must fint how its Your element named  (use getinnertext and parse, or something similar
        until cpt<>nil;  //this repeat..until waits for captcha image to be loaded, usually it takes longer than the rest of webpage code (on slower connections)
          if assigned(cpt) then begin
          el:=cpt.id;
        elscreenshot(el,x);
        end;

        end;

希望对您有所帮助:)

您无法获取此图片的URL,因为它不是通过标准HTML协议传输的。

这种场景下的图片通常会以数据流的形式传输,然后在客户端正常显示。

在您的情况下,图像实际上是作为 base64 字符串从服务器传输到您的计算机,然后在您的计算机上解码为实际图像。

您可以巧妙地使用 Google Chrome developer tools 来获取此信息,可以使用 F12 键激活。

以这种方式实现的主要原因是为了防止网络机器人克服 captcha 安全性。

事实上,大多数使用 captcha 保护系统的网站都是有原因的。

最常见的原因是通过在网站上发布各种垃圾邮件内容来防止网络启动对服务器造成破坏。

另一个原因是为了防止他们下载所有站点内容而使服务器过载。

事实上,您试图从该站点收集信息并将其存储在您自己的数据库中可能会直接违反站点使用协议。

基于上述网站与管辖系统相关联,我敢打赌,不应以任何方式复制或重新分发网站上发布的任何信息。

图像是 base64 encoding ,您需要将其从 html 代码中提取出来并将其转换为位图不要忘记将 uuidCaptcha 与您的 post 一起发送request 是标识您在程序中输入的验证码的 ID。

uses Soap.EncdDecd, IdHTTP, System.StrUtils, pngimage;

Function _ExtractBetweenTags(Const s, LastTag, FirstTag: string; TrimTags: Boolean = True): string;
var
  pLast,pFirst,pNextFirst : Integer;
begin
  pFirst := Pos(FirstTag,s);
  pLast := Pos(LastTag,s);
  while (pLast > 0) and (pFirst > 0) do begin
    if (pFirst > pLast) then // Find next LastTag
      pLast := PosEx(LastTag,s,pLast+Length(LastTag))
    else
    begin
      pNextFirst := PosEx(FirstTag,s,pFirst+Length(FirstTag));
      if (pNextFirst = 0) or (pNextFirst > pLast) then begin
        if TrimTags then begin
          Result := Trim(StringReplace(Trim(Copy(s,pFirst,pLast-pFirst+Length(LastTag))), LastTag, '', [rfReplaceAll, rfIgnoreCase]));
          Result := Trim(StringReplace(Result, FirstTag, '', [rfReplaceAll, rfIgnoreCase]));
        end
        else
        Result := Trim(Copy(s,pFirst,pLast-pFirst+Length(LastTag)));
        Exit;
      end
      else
        pFirst := pNextFirst;
    end;
  end;
  Result := '';
end;

procedure TForm4.btn1Click(Sender: TObject);
var
  Input: TStringStream;
  Output: TBytesStream;
  sTmp, uuidCaptcha, captchaCodigo: string;
  IdHTTP: TIdHTTP;
  Graphic: TGraphic;
begin
  IdHTTP := TIdHTTP.Create(nil);
  try
    IdHTTP.AllowCookies := True;
    IdHTTP.HandleRedirects := True;
    IdHTTP.Request.Connection := 'keep-alive';
    IdHTTP.Request.UserAgent := 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36';
    sTmp := IdHTTP.Get('http://www.tjms.jus.br/cpopg5/imagemCaptcha.do');
    uuidCaptcha := _ExtractBetweenTags(sTmp, '"}', '"uuidCaptcha": "'); // You need this when you send the post request
    captchaCodigo := _ExtractBetweenTags(sTmp, '", "labelValorCaptcha":', 'base64,');
    mmo1.Lines.Add(captchaCodigo);
    Input := TStringStream.Create(captchaCodigo, TEncoding.ASCII);
    try
      Output := TBytesStream.Create;
      try
        Soap.EncdDecd.DecodeStream(Input, Output);
        Output.Position := 0;
        Graphic := TPngImage.Create;
        try
          Graphic.LoadFromStream(Output);
          img1.Picture.Bitmap.Assign(Graphic);  // Your Image loads here
        finally
          Graphic.Free;
        end;
      finally
        Output.Free;
      end;
    finally
      Input.Free;
    end;
  finally
    IdHTTP.Free;
  end;
end;