gpt4 book ai didi

Delphi 使用 HtmlP 解析 HTML

转载 作者:行者123 更新时间:2023-12-02 15:38:55 24 4
gpt4 key购买 nike

我正在尝试解析 html 文件,以便可以从表中提取数据。
所以我做了一些谷歌魔术,最后在这里提出了一个类似的问题。

在这个问题中,他们建议使用 HTMLP 来解析 html。所以我下载了这些单位并尝试了一下。

它有效,但我想我错过了一些东西。我完全不知道如何从元素中获取实际文本。

我查看了源代码,但找不到任何相关内容。所以我希望这里有人知道答案。

提前致谢。

编辑

根据要求:我试图获取的数据被发现 here
我想获取这些数据并将每一行转换为一个将被存储的对象,以便我可以比较不同的做法、资格和比赛。

最佳答案

您的代码存在问题,请您在此q中恢复,问题出在以下行:

for i:=0 to doc.body.all.length-1 do

执行此操作时,会发生无效变体操作。这是我用来调查此问题的代码:

procedure GetTable2(FSource : TStrings);
var
Doc : IHtmlDocument2;
Body : IHtmlElement;
All : IHtmlElementCollection;
begin
Doc := coHTMLDocument.Create as IHTMLDocument2;
Doc.Write(PSafeArray(FSource.Text));
Doc.Close;
Assert(Doc <> Nil);
Body := Doc.body;
Assert(Body <> Nil);
All := Body.All as IHtmlElementCollection;
Assert(All <> Nil);
Assert(All.Length <> 0);
end;

这会传递一个 TStringlist,该列表已加载了本地保存的比赛结果页面的副本。

您一直在使用“后期绑定(bind)”(即变体)与 MS Dom 解析器交互。这很好,如果比使用早期绑定(bind)(如我刚才引用的代码)慢一点,但它可以隐藏或掩盖某些类型的错误。

我的代码将对已解析 HTML 的访问分为几个阶段,并使用 Assert() 检查 DOM 对象是否确实存在。它们都通过了断言测试,但最后一个断言(All 集合的长度不为零)失败。

您可能想运行上面的代码并检查 Body 对象的 OuterHtml 属性。它只是 '' 加上一些嵌入的 CRLF。 (这个答案的原始版本停在这里)。

更新:进一步挖掘揭示了问题的原因。要查看它,请将您的问题网页保存在本地,然后创建一个新的 VCL 项目,在其窗体中添加一个 TWebBrowser、两个 TMemos 和 TButton,然后将以下代码粘贴到其中(显然,您需要调整 Form.创建以加载页面的本地副本):

procedure GetTable(All : IHtmlElementCollection; Output : TStrings);
var
el:OleVariant;
i,tdc,mc:integer;
tst,v:string;
begin
v:='';
mc:=4;
tdc:=0;
for i:=0 to all.length -1 do
begin
el:= All.item(i, '');
if el.tagname='TD' then
begin
inc(tdc);
if tdc>mc then
begin
Output.Add(v);
v:='';
tdc:=1;
end;
if v='' then v:=el.InnerText
else v:=v+'^'+el.InnerText;
end;
end;
end;

procedure ProcessDoc(Doc : IHtmlDocument2; Output : TStrings);
var
Body : IHtmlElement;
All : IHtmlElementCollection;
V : OleVariant;
begin
Assert(Doc <> Nil);
Body := Doc.Body;
Assert(Body <> Nil);
All := Body.All as IHtmlElementCollection;
Assert(All <> Nil);
Assert(All.Length <> 0);
GetTable(All, Output);
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
Memo1.Lines.LoadFromFile('D:\aaad7\html\race.htm');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
V : OleVariant;
begin
WebBrowser1.Navigate('about:blank'); // This line is so that the WebBrowser
// has a Doc object
Doc := WebBrowser1.Document as IHTMLDocument2;
V := VarArrayCreate([0, 0], varVariant);
V[0] := Memo1.Lines.Text;
try
Doc.Write(PSafeArray(TVarData(V).VArray));
finally
Doc.Close;
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
ProcessDoc(Doc, Memo2.Lines);
end;

当您单击 Button1 时,您很快就会看到问题的原因(假设您像我一样使用 IE11,但您可能会在早期版本中遇到这些问题),即一连串的七个 Javascript 错误弹出窗口。如果您通过它们单击"is",您将看到第二个备忘录收到代码稍作修改版本的输出。

所以,我认为您的代码的问题在于,因为您正在创建一个没有 GUI 的 IHTMLDocument 对象,所以无法显示脚本错误。我认为问题隐藏在您的非 gui Doc 对象中,因为 IIRC(COM 对象的 MS 规范要求)异常永远不会跨越 COM 主机及其客户端之间的边界传播,因此您永远不会找出错误。明显的解决方法是将页面加载到 TWebBrowser 中并使用其中的 Doc 对象。

更新#2:当我第一次写这个答案时,我没有意识到你可以告诉你的 IHtmlDocument 不要尝试弹出 JavaScript 错误,这样它就会加载而不是拒绝。您所需要做的就是放置

Doc.DesignMode := 'On';

在您尝试向其中加载任何内容之前,例如通过调用其 .Write 方法。 Fwiw,当使用 TWebBrowser 的 Silent 属性为 True 时,您可以执行类似的操作。

顺便说一句,如果您尝试解析表格以获取数据,您可能想看看我之前的回答:

Delphi: Some tip to parse this html table?

关于Delphi 使用 HtmlP 解析 HTML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25448938/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com