delphi - 德尔福网页浏览
问题描述
我想自动化以下过程:我登录到一个网站。在搜索页面,输入我要搜索的信息,点击搜索按钮。点击加载我的结果。从结果页面中,我选择预览 pdf 文件的选项,然后单击按钮。此点击上传我的 pdf 文件。
如果我将这些命令拆分为按钮,然后一个接一个地按下它,一切正常,但是当我想连续执行所有命令时,我得到一个错误。(我认为错误是因为 WebBrowser 没有加载所有内容。)请帮忙。
procedure TMainForm.Button10Click(Sender: TObject);
var doc :IHTMLDocument2;
FileStream: TFileStream;
StreamAdapter: IStream;
PersistStreamInit: IPersistStreamInit;
i, a, b : integer;
sir: string;
MergiInainte:boolean;'
begin
MergiInainte:=false;
WebBrowser1.Navigate('https://website/externallogin.aspx');'
repeat
if ((WebBrowser1.ReadyState = READYSTATE_COMPLETE) and (WebBrowser1.Busy = false)) then
MergiInainte:=true;
until MergiInainte;' // This repeat is not working. Dont know why?
//After webBrowser is fully loaded, the next code has to be run
doc := WebBrowser1.Document AS IHTMLDocument2;
WebFormSetFieldValue(doc,0,'txtNume','user');
WebFormSetFieldValue(doc,0,'txtPwd','psswd');
WebBrowser1.OleObject.Document.GetElementByID('tibAutentification').click;'
//after the above code is fully executat, next code is in line
WebBrowser1.Navigate('https://website/Pages/SearchTitle.aspx');
//after the above code is executed, next i need to complete form element with what the nexd data
doc := WebBrowser1.Document AS IHTMLDocument2;
WebBrowser1.OleObject.Document.GetElementByID('chkTitleNo').click;
WebFormSetFieldValue(doc,0,'txtTitleNo','28972'); //nr titlu de proprietate
WebBrowser1.OleObject.Document.GetElementByID('tibSearch').click;
WebBrowser1.OleObject.Document.GetElementByID('fdgMain:_ctl3:imbView').click;
WebBrowser1.OleObject.Document.GetElementByID('tibViewPDF').click;
end;
// But i'm getting error: Access violation....read of adress 0000000.'
procedure TForm1.WebFormSetFieldValue(const document: IHTMLDocument2; const formNumber: integer; const fieldName, newValue: string) ;
var form : IHTMLFormElement;
field: IHTMLElement;
begin
form := WebFormGet(formNumber, WebBrowser1.Document AS IHTMLDocument2) ;
field := form.Item(fieldName,'') as IHTMLElement;
if field = nil then Exit;
if field.tagName = 'INPUT' then (field as IHTMLInputElement).value := newValue;
if field.tagName = 'SELECT' then (field as IHTMLSelectElement).value := newValue;
if field.tagName = 'TEXTAREA' then (field as IHTMLTextAreaElement).value := newValue;
end;
解决方案
提交 web 表单是一种导航,因此您必须在调用后再次等待ReadyState
andBusy
属性tibAutentification.click
(假设这是 web 表单的提交按钮)。与第二次Navigate()
通话相同。此外,您需要在等待浏览器准备好时抽取调用线程的消息队列,以便它可以正确处理其状态更改。
procedure TMainForm.Button10Click(Sender: TObject);
var
doc: IHTMLDocument2;
doc3: IHTMLDocument3;
FileStream: TFileStream;
StreamAdapter: IStream;
PersistStreamInit: IPersistStreamInit;
i, a, b : integer;
sir: string;
procedure WaitForReady;
begin
while WebBrowser1.ReadyState <> READYSTATE_COMPLETE do
Application.ProcessMessages;
end;
begin
WebBrowser1.Navigate('https://website/externallogin.aspx');
WaitForReady;
doc := WebBrowser1.Document as IHTMLDocument2;
doc3 := doc as IHTMLDocument3;
WebFormSetFieldValue(doc,0,'txtNume','user');
WebFormSetFieldValue(doc,0,'txtPwd','psswd');
doc3.GetElementByID('tibAutentification').click;
WaitForReady;
WebBrowser1.Navigate('https://website/Pages/SearchTitle.aspx');
WaitForReady;
doc := WebBrowser1.Document as IHTMLDocument2;
doc3 := doc as IHTMLDocument3;
doc3.GetElementByID('chkTitleNo').click;
WebFormSetFieldValue(doc,0,'txtTitleNo','28972'); //nr titlu de proprietate
doc3.GetElementByID('tibSearch').click;
WaitForReady; // ?
doc := WebBrowser1.Document as IHTMLDocument2;
doc3 := doc as IHTMLDocument3;
doc3.GetElementByID('fdgMain:_ctl3:imbView').click;
WaitForReady; // ?
doc := WebBrowser1.Document as IHTMLDocument2;
doc3 := doc as IHTMLDocument3;
doc3.GetElementByID('tibViewPDF').click;
end;
procedure TForm1.WebFormSetFieldValue(const document: IHTMLDocument2;
const formNumber: integer; const fieldName, newValue: string);
var
form : IHTMLFormElement;
field: IHTMLElement;
begin
if document = nil then Exit;
form := WebFormGet(formNumber, document);
if form = nil then Exit;
field := form.Item(fieldName,'') as IHTMLElement;
if field = nil then Exit;
if field.tagName = 'INPUT' then
(field as IHTMLInputElement).value := newValue
else if field.tagName = 'SELECT' then
(field as IHTMLSelectElement).value := newValue
else if field.tagName = 'TEXTAREA' then
(field as IHTMLTextAreaElement).value := newValue;
end;
由于与手动抽取消息队列相关的重入问题,序列化此代码不是一个好主意,您应该使用浏览器的OnDocumentComplete
事件,让 VCL 为您处理消息,例如(可能需要一些调整):
procedure TMainForm.Button10Click(Sender: TObject);
begin
WebBrowser1.Navigate('https://website/externallogin.aspx');
WebBrowser1.Tag := 1;
end;
procedure TMainForm.WebBrowser1DocumentComplete(ASender: TObject;
const Disp: IDispatch; const URL: OleVariant);
var
doc: IHTMLDocument2;
doc3: IHTMLDocument3;
begin
case WebBrowser1.Tag of
1: begin
doc := WebBrowser1.Document as IHTMLDocument2;
doc3 := doc as IHTMLDocument3;
WebFormSetFieldValue(doc,0,'txtNume','user');
WebFormSetFieldValue(doc,0,'txtPwd','psswd');
doc3.GetElementByID('tibAutentification').click;
WebBrowser1.Tag := 2;
end;
2: begin
WebBrowser1.Navigate('https://website/Pages/SearchTitle.aspx');
WebBrowser1.Tag := 3;
end;
3: begin
doc := WebBrowser1.Document as IHTMLDocument2;
doc3 := doc as IHTMLDocument3;
doc3.GetElementByID('chkTitleNo').click;
WebFormSetFieldValue(doc,0,'txtTitleNo','28972'); //nr titlu de proprietate
doc3.GetElementByID('tibSearch').click;
WebBrowser1.Tag := 4;
end;
4: begin
doc := WebBrowser1.Document as IHTMLDocument2;
doc3 := doc as IHTMLDocument3;
doc3.GetElementByID('fdgMain:_ctl3:imbView').click;
WebBrowser1.Tag := 5;
end;
5: begin
doc := WebBrowser1.Document as IHTMLDocument2;
doc3 := doc as IHTMLDocument3;
doc3.GetElementByID('tibViewPDF').click;
WebBrowser1.Tag := 0;
end;
end;
end;
推荐阅读
- terraform - 我在运行 terraform 计划时遇到问题
- assembly - AVR 汇编器检查是奇数
- development-environment - 为什么在我的代码中找不到函数 setCredentials()?
- java - Java:无法使用 for 循环“蛮力”方程系统
- c# - 无法导入 System.Windows.Data
- azure - 如何重命名 Azure 应用服务证书
- typescript - 如何在快递上返回完整的详细错误?
- bash - 我可以为 bash 脚本(如 C++“#pragma once”)创建一个评估一次的标头吗?
- swiftui - 将单元格动态添加到 SwiftUI LazyGrid
- xquery - ¿如何替换和插入新节点?