使用DELPHI获取网页的内容

时间:2016-10-06 12:51:02

标签: delphi http-post indy http-get

我正在尝试检索此页面的<table><tbody>部分:

http://www.mfinante.ro/infocodfiscal.html?captcha=null&cod=18505138

我正在使用Delphi XE7。

我尝试使用IXMLHttpRequest,WinInet(InternetOpenURL()InternetReadFile()),TRestClient / TRestRequest / TRestResponseTIdHTTP.Get() ,但他们所检索的都是一些胡言乱语,如下:

  

<html><head><meta http-equiv="Pragma" content="no-cache"/>'#$D#$A'<meta http-equiv="Expires" content="-1"/>'#$D#$A'<meta http-equiv="CacheControl" content="no-cache"/>'#$D#$A'<script>'#$D#$A'(function(){p={g:"0119a4477bb90c7a81666ed6496cf13b5aad18374e35ca73f205151217be1217a93610c5877ece5575231e088ff52583c46a8e8807483e7185307ed65e",v:"87696d3d40d846a7c63fa2d10957202e",u:"1",e:"1",d:"1",a:"challenge等。

请查看此代码:

program htttpget;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  SysUtils, HTTPApp, IdHTTP, ActiveX;

var
  CoResult: Integer;
  HTTP: TIdHTTP;
  Query: String;
  Buffer: String;
begin
  try
    CoResult := CoInitializeEx(nil, COINIT_MULTITHREADED);
    if not((CoResult = S_OK) or (CoResult = S_FALSE)) then
    begin
      Writeln('Failed to initialize COM library.');
      Exit;
    end;
    HTTP := TIdHTTP.Create;
    Query := 'http://www.mfinante.ro/infocodfiscal.html?captcha=null' +
             '&cod=18505138';
    Buffer := HTTP.Get(Query);
    writeln(Buffer);
    HTTP.Destroy;
  except
  end;
end.

这个页面有什么问题?我没有做过很多&#34;得到&#34;我生活中的功能,但其他网站返回正常的回应。有人至少可以向我澄清为什么这不起作用吗?

是否有其他方法可以获取此网页的内容?是否有其他编程语言(Java,脚本等)可以在没有第三方软件的情况下执行此操作(例如使用Firefox源代码模拟浏览器,获取页面,不显示窗口,然后复制内容)。

2 个答案:

答案 0 :(得分:2)

这是正常的,您确实已正确检索了内容。您的浏览器中发生的是脚本被执行并且页面在客户端构建。如果您希望在代码中复制它,那么您将需要执行相同的操作。完全按照浏览器执行脚本。

您在这里真正需要的是所谓的无头浏览器。将其中一个集成到您的程序中。然后让无头浏览器处理请求,包括执行脚本。完成执行脚本后,请阅读页面的修改内容。

答案 1 :(得分:1)

您可以使用TWebBrowser。

请参阅此帖子:How can I get HTML source code from TWebBrowser

RRUZ的答案,您可以在互联网上的许多地方找到,您正在寻找的答案。这会给你原始的html源代码,就像IdHttp.Get()一样。

但是,Mehmet Fide的答案会为您提供DOM的HTML源代码, 您正在寻找的内容。

我在这里提供一个变体。 (它包括当时需要的一些黑客,以获得完整的DOCTYPE。不确定它们是否仍然需要......)

function EndStr(const S: String; const Count: Integer): String;
var
  I: Integer;
  Index: Integer;
begin
  Result := '';
  for I := 1 to Count do
  begin
    Index := Length(S)-I+1;
    if Index > 0 then
      Result := S[Index] + Result;
  end;
end;

function GetHTMLDocumentSource(WebBrowser: TWebBrowser; var Charset: String):
    String;
var
  Element: IHTMLElement;
  Node: IHTMLDomNode;
  Document: IHTMLDocument2;
  I: Integer;
  S: String;
begin
  Result := '';
  Document := WebBrowser.Document as IHTMLDocument2;

  For I := 0 to Document.all.length -1 do
  begin
    Element := Document.all.item(I, 0) as IHTMLElement;
    If Element.tagName = '!' Then
    begin
      Node := Element as IHTMLDomNode;
      If (Node <> nil) and (Pos('CTYPE', UpperCase(Node.nodeValue)) > 0) Then
      begin
        S := VarToStr(Node.nodeValue);  { don't change case of result }
        if Copy(Uppercase(S), 1, 5) = 'CTYPE' then
          S := 'DO' + S;
        if Copy(Uppercase(S), 1, 7) = 'DOCTYPE' then
          S := '<!' + S;
        if Uppercase(S) = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//E' then
          S := S +'N">';

        if EndStr(Lowercase(S), 3) = '.dt' then
          S := S + 'd"';
        if EndStr(Lowercase(S), 5) = '.dtd"' then
          S := S + '>';

        Result := Result + S;
      end;
    end
    Else
      Result := Result + Element.outerHTML;

    If Element.tagName = 'HTML' Then
      Break;
  end;
  Charset := Document.charset;
end;

请调用WebBrowser.Navigate(URL),然后在OnDocumentComplete事件中检索Html源。

但是,使用您的URL,您将看到OnDocumentComplete事件触发两次:(,因此您需要从上次触发中获取Html。

您可以参考这篇文章How do I avoid the OnDocumentComplete event for embedded iframe elements?获取有关如何获取最终OnDocumentComplete事件的信息。但是,我尝试了它并没有为我工作。您可能需要使用其他策略来获取最后一个事件。

不确定您的需求,但您也可以通过禁用WebBrowser下载图像来优化此过程。我相信这是可能的。