使用Delphi中的IHTMLDocument2静默阻止cookie警告



我正在使用IHTMLDocument2对一组网站进行爬网。我正在创建IHTMLDocument2实例,如下所示:

    var
      myDownload : TDownLoadURL;
      doc: OleVariant;
    (...)
      myDownload:= TDownLoadURL.Create(nil);
      with myDownload do
      begin
        URL:=myURL;
        Filename:= GetTempDirectory+'temp_download_url_complete2.txt';
        ExecuteTarget(nil);
      end;
(...)
      doc := coHTMLDocument.Create as IHTMLDocument2;
      doc.write(html);
      doc.close;
(...)

有一个特定的网站弹出一条消息:

允许本网站为您提供个性化信息,你允许它在你的计算机

我已经更改了操作系统(Windows 2008 SE)的Internet选项,在没有提示的情况下阻止cookie,但消息不断出现。如何在静默模式下创建IHTMLDocument2?

如果需要取消显示IHTMLDocument用户界面或用户通知,则需要同时实现IOleClientSite和定义为DISPID_AMBIENT_DLCONTROL的环境属性
从文档"下载控制":

主机可以控制下载的某些方面——帧、图像、Java、,等等--通过实现IOleClientSite和环境属性定义为DISPID_AMBIENT_DLCONTROL。当主机的IDispatch::Invoke方法是在dispidMember设置为DISPID_AMBIENT_DLCONTROL的情况下调用的,它应将零或以下值的组合放入pvarResult。

在这种情况下,您需要的标志是DLCTL_SILENT(可能还有DLCTL_NO_SCRIPTS)。

如上所述,如果您希望从文档中获取事件通知(例如DISPID_READYSTATE),主机还应该实现IDispatch.Invoke)和(可选IPropertyNotifySink或其他COM事件接收器对象)。

看看EmbeddedWB源代码,看看它是如何实现的。特别是CCD_ 9和CCD_。它已经满足了你的需求。


以下是一个基于UI_Less(未实现IPropertyNotifySink)的简化演示:

uses ..., ActiveX, MSHTML;
const
  DISPID_AMBIENT_DLCONTROL = (-5512);
type
  TUILess = class(TComponent, IUnknown, IDispatch, IOleClientSite)
    protected
    // IDispatch
    function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
      Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HRESULT; stdcall;
    // IOleClientSite
    function SaveObject: HRESULT; stdcall;
    function GetMoniker(dwAssign: Longint; dwWhichMoniker: Longint;
      out mk: IMoniker): HRESULT; stdcall;
    function GetContainer(out container: IOleContainer): HRESULT; stdcall;
    function ShowObject: HRESULT; stdcall;
    function OnShowWindow(fShow: BOOL): HRESULT; stdcall;
    function RequestNewObjectLayout: HRESULT; stdcall;
  end;
implementation
function TUILess.Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
  Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HRESULT;
const
  DLCTL_NO_SCRIPTS = $00000080;
  DLCTL_NO_JAVA = $00000100;
  DLCTL_NO_RUNACTIVEXCTLS = $00000200;
  DLCTL_NO_DLACTIVEXCTLS = $00000400;
  DLCTL_DOWNLOADONLY = $00000800;
  DLCTL_SILENT = $40000000;
var
  I: Integer;
begin
  if DISPID_AMBIENT_DLCONTROL = DispID then
  begin
    I := DLCTL_DOWNLOADONLY + DLCTL_NO_SCRIPTS +
      DLCTL_NO_JAVA + DLCTL_NO_DLACTIVEXCTLS +
      DLCTL_NO_RUNACTIVEXCTLS +
      DLCTL_SILENT;
    PVariant(VarResult)^ := I;
    Result := S_OK;
  end
  else
    Result := DISP_E_MEMBERNOTFOUND;
end;
function TUILess.SaveObject: HRESULT;
begin
  Result := E_NOTIMPL;
end;
function TUILess.GetMoniker(dwAssign: Longint; dwWhichMoniker: Longint;
  out mk: IMoniker): HRESULT;
begin
  Result := E_NOTIMPL;
end;
function TUILess.GetContainer(out container: IOleContainer): HRESULT;
begin
  Result := E_NOTIMPL;
end;
function TUILess.ShowObject: HRESULT;
begin
  Result := E_NOTIMPL;
end;
function TUILess.OnShowWindow(fShow: BOOL): HRESULT;
begin
  Result := E_NOTIMPL;
end;
function TUILess.RequestNewObjectLayout: HRESULT;
begin
  Result := E_NOTIMPL;
end;
procedure TForm1.Button1Click(Sender: TObject);
const
  cHTML: WideString = '<b>test</b><script>alert("boo")</script>';
var
  Doc: IHTMLDocument2;
  DocClientSite: TUILess;
begin
  DocClientSite := TUILess.Create(nil);
  try
    Doc := coHTMLDocument.Create as IHTMLDocument2;
    try
      (Doc as IOleObject).SetClientSite(DocClientSite);
      (Doc as IOleControl).OnAmbientPropertyChange(DISPID_AMBIENT_DLCONTROL); // Invoke
      OleVariant(Doc).write(cHTML);
      Doc.close;
      ShowMessage(Doc.body.innerHtml); // Test
    finally
      (Doc as IOleObject).SetClientSite(nil);
      Doc := nil;
    end;
  finally
    DocClientSite.Free;
  end;
end;

恐怕您无法轻易隐藏该消息。为什么?

首先,你需要了解为什么该消息会显示在特定的网站上。简单的答案是欧盟今年开始使用的关于处理cookie的新法律(不确定确切时间):

http://ico.org.uk/for_organisations/privacy_and_electronic_communications/the_guide/cookies?hidecookiesbanner=true

然后你需要意识到,显示的消息不是任何类型的标准弹出消息,而是硬编码到网站中的。更糟糕的是,每个网站所有者都使用自己的方法来做到这一点。

BTW在你的浏览器中禁用cookie不会阻止该消息的显示。为什么?如果一个网站想查看是否有cookie,它必须向客户端计算机发送一个cookie。但法律要求,在将任何cookie发送到客户端计算机之前,都要警告用户使用cookie。

因此,简单地点击"我接受使用cokies一次"可能会更容易,而且这条消息可能不会再次显示。为什么?Becuse在这种情况下,网站会创建一个永久cookie,存储您已经同意使用cookie的信息。

最新更新