在Delphi中使用idHTTP发布表单数据

时间:2015-10-27 10:20:18

标签: delphi post indy

我正在使用带有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; 

Form retrieved

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>

2 个答案:

答案 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支持。