带有问题网站的 HTTPclient POST

Posted

技术标签:

【中文标题】带有问题网站的 HTTPclient POST【英文标题】:HTTPclient POST with problematic web site 【发布时间】:2011-01-23 18:32:02 【问题描述】:

我正在尝试从 web site 检索一些数据。

正如您从代码中看到的那样,我指定了从 html 源中获取名称的输入字段,但也许这个网站不接受这种 POST 请求?

如何模拟用户交互来检索生成的 HTML?

package com.transport.urlRetriver;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

public class UrlRetriver 


    String stationPoller (String url, ArrayList<NameValuePair> params) 

        HttpPost postRequest;
        HttpResponse response;
        HttpEntity entity;
        String result = null;

        DefaultHttpClient httpClient = new DefaultHttpClient();


        try 

            postRequest = new HttpPost(url);

            postRequest.setEntity((HttpEntity) new UrlEncodedFormEntity(params));
            response = httpClient.execute(postRequest);

            entity = response.getEntity();

            if(entity != null)
              InputStream inputStream = entity.getContent();
              result = convertStreamToString(inputStream);
            



         catch (Exception e) 

            result = "We had a problem";

         finally 

            httpClient.getConnectionManager().shutdown();

        



        return result;

    





    void ATMtravelPoller () 




        ArrayList<NameValuePair> params = new ArrayList<NameValuePair>(2);

        String url = "http://www.atm-mi.it/it/Pagine/default.aspx";

        params.add(new BasicNameValuePair("ctl00$SPWebPartManager1$g_afa5adbb_5b60_4e50_8da2_212a1d36e49c$txt_address_s", "Viale romagna 1"));

        params.add(new BasicNameValuePair("ctl00$SPWebPartManager1$g_afa5adbb_5b60_4e50_8da2_212a1d36e49c$txt_address_e", "Viale Toscana 20"));

        params.add(new BasicNameValuePair("sf_method", "POST"));

        String result = stationPoller(url, params);

        saveToFile(result, "/home/rachele/Documents/atm/out4.html");

    

    static void saveToFile(String toFile, String pos)
          try
                // Create file 
                FileWriter fstream = new FileWriter(pos);
                BufferedWriter out = new BufferedWriter(fstream);
                out.write(toFile);
                //Close the output stream
                out.close();
                catch (Exception e)//Catch exception if any
                  System.err.println("Error: " + e.getMessage());
                
              

    private static String convertStreamToString(InputStream is) 
          BufferedReader reader = new BufferedReader(new InputStreamReader(is));
          StringBuilder stringBuilder = new StringBuilder();

          String line = null;
          try 
            while ((line = reader.readLine()) != null) 
              stringBuilder.append(line + "\n");
            
           catch (IOException e) 
            e.printStackTrace();
           finally 
            try 
              is.close();
             catch (IOException e) 
              e.printStackTrace();
            
          
          return stringBuilder.toString();
        


【问题讨论】:

这不是一个答案,而是对所发生情况的描述。您需要提交大约 30 个参数,并且一些参数名称/值是动态生成的,以防止脚本或程序获取内容。您对每次获取内容时都会更改的参数名称进行硬编码。这些参数不会相同。 不是您的 javascript 事物的答案(因此是评论)但是...请注意,对于很多网站,您需要从 Java 伪造您的“用户代理”,否则您将无法获得真实的网站。去过那里,做到了,你必须伪造用户代理;) 对于这个网站,你是否发送用户代理并没有什么不同。我通过从我的Firefox中过滤掉用户代理标头来测试它,结果没有什么不同。 gigadot 你认为有办法解决这个问题吗? 如果我是你,我会先尝试对页面内容进行Http GET。然后,获取表单标签中的所有输入标签(包括隐藏类型),并为 Http POST 创建所有名称/值对的列表。现在忽略 java scriptbits。如果它不起作用,那么我们必须重新考虑它。 【参考方案1】:

在我看来,可能存在具有动态值的 javascript 生成字段,以防止自动代码抓取网站。发送您要下载的具体网站。

【讨论】:

我已经在原始描述中插入了:atm-mi.it/en/Pages/default.aspx 正如 gigadot 上面写的那样,您必须执行 GET 请求才能获取隐藏字段(我可以看到 __REQUESTDIGEST 有问题),然后发出 POST 请求。一般来说,就像浏览器中的用户一样。

以上是关于带有问题网站的 HTTPclient POST的主要内容,如果未能解决你的问题,请参考以下文章

带有客户端证书的 HttpClient POST 请求

带有 BaseAddress 的 HttpClient

带有 BaseAddress 的 HttpClient

带有 HttpClient 的进度条

使用带有 .NET 4.5 HttpClient 的代理

Angular 6获取带有httpclient问题的响应标头