我正在使用带有IdHTTP lib的Delphi从此URL(http://apply.dataprocessors.com.au)获取表单,处理拼图并发布正确的答案。但是,显然我没有正确处理POST方法,一旦检索到的响应是:"提交问题。请再试一次。"
以下是Delphi源代码:
procedure TForm1.Button1Click(Sender: TObject);
var
sGET, sPOST, sGET_count: String;
countCircles: integer;
parameters: TStringList;
begin
parameters := TStringList.Create;
sGET := http.Get('http://apply.dataprocessors.com.au');
sGET_count := StringReplace(sGET, '$', ' ', [rfReplaceAll, rfIgnoreCase]);
sGET_count := StringReplace(sGET_count, 'unfilled', '$', [rfReplaceAll, rfIgnoreCase]);
countCircles := 120 - sGET_count.CountChar('$');
parameters.Add('title=submit');
parameters.Add('value=' + countCircles.ToString());
parameters.Add('submit=Submit');
http.Request.ContentType := 'application/x-www-form-urlencoded';
sPOST := http.Post('http://apply.dataprocessors.com.au/?', parameters);
txtPost.Lines.Add(sPOST);
end;
HTML code:
<html>
<head>
</head>
<body>
<form action="" method="POST">
<input type="hidden" name="title" value="submit">
<p>How many filled circles do you see:? <br><img src="unfilled_O.gif" height="12" width="12"><br></p>
<p>Answer: <input type="text" name="value" value="" size="10"></p>
<p><input type="Submit" value="Submit">
</form></body>
</html>
从POST方法检索的响应:
<html>
<head>
</head>
<body>
<p>Problem with submission. Please try again.</p></body>
</html>
答案 0 :(得分:2)
我发现您的您的TIdHTTP
代码没有问题(尽管/?
的网址末尾的Post()
不是必需的。)TIdHTTP
代码中缺少步骤。有关详细信息,请参见下文。
我还发现您的StringReplace()
代码存在问题:
sGET := http.Get('http://apply.dataprocessors.com.au'); sGET_count := StringReplace(sGET, '$', ' ', [rfReplaceAll, rfIgnoreCase]); sGET_count := StringReplace(sGET, 'unfilled', '$', [rfReplaceAll, rfIgnoreCase]);
注意第二个StringReplace()
的第一个参数。在第二次调用中,您正在搜索TIdHTTP.Get()
返回的原始HTML 。您没有搜索第一个StringReplace()
的结果。然后,当您重新分配StringReplace()
时,您将完全丢弃第一个sGET_count
的结果,从而有效地使第一个呼叫成为无操作。你可能打算这样做:
sGET := http.Get('http://apply.dataprocessors.com.au');
sGET_count := StringReplace(sGET, '$', ' ', [rfReplaceAll, rfIgnoreCase]);
sGET_count := StringReplace({sGET}sGET_count, 'unfilled', '$', [rfReplaceAll, rfIgnoreCase]);
更新:当我访问网络浏览器中的网址时,我发现了一些代码未考虑的内容。一,网络表单包含jobref
字段,您未在POST
提交中添加该字段。但更重要的是,当真正的Web浏览器检索网页时,相关网页会调用JavaScript函数,但当前TIdHTTP
设置检索时则不会。该Javascript位于http://apply.dataprocessors.com.au/funcs1.js
并包含一个命令,可以动态地将cookie添加到Web浏览器:
function init() {
document.cookie = 'pc3o=d2r22; path=';
}
此命令由HTML调用:
<html>
<head>
...
<script type="text/javascript" src="funcs1.js"></script>
</head>
<body onLoad="init()">
...
</html>
当webbrowser提交webform时,除了检索HTML时HTTP头中存在的普通PHP cookie之外,还会将额外的cookie发送回Web服务器。您需要将TIdHTTP.AllowCookies
属性设置为True(默认情况下为False),因此TIdHTTP.Post()
可以发回cookie,但Post()
只会默认发送PHP cookie,而不是Javascript cookie,原因显而易见(TIdHTTP
不调用客户端脚本)。
如果您更改TIdHTTP.Request.UserAgent
属性以模仿真实的Web浏览器,而不是使用Indy的默认UserAgent
,则下载的HTML将包含该JavaScript引用。这是可选的,因为你可以手动添加Javascript cookie(幸运的是它是静态的,所以你不需要实际解析Javascript,但你可以,如果你愿意,可以)到TIdHTTP.CookieManager
而不管UserAgent
1}},Post()
仍然会发送它,服务器似乎并不关心HTML是否包含JavaScript引用。
话虽如此,以下代码适用于我(我让服务器向POST
发送成功的响应):
procedure TForm1.Button1Click(Sender: TObject);
var
sGET, sPOST, sGET_count: String;
countCircles: integer;
parameters: TStringList;
begin
parameters := TStringList.Create;
try
http.AllowCookies := True;
// optional: http.Request.UserAgent := 'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko';
sGET := http.Get('http://apply.dataprocessors.com.au');
http.CookieManager.AddServerCookie('pc3o=d2r22; path=', http.URL);
sGET_count := StringReplace(sGET, '$', '', [rfReplaceAll, rfIgnoreCase]);
sGET_count := StringReplace(sGET_count, '"filled_O.gif"', '$', [rfReplaceAll, rfIgnoreCase]);
countCircles := sGET_count.CountChar('$');
parameters.Add('title=submit');
parameters.Add('jobref=');
parameters.Add('value=' + countCircles.ToString());
http.Request.ContentType := 'application/x-www-form-urlencoded';
http.Request.Referer := 'http://apply.dataprocessors.com.au';
sPOST := http.Post('http://apply.dataprocessors.com.au', parameters);
ShowMessage(sPOST);
finally
parameters.Free;
end;
end;
答案 1 :(得分:0)
使用F12(或HTTP代理)捕获您的浏览器通信并查看“工作”请求的外观。
工作请求是否使用Cookie?如果是,请为IdHttp启用cookie支持。