Disclosure Statement: This site contains affiliate links, which means that I may receive a commission if you make a purchase using these links. As an eBay Partner, I earn from qualifying purchases.

Get captcha image

Post Reply
yaser6403
Posts: 1
Joined: Wed Mar 17, 2021 8:34 pm

Get captcha image

Post by yaser6403 »

hi, i want to get image of simple captcha to solve by ocr, but i can't found any way.
if download image by DownloadURL, i get new image and it's incorrect. i can't use screenshot because Visible of browser is False. i try to use OnResourceLoadComplete event but not successful because no access to memory stream. please help me if any way exists
demonslord
Posts: 3
Joined: Thu Mar 18, 2021 10:30 am

Re: Get captcha image

Post by demonslord »

Hi yaser6403,

You need register your custom TCefv8HandlerOwn on GlobalCEFApp_OnWebKitInitializedEvent, which contain javascript code to grab your captcha image:

Code: Select all

procedure GlobalCEFApp_OnWebKitInitializedEvent;
var
  TempHandler       : ICefv8Handler;
  JS: TScriptList;
begin
  JS:= TScriptList.Create;
  try
    JS.Add('var myextension;');
    JS.Add('if (!myextension)');
    JS.Add('  myextension = {};');
    JS.Add('(function() {');
    JS.Add(' myextension.getImage = function(img) {');
    JS.Add('   var canvas = document.createElement("canvas");');
    JS.Add('   canvas.width = img.width;');
    JS.Add('   canvas.height = img.height;');
    JS.Add('   var pixels = "";');
    JS.Add('   if (img.naturalWidth && img.naturalHeight) {');
    JS.Add('     var ctx = canvas.getContext("2d");');
    JS.Add('     ctx.drawImage(img, 0, 0);');
    JS.Add('     pixels = canvas.toDataURL("image/png");');
    JS.Add('   }');
    JS.Add('   native function SetImage();');
    JS.Add('   return SetImage(img.width,img.height,pixels,"'+CHROMIUM_JS_SET_IMAGE_MSGNAME+'");');
    JS.Add(' }');
    JS.Add('})();');

    TempHandler := TMyImageHandler.Create;
    CefRegisterExtension('myextension', JS.Text, TempHandler)
  finally
    TempHandler:= nil;
    JS.Free;
  end;
end;
On TCefv8HandlerOwn.Execute, you need handle the message send by browser and handle.

Code: Select all

  TMyImageHandler = class(TCefv8HandlerOwn)
  protected
    function Execute(const name: ustring; const obj: ICefv8Value; const arguments: TCefv8ValueArray; var retval: ICefv8Value; var exception: ustring): Boolean; override;
  end;

Code: Select all

function TMyImageHandler.Execute(const name: ustring; const obj: ICefv8Value; const arguments: TCefv8ValueArray; var retval: ICefv8Value;
  var exception: ustring): Boolean;
var
  TempMessage : ICefProcessMessage;
  TempFrame   : ICefFrame;
  Pixels: string;
  p: Integer;
  EventMessageName: string;
begin
  Result := False;
  try
    if (name = 'SetImage') then
    begin
      Pixels:= arguments[2].GetStringValue;
      p:= Pos(',',Pixels);
      if p > 0 then
        System.Delete(Pixels,1,p);

      EventMessageName:= arguments[3].GetStringValue;

      TempMessage := TCefProcessMessageRef.New(EventMessageName);
      TempMessage.ArgumentList.SetString(0, Pixels);

      TempFrame := TCefv8ContextRef.Current.Browser.MainFrame;
      if (TempFrame <> nil) and TempFrame.IsValid then
        TempFrame.SendProcessMessage(PID_BROWSER, TempMessage);

      Result := True;
    end;

  finally
    TempMessage := nil;
  end;
end;
On Browser_OnProcessMessageReceived event, you need handle the base64 of image, like this:

Code: Select all

if (message.Name = CHROMIUM_JS_SET_IMAGE_MSGNAME) then
  begin
    Pixels:= message.ArgumentList.GetString(0);
    if Pixels <> '' then
    begin
      Stream:= TMemoryStream.Create;
      MyBase64Decode(Pixels,Stream);
      Png:= TPngImage.Create;
      Stream.Position:= 0;
      Png.LoadFromStream(Stream);
      DoImage(Png);
    end else
    begin
      DoImage(nil);
    end;
  end;
BR
dilfich
Posts: 330
Joined: Thu Nov 30, 2017 1:17 am

Re: Get captcha image

Post by dilfich »

Watch the Demo with DownloadImage, specify the link and that's it, if the image is already downloaded, then through DownloadImage you will get it from the cache, which means it will not be new.
(the main thing is that the link of the ball is the same)
Post Reply