引言

HttpClient是java语言下一个支持http协议的客户端编程工具包,它实现了HTTP协议的所有方法,但是不支持JS渲染。我们在做一些小玩意时,有可能需要登录某些网站获取信息,那么HttpClient就是你的好帮手,废话不多说,进入实战。

一 登录的实际意义

在HTTP横行的今天,我们每天都要登录一些网站,那么登录的意义是什么呢?首先要对cookie要有一定了解。cookie是存放在本地的一些小文件,它由服务器发送命令,浏览器在本地读写。当访问某些网站的时候,浏览器会检查是否有所浏览网站的cookie信息,如果有则在发送访问请求的时候携带上这些内容,服务器可以读取到浏览器发送请求中的cookie信息,在回应请求时可以再写cookie信息。cookie信息包括键值,内容,过期时间,所属网站。

说到这里cookie差不多讲完了,那么登录到底是怎么回事?登录就是服务器向你的浏览器写cookie,如果仅仅是在你的计算机上写cookie,那么别有用心的人伪造一个cookie也有机会登录网站,所以服务器会在内存中保留一份相同的信息,这个过程叫做会话。如果你在网站点击退出按钮,服务器会把内存中的cookie清除掉,同时清除浏览器中有关登录的cookie。知道了这些,我们就可以上手了。

二 找到登录关键cookie

这里我们可以用wireshark来抓包分析一下。打开知乎首页,打开wireshark,开始监听端口,输入用户名和密码,点击登录,查看wireshark抓到的包。截图如下:

第一张图是本地post提交数据。

第二张图是提交的信息,包括_xsrf,password,remember_me,email,注意,提交的信息中包括cookie,_xsrf可以从知乎首页中获取。

第三张图是服务器返回的信息,注意它的状态是200,说明是成功的。

第四章图是服务器返回的数据,注意它有三条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){//创建一个HttpClientRequestConfig 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/");//获取_xsrfCloseableHttpResponse 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", "xxxx@xxx.com"));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);//从响应信息中获取cookiepublic 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);}
}

代码的流程是:

  1. 从知乎首页获取xsrf信息。

  2. post请求当中需要cookie信息,但是我们第一步中没有得到cookie,请在浏览器中自行找到cookie添加进去,上边的cookie是我找到的。

  3. 提交post请求,得到登录用cookie

  4. 随便找一个需要登录的子页面,将得到的cookie写入到请求头中,提交请求,查看是否已经登录成功

四 结果验证

第一张图显示得到cookie并登录成功

第二张图显示已经进入需要登录的界面

总结

当我们需要登录一个界面获取信息的时候,我们要知道登录实际上做了什么,那就是读写cookie,post数据。

获取cookie时,需要从响应头中获取,当服务器发来新的cookie信息时需要及时写入。

当我们能登录一个网站的时候,如何对其内容进行操作,这里推荐jsoup,良心库,仿jquery操作模式。

摘自开源中国社区:http://my.oschina.net/jiangmitiao/blog/483092

使用HttpClient登录知乎获取返回页面信息相关推荐

  1. 三十四、进阶之获取详情页面信息并显示

    (1)分析如何获取对应电影的详情信息 获取卖座网站电影的详情信息 观察卖座网,进入"阿凡达"和"你好李焕英"的详情页面,可以发现路径变化的只有电影id(film ...

  2. request-promise 获取返回头信息_http返回的状态码 大全

    00 Continue 继续.客户端应继续其请求101 Switching Protocols 切换协议.服务器根据客户端的请求切换协议.只能切换到更高级的协议,例如,切换到HTTP的新版本协议200 ...

  3. C# AD域账号登录验证,获取域用户信息

    using System; using System.Collections.Generic; using System.Configuration; using System.DirectorySe ...

  4. jquery的ajax查询数据库,jquery中使用ajax获取远程页面信息

    效果图如下: 先贴前台代码:其中关键代码是 通过span标记的data(自定义属性)绑定Id DataKeyNames="Id" onrowdeleting="GvCol ...

  5. python爬虫抓取文本_Python实现可获取网易页面所有文本信息的网易网络爬虫功能示例...

    本文实例讲述了Python实现可获取网易页面所有文本信息的网易网络爬虫功能.分享给大家供大家参考,具体如下: #coding=utf-8 #------------------------------ ...

  6. java爬取验证码图片_JAVA HttpClient实现页面信息抓取(获取图片验证码并传入cookie实现信息获取)...

    JAVA HttpClient实现页面信息抓取(获取图片验证码并传入cookie实现信息获取) 发布时间:2018-05-18 16:41, 浏览次数:632 , 标签: JAVA HttpClien ...

  7. java ajax cookie_项目 | Java获取Ajax页面(半次元)—— PhantomJS实现(带cookie登录)...

    写在前面 之前,为了从半次元上下载coser小姐姐的照片,想写个爬虫保存网页上的图片链接,就直接用了Jsoup来读取半次元的网页. 这里说一下,对于想写Java爬虫的小伙伴们来说,Jsoup算是很好用 ...

  8. Flutter路由管理和页面参数的传递(获取返回)

    前言 在做 Flutter 开发的时候所有的页面以及页面上的元素都变成了 Widget ,创建一个页面或者视图直接 new 一个新的 widget 就可以,相关的参数我们可以直接通过构造函数直接传递. ...

  9. 调用API接口登录后,获取用户信息保存到Vuex中并渲染到Vue页面

    文件封装 步骤 核心请求文件 在 apiUse 文件夹中的 index.js 文件写 API接口方法 baseURL + url 后台完整地址 将信息写入 store 文件夹中的 index.js 文 ...

最新文章

  1. 不懂SOLID,GRASP这些软件开发原则!写出来的代码都是垃圾!
  2. 《深入理解Elasticsearch(原书第2版)》——1.4 小结
  3. PHP基础--mySQL数据库
  4. python的子子孙孙(变种编程语言)
  5. python调用C语言函数(方法)的几种方法
  6. what??|诞生才一年的BCH竟面临硬分叉的抉择
  7. 《面向对象分析与设计》一第2章 什么是面向对象分析
  8. 2020微信生态全景运营白皮书:10大热门场景、5大案例剖析.pdf(附下载链接)
  9. The DotNet Garbage Collection
  10. “干掉”程序员饭碗后,OpenAI 又对艺术家下手了!
  11. STM32+DWM1000开发uwb测距系列教程之一:官方例程简介
  12. 第八章:加载Maya2011模型
  13. Linux命令之杀掉被占用的端口号
  14. 音色、音高、音强、音长
  15. python同时监控键鼠教程
  16. 阿里api文档链接地址
  17. prent()和prents()的区别
  18. 魅族mx四核即将使用android,魅族MX四核真机主板曝光 6月份即将上市
  19. 【word小技巧】插入三阶以上的矩阵
  20. yii Yii Framework PHP 框架

热门文章

  1. python照片转彩色手绘_python实现图片彩色转化为素描
  2. MySQL 必知必会系列(五)
  3. Centos7.4使用recuse模式恢复虚机mbr分区表
  4. 3分钟弄明白顶级域名二级域名子域名父域名的区别
  5. 理财通app的设计与实现(六)
  6. EN 14967:防水沥青防潮层—CE认证
  7. 无法识别服务器硬件信息,请教:无法获取服务器硬件信息
  8. java 导出txt_【Java】导入导出TXT文件
  9. BZOJ5011 [Jx2017]颜色(洛谷P4065)
  10. 为什么游戏行业容易遭受DDoS攻击