使用PHP (libcurl)、Python (liburl)或AJAX读取JSP servlet页面
我正在尝试用curl访问一个网页:http://rutgers.bncollege.com/webapp/wcs/stores/servlet/TextBookProcessDropdownsCmd?campusId=35577418
,目的是提取一些数据。但我遇到的问题是,总是收到404错误或者302状态的响应。我怀疑这可能和Barnes and Noble的Tomcat服务器在远程请求时没有正确重定向到servlet有关。不过这只是我的猜测。我已经尝试了多种方法,包括在PHP5中使用libcurl、在Python中使用liburl、使用AJAX(有框架和无框架)以及在终端中使用curl命令。
这是我在输出响应文本时得到的结果:
发生了一个错误:
错误代码:404
消息目标:/BNCB_GenericError.jsp
Servlet名称:JSP 1.2处理器
堆栈跟踪:[Ljava.lang.StackTraceElement;@14b6c4d
根本原因:无
这是我发送和接收的请求头:
响应头
过期时间 Thu, 01 Dec 1994 16:00:00 GMT
缓存控制 不缓存="set-cookie,set-cookie2"
内容长度 0
性能头 持续时间=D=56606,
时间=t=1300287776952692
内容类型 text/html;
字符集=ISO-8859-1
内容语言 en-US 日期 Wed, 16
Mar 2011 15:02:57 GMT
连接 保持连接
变化 接受编码
设置Cookie WC_SESSION_ESTABLISHED=true;Domain=.bncollege.com;Path=/
WC_ACTIVESTOREDATA=%2d1%2c0;Domain=.bncollege.com;Path=/WC_USERSESSION_46349649=46349649%2cnull%2cnull%2c%2d2000%2cnull%2cnull%2cnull%2cnull%2cnull%2cnull%2cnull%2cnull%2c%5b0%7cnull%7cnull%7cnull%7c%2d2000%5d%2c8XwO3l7WhszbuSO41vmZUDtbpoQ%3d;Domain=.bncollege.com;Path=/
JSESSIONID=0000AuZi2Uo6F6Ft5xihFdUsBQn:app06z02;Domain=.bncollege.com;Path=/
TS884e96=b7fb55c6fcd8aff3987bcdb831a8255a16b4cbcb208252614d80d120;
请求头
主机 uncc.bncollege.com
用户代理 Mozilla/5.0 (Macintosh; U;
Intel Mac OS X 10.6; en-US;
rv:1.9.2.15pre) Gecko/20110227
Firefox/3.6.15pre (Mac Community
Build, ElFurbe)
接受 text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
接受语言 en-us,en;q=0.5
接受编码 gzip,deflate
接受字符集 ISO-8859-1,utf-8;q=0.7,*;q=0.7
保持连接 115 连接 保持连接
这是相关的代码:
function bufferURL($url,$bindArgs) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://rutgers.bncollege.com/webapp/wcs/stores/servlet/TBWizardView?catalogId=10001&storeId=58552&langId=-1');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_COOKIEJAR, "my_cookies.txt");
curl_setopt($ch, CURLOPT_COOKIEFILE, "my_cookies.txt");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3");
curl_exec($ch);
$url .= '?';
foreach ($bindArgs as $a => $b) $url .= $a . '=' . $b . '&';
$url = substr($url,0,strlen($url)-1);
curl_setopt($ch, CURLOPT_HTTPGET, true);
curl_setopt($ch, CURLOPT_URL, $url);
echo curl_exec($ch);
}
看起来BN使用Dojo来执行他们的AJAX请求到servlet;然而,即使使用相同的请求格式,我也无法复制这个过程。
1 个回答
这看起来有点奇怪。你一开始设置的选项是一个网址,然后又把它改成了发送数据的方式。接着在选项的最后,你又在网址后面加了一个问号,手动添加了更多的查询字符串,然后又把多余的“&”去掉……最后在把它改成GET请求后又重新设置了网址!这真是让人摸不着头脑。
加上问号肯定是导致问题的原因之一——网址里已经有一个问号了,这说明它已经有了查询字符串。而且,你似乎没有正确地对你添加的参数进行网址编码,这也可能会引发问题。
你可以看看parse_url
和parse_str
这两个工具,它们可以帮助你拆解原始网址,提取出原来的查询字符串。一旦你把它拆分成各个部分,并把原来的查询字符串提取到一个数组里,你就可以在这个数组里添加新的查询选项、替换已有的条目,或者删除你不想要的部分。然后你可以使用http_build_query
来重新构建查询字符串,再把正确的网址组合起来。
不过,这样做只有在目标接受GET请求而不是POST请求时才会比较顺利。
如果目标需要POST请求,你可以不动查询字符串,直接把你的查询字符串作为一个数组提交,使用CURLOPT_POSTFIELDS
选项。这样会为你处理好所有的复杂工作。
要注意的是,看起来你可能是在尝试用别人的ajax接口做一些不太合适的事情。可能他们已经设置了一些额外的保护措施来防止自动请求。