获取cookie的情况,我们随时会遇到。比如我们的爬虫访问某个需要登录的网址,必须要用到cookie时,就不得不对jsoup和httpclient进行保存cookie的设置。
下面我们来看一个获取多个同路径下同名Cookie的问题。
我们看到 设置了两个 99a0_city cookie, 值分别为1 和 269;如chrome、firefox、ie8将选择最后一个作为cookie值。
好像没什么问题,接下来继续看两个工具:
jsoupConnection conn = Jsoup.connect("http://www.xttblog.com");
conn.method(Method.GET);
conn.followRedirects(false);
Response response = conn.execute();
System.out.println(response.cookies());
//{referer=deleted, 99a0_city=1, PHPSESSID=b5rjkoq2s2qmukjf9n2ffvjvn5}
//立即过期的也显示出了,即从服务器传过来的都显示
99a0_city竟然为1,即选择了第一个作为cookie的值。
查看并修改org.jsoup.helper.HttpConnection中获取cookie的代码:Map> resHeaders = conn.getHeaderFields();
for (Map.Entry> entry : resHeaders.entrySet()) {
String name = entry.getKey();
if (name == null)
continue; // http/1.1 line
List values = entry.getValue();
if (name.equalsIgnoreCase("Set-Cookie")) {
for (String value : values) {
TokenQueue cd = new TokenQueue(value);
String cookieName = cd.chompTo("=").trim();
String cookieVal = cd.consumeTo(";").trim();
// ignores path, date, domain, secure et al. req'd?
System.out.println(cookieName+"="+cookieVal);
cookie(cookieName, cookieVal);
}
} else { // only take the first instance of each header
if (!values.isEmpty())
header(name, values.get(0));
}
}
conn是java.net.HttpURLConnection,也就是说如果使用HttpURLConnection时 有多个同名的cookie 将获取第一个作为cookie的值。
HttpClient
HttpClient和浏览器行为一样获取最后一个Cookie:HttpClient client = new HttpClient();
GetMethod get = new GetMethod("http://www.xttblog.com");
get.setFollowRedirects(false);
client.executeMethod(get);
System.out.println(Arrays.toString(client.getState().getCookies()));
//[PHPSESSID=cn74fv516879pv26h5lbaf9gd0, 99a0_city=269]
//立即过期的不显示出来
因此总结:使用java.net.HttpURLConnection的工具/框架,如果多个同路径下同名的cookie将获取第一个;
使用apache HttpClient,和浏览器行为一样获取最后一个。
因此,当我们在使用cookie时,尽量保证服务器设置一个cookie。
还要注意:使用java.net.HttpURLConnection的工具/框架,可能获取到过期的cookie,如之前的referer[过期时间是2011年,即立即过期];
使用apache HttpClient,不会获取到过期的cookie。