用Python和PHP提交HTML表单很简单,初学者能在Java中做到吗?
我写了两个版本的脚本,用来提交一个网页表单(https),并收集结果。一个版本是用php的Snoopy.class,另一个是用python的urllib和urllib2。现在我想做一个java版本。
Snoopy让php版本的编写变得非常简单,而且在我自己的OS X电脑上运行得很好。但是在pair.com的网络托管服务上,它占用了太多内存,导致在执行curl时被杀掉了。在dreamhost.com的网络托管服务上运行得很好。
所以我决定在研究内存问题的原因时,尝试一下python版本,urllib和urllib2让这个过程变得很简单。这个脚本运行得很好。通过几百次表单提交,获取了大约70,000条数据库记录,保存到一个大约10MB的文件中,花了大约7分钟。
在研究如何用java实现这个功能时,我感觉这不会像用php和python那样简单。难道在java中提交表单对普通人来说太难了吗?
我花了大部分时间试图弄清楚如何设置Apache HttpClient。也就是在我放弃之前。如果再花几天时间还搞不定,那我想我可能会另提一个问题。
HttpClient innovation.ch不支持https。
而WebClient看起来也要花我至少几天时间才能搞明白。
所以,php和python版本都很简单。java版本也能用几行简单的代码实现吗?如果不能,那我就先放一放,因为我还是个新手。如果可以的话,能不能请好心人指点我一下?
谢谢。
为了比较,这里是两个版本的关键代码行:
python版本
import urllib
import urllib2
submitVars['firstName'] = "John"
submitVars['lastName'] = "Doe"
submitUrl = "https URL of form action goes here"
referer = "URL of referring web page goes here"
submitVarsUrlencoded = urllib.urlencode(submitVars)
req = urllib2.Request(submitUrl, submitVarsUrlencoded)
req.add_header('Referer', referer)
response = urllib2.urlopen(req)
thePage = response.read()
php版本
require('Snoopy.class.php');
$snoopy = new Snoopy;
$submit_vars["first_name"] = "John";
$submit_vars["last_name"] = "Doe";
$submit_url = "https URL of form action goes here";
$snoopy->referer = "URL of referring web page goes here";
$snoopy->submit($submit_url,$submit_vars);
$the_page = $snoopy->results;
4 个回答
使用HttpClient确实是一个更可靠的解决方案,但其实不需要外部库也可以做到这一点。你可以在这里查看一个示例,了解具体怎么做。
使用 HttpComponents,网址是 http://hc.apache.org/。你需要准备以下东西:
下面是一个示例代码:
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.NameValuePair;
import org.apache.http.HttpResponse;
import org.apache.http.HttpEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.HttpClient;
import java.util.ArrayList;
import java.util.List;
import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
public class HttpClientTest {
public static void main(String[] args) throws Exception {
// request parameters
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
formparams.add(new BasicNameValuePair("q", "quality"));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, "UTF-8");
HttpPost httppost = new HttpPost("http://stackoverflow.com/search");
httppost.setEntity(entity);
// execute the request
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(httppost);
// display the response status code
System.out.println(response.getStatusLine().getStatusCode());
// display the response body
HttpEntity responseEntity = response.getEntity();
OutputStream out = new ByteArrayOutputStream();
responseEntity.writeTo(out);
System.out.println(out);
}
}
把它保存为 HttpClientTest.java。确保这个 Java 文件、httpcore-4.0.1.jar 和 httpclient-4.0-alpha4.jar 都在同一个文件夹里。假设你已经安装了 Sun 的 Java 1.6 JDK,接下来编译它:
javac HttpClientTest.java -cp httpcore-4.0.1.jar;httpclient-4.0-alpha4.jar;commons-logging-1.1.1.jar
然后执行它:
java HttpClientTest.class -cp httpcore-4.0.1.jar;httpclient-4.0-alpha4.jar;commons-logging-1.1.1.jar
我认为在 Java 中的操作和在 PHP 或 Python 中一样简单(就像你给的例子)。无论是哪种情况,你都需要:
- 配置好 SDK
- 一个库(带有依赖项)
- 示例代码
MercerTraieste 和 Tarnschaf 这两位朋友给出了问题的部分解决方案。我花了几天时间,经历了无数个脑袋疼的夜晚,才放弃了尝试在 http post 中添加 referer 的想法,最后又发了个新问题到 StackOverflow。
Jon Skeet 立刻回复我说我只需要...
httppost.addHeader("Referer", referer);
...这让我感觉自己挺傻的,怎么会忽略这个呢?
下面是根据 MercerTraieste 的建议,几乎完全改写后的代码。在我的情况下,我需要下载并放到我的类路径中:
- httpclient-4.0-beta2.jar
- httpcore-4.0.1.jar
- commons-logging-1.1.1.jar
import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpRequest;
import org.apache.http.HttpException;
import org.apache.http.NameValuePair;
import org.apache.http.HttpResponse;
import org.apache.http.HttpEntity;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.HttpClient;
import org.apache.http.protocol.HttpContext;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.impl.client.DefaultHttpClient;
import java.util.ArrayList;
import java.util.List;
import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class HttpClientTest
{
public static void main(String[] args) throws Exception
{
// initialize some variables
String referer = "URL of referring web page goes here";
String submitUrl = "https URL of form action goes here";
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
formparams.add(new BasicNameValuePair("firstName", "John"));
formparams.add(new BasicNameValuePair("lastName", "Doe"));
// set up httppost
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, "UTF-8");
HttpPost httppost = new HttpPost(submitUrl);
httppost.setEntity(entity);
// add referer
httppost.addHeader("Referer", referer);
// create httpclient
DefaultHttpClient httpclient = new DefaultHttpClient();
// execute the request
HttpResponse response = httpclient.execute(httppost);
// display the response body
HttpEntity responseEntity = response.getEntity();
OutputStream out = new ByteArrayOutputStream();
responseEntity.writeTo(out);
System.out.println(out);
}
}