使用HttpClient登录知乎获取返回页面信息
Posted jzdwajue
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用HttpClient登录知乎获取返回页面信息相关的知识,希望对你有一定的参考价值。
引言
HttpClient是java语言下一个支持http协议的client编程工具包,它实现了HTTP协议的全部方法,可是不支持JS渲染。我们在做一些小玩意时,有可能须要登录某些站点获取信息,那么HttpClient就是你的好帮手,废话不多说,进入实战。
一 登录的实际意义
在HTTP横行的今天,我们每天都要登录一些站点,那么登录的意义是什么呢?首先要对cookie要有一定了解。cookie是存放在本地的一些小文件,它由server发送命令。浏览器在本地读写。
当訪问某些站点的时候,浏览器会检查是否有所浏览站点的cookie信息,假设有则在发送訪问请求的时候携带上这些内容,server能够读取到浏览器发送请求中的cookie信息。在回应请求时能够再写cookie信息。cookie信息包含键值。内容。过期时间。所属站点。
讲到这里cookie几乎相同讲完了。那么登录究竟是怎么回事?登录就是server向你的浏览器写cookie,假设不过在你的计算机上写cookie,那么别实用心的人伪造一个cookie也有机会登录站点。所以server会在内存中保留一份同样的信息。这个过程叫做会话。假设你在站点点击退出button,server会把内存中的cookie清除掉。同一时候清除浏览器中有关登录的cookie。
知道了这些,我们就能够上手了。
二 找到登录关键cookie
这里我们能够用wireshark来抓包分析一下。
打开知乎首页,打开wireshark。開始监听port。输入username和password,点击登录。查看wireshark抓到的包。
截图例如以下:
第一张图是本地post提交数据。
第二张图是提交的信息,包含_xsrf,password。remember_me,email。注意,提交的信息中包含cookie,_xsrf能够从知乎首页中获取。
第三张图是server返回的信息,注意它的状态是200,说明是成功的。
第四章图是server返回的数据,注意它有三条cookie设置。以及带有一个登录成功与否的信息。
通过上边的步骤我们能知道什么呢?首先,发送登录请求的时候带有的cookie。以及post数据的格式。其次我们能拿到登录用cookie信息(第四张图)。
三 使用HttpClient构造登录信息
HttpClient是如何模拟浏览器的呢?首先须要建立一个HttpClient,这个HttpClient是用来模拟一个浏览器。
其次构造一个post请求,加入post数据信息以及cookie。具体代码例如以下:
import org.apache.http.*; import org.apache.http.client.CookieStore; import org.apache.http.client.config.CookieSpecs; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.config.Lookup; import org.apache.http.config.RegistryBuilder; import org.apache.http.cookie.CookieSpecProvider; import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.cookie.BasicClientCookie; import org.apache.http.impl.cookie.DefaultCookieSpecProvider; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import java.io.IOException; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; /** * Created by gavin on 15-7-23. */ public class HttpClientTest { public static void main(String[] args) { //创建一个HttpClient RequestConfig requestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD_STRICT).build(); CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).build(); try { //创建一个get请求用来接收_xsrf信息 HttpGet get = new HttpGet("http://www.zhihu.com/"); //获取_xsrf CloseableHttpResponse response = httpClient.execute(get,context); setCookie(response); String responsehtml = EntityUtils.toString(response.getEntity()); String xsrfValue = responseHtml.split("<input type=\"hidden\" name=\"_xsrf\" value=\"")[1].split("\"/>")[0]; System.out.println("xsrfValue:" + xsrfValue); response.close(); //构造post数据 List<NameValuePair> valuePairs = new LinkedList<NameValuePair>(); valuePairs.add(new BasicNameValuePair("_xsrf", xsrfValue)); valuePairs.add(new BasicNameValuePair("email", "[email protected]")); valuePairs.add(new BasicNameValuePair("password", "xxxxx")); valuePairs.add(new BasicNameValuePair("remember_me", "true")); UrlEncodedFormEntity entity = new UrlEncodedFormEntity(valuePairs, Consts.UTF_8); //创建一个post请求 HttpPost post = new HttpPost("http://www.zhihu.com/login/email"); post.setHeader("Cookie", " cap_id=\"YjA5MjE0YzYyNGQ2NDY5NWJhMmFhN2YyY2EwODIwZjQ=|1437610072|e7cc307c0d2fe2ee84fd3ceb7f83d298156e37e0\"; "); //注入post数据 post.setEntity(entity); HttpResponse httpResponse = httpClient.execute(post); //打印登录是否成功信息 printResponse(httpResponse); //构造一个get请求,用来測试登录cookie是否拿到 HttpGet g = new HttpGet("http://www.zhihu.com/question/following"); //得到post请求返回的cookie信息 String c = setCookie(httpResponse); //将cookie注入到get请求头其中 g.setHeader("Cookie",c); CloseableHttpResponse r = httpClient.execute(g); String content = EntityUtils.toString(r.getEntity()); System.out.println(content); r.close(); } catch (IOException e) { e.printStackTrace(); } finally { try { httpClient.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void printResponse(HttpResponse httpResponse) throws ParseException, IOException { // 获取响应消息实体 HttpEntity entity = httpResponse.getEntity(); // 响应状态 System.out.println("status:" + httpResponse.getStatusLine()); System.out.println("headers:"); HeaderIterator iterator = httpResponse.headerIterator(); while (iterator.hasNext()) { System.out.println("\t" + iterator.next()); } // 推断响应实体是否为空 if (entity != null) { String responseString = EntityUtils.toString(entity); System.out.println("response length:" + responseString.length()); System.out.println("response content:" + responseString.replace("\r\n", "")); } } public static Map<String,String> cookieMap = new HashMap<String, String>(64); //从响应信息中获取cookie public static String setCookie(HttpResponse httpResponse) { System.out.println("----setCookieStore"); Header headers[] = httpResponse.getHeaders("Set-Cookie"); if (headers == null || headers.length==0) { System.out.println("----there are no cookies"); return null; } String cookie = ""; for (int i = 0; i < headers.length; i++) { cookie += headers[i].getValue(); if(i != headers.length-1) { cookie += ";"; } } String cookies[] = cookie.split(";"); for (String c : cookies) { c = c.trim(); if(cookieMap.containsKey(c.split("=")[0])) { cookieMap.remove(c.split("=")[0]); } cookieMap.put(c.split("=")[0], c.split("=").length == 1 ?"":(c.split("=").length ==2?
c.split("=")[1]:c.split("=",2)[1])); } System.out.println("----setCookieStore success"); String cookiesTmp = ""; for (String key :cookieMap.keySet()) { cookiesTmp +=key+"="+cookieMap.get(key)+";"; } return cookiesTmp.substring(0,cookiesTmp.length()-2); } }
代码的流程是:
-
从知乎首页获取xsrf信息。
-
post请求其中须要cookie信息,可是我们第一步中没有得到cookie。请在浏览器中自行找到cookie加入进去,上边的cookie是我找到的。
-
提交post请求,得到登录用cookie
-
随便找一个须要登录的子页面,将得到的cookie写入到请求头中,提交请求,查看是否已经登录成功
四 结果验证
第一张图显示得到cookie并登录成功
第二张图显示已经进入须要登录的界面
总结
当我们须要登录一个界面获取信息的时候,我们要知道登录实际上做了什么,那就是读写cookie,post数据。
获取cookie时,须要从响应头中获取。当server发来新的cookie信息时须要及时写入。
当我们能登录一个站点的时候,怎样对其内容进行操作。这里推荐jsoup。良心库,仿jquery操作模式。
摘自开源中国社区:http://my.oschina.net/jiangmitiao/blog/483092
以上是关于使用HttpClient登录知乎获取返回页面信息的主要内容,如果未能解决你的问题,请参考以下文章
基于HttpClient的新版正方教务系统模拟登录及信息获取API