獲取含跨域網址的框架網頁的原始碼

一劍平江湖發表於2013-12-10

前面介紹過的獲取框架網頁的原始碼的方法在針對框架中每個文件的URL都是和主網頁在同一個域名(同一個網站)的情況下是不會出什麼問題的,但如果框架包含的網頁是別的域的話,例如以下網頁:該網頁含左右兩個框架,都包含別的域的網址,該網頁原始碼如下:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>框架網頁</title>
</head>
<frameset cols="*,*" frameborder="no" border="0" framespacing="0">
  <frame src="http://www.baidu.com" name="leftFrame" id="leftFrame" title="leftFrame" />
  <frame src="http://www.google.cn" name="mainFrame" id="mainFrame" title="mainFrame" />
</frameset>
<noframes><body>
</body>
</noframes></html>
 

如果使用以下的程式碼獲取這兩個框架的網頁原始碼: 

procedure TForm1.Button1Click(Sender: TObject);
var
  doc, framedoc: IHTMLDocument2;
  frame_dispatch: IDispatch;
  ole_index: OleVariant;
  i: Integer;
begin
  doc := WebBrowser1.Document as IHTMLDocument2;
  if doc = nil then Exit;
  for i := 0 to doc.frames.length - 1 do
  begin
    ole_index := i;
    frame_dispatch := doc.frames.item(ole_index);
    if frame_dispatch = nil then Continue;
    framedoc := (frame_dispatch as IHTMLWindow2).document;
    if framedoc = nil then Continue;
    ShowMessage(framedoc.body.innerHTML);
  end;
end;
 

執行這段程式碼,系統會彈出“拒絕訪問”的出錯對話方塊,沒有任何商量的餘地。怎麼辦,框架網頁的原始碼還是要獲取的,不會因為跨域問題而放棄的。只有百度一下了,幾番搜尋,終於找到了另一種獲取網頁原始碼的方法,而這種方法可以解決跨域問題,方法如下:

1. 單元引用 Uses MsHtml, ActiveX

2. 程式碼:

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
  ole_index: OleVariant;
  FrameDis: IDispatch;
  FrameWin: IHtmlWindow2;
  psi:IServiceProvider;
  frameb: IWebBrowser2;
  pPersist: IPersistStreamInit;
  ss: TStringStream;
  str1, str2: String;
begin
  if WebBrowser1.Busy then Exit;
  Memo1.Lines.Clear;
  //獲取主網頁網址
  Memo1.Lines.Add(WebBrowser1.OleObject.document.url);
  //獲取主網頁原始碼
  Memo1.Lines.Add(WebBrowser1.OleObject.document.documentElement.outerHTML);
  //新增空行
  Memo1.Lines.Add(' ');

  for i := 0 to WebBrowser1.OleObject.document.frames.length - 1 do
  begin
    ole_index := i;
    FrameDis := (WebBrowser1.Document as IHtmlDocument2).frames.item(ole_index);
    FrameDis.QueryInterface(IID_IHTMLWindow2, FrameWin) ;
    if FrameWin = nil then Continue;
    FrameWin.QueryInterface(IServiceProvider, psi);
    if psi = nil then Continue;
    psi.QueryService(IID_IWebBrowserApp,IID_IWebBrowser2,frameb);
    if frameb=nil then continue;
    frameb.Document.QueryInterface(IPersistStreamInit, pPersist);
    if pPersist = nil then Continue;
    //獲取框架頁網址
    Memo1.Lines.Add((frameb.Document as IHtmlDocument2).url);
    ss := TStringStream.Create('');
    try
      //獲取框架頁原始碼
      if Succeeded(pPersist.Save(TStreamAdapter.Create(ss), True)) then
      begin
        str1 := ss.DataString;
        str2 := Utf8ToAnsi(str1); //有些網頁使用UTF-8編碼方式,不進行轉換中文會亂碼
        if str2 = '' then
          Memo1.Lines.Add(str1)
        else
          Memo1.Lines.Add(str2);
      end;
    finally
      FreeAndNil(ss);
    end;
    Memo1.Lines.Add(' '); //新增空行
  end;
end;

相關文章