很早之前写过一个java爬虫,用来抓某网站妹子图片的,用到了httpclient包,但是没有认真理解方法,只是为了实现功能而拼凑了一个东西出来,当然也还为了好玩。
现在不一样了,已经决定了不考研,而又处于大三这个开始有找工作的压力的情况下,自然要开始学习磨炼自己的技术。再加上学习安卓网络编程正好用到了httpclient包,于是就下载了官方手册仔细的学了一学,现在在这里写下来我对第一部分(Post与get)相关的理解。
首先贴出下载链接:http://hc.apache.org/downloads.cgi
然后是官方官方教程:http://hc.apache.org/httpcomponents-client-4.5.x/tutorial/html/index.html
下面开始说说常用的方法。
GET:基本知识就不说了,网上一搜一大堆。这里讲讲怎么用发送get请求,获取网页的request。
1.用Httpclient的静态方法获取一个CloseableHttpClient的 对象(CloseableHttpClient httpclient = HttpClients.createDefault();)
2.获取一个HttpGet对象,并传入想要get的url(HttpGet httpGet = new HttpGet(url);)
3.通过httpClient.execute(httpGet)返回一个CloseableHttpResponse的服务器返回的response
4.将调用response的getEntity()方法,返回一个HttpEntity对象entity
5.调用entity的getContent方法返回一个输入流
6.常规的把输入流处理为String就可以利用正则表达式获取自己想要的信息了。
其中,如果要给get方法带上参数,则需要构建uri,比如提交一个百度搜索界面,带上搜索关键词“地锅鸡”,则需要提交网址http://www.baidu.com/s?wd=地锅鸡 的形式,不知道的同学可以用chrome的抓包功能,然后进行分析(如果有必要以后也写个笔记记录一下抓包的过程)。
构建URI如:URI uri = new URIBuilder().setScheme("http").setHost("www.baidu.com").setPath("/s").setParameter("wd", keyWord).build();
然后将URI放入HttpGet的构建即可。
Post方法,稍微麻烦一点。我因为写安卓做了一个种子搜索器,所以用到了KittyBt网站以及它的搜索功能。即提交搜索关键词,解析返回的网址,用正则表达式获取所需要的信息就可以了。
基本过程如下:
1.创建Httpclient对象
2.创建HttpPost对象,带上网址参数
3.设置提交的header(为了防止网站把程序提交的request过滤掉),使用addHeader()方法
4.设置需要post的内容List<NameValuePair> formparas,调用add()方法,并用BasicNameValuePair构建参数
5. Httpclient的execute执行httppost,如上面的方法获取一个response,再用entity获得输入流进行解析。
public class HttpUtils {
static CloseableHttpClient httpClient = HttpClients.createDefault();
static CloseableHttpResponse response1;
/**
* @param 目标url
* @return 网页正文string
*/
public static String contentByGet(String url) throws Exception {
String response = "";// 用于存放网页返回的html内容
InputStream in = null;// 用于获得entity的输入流
HttpGet httpGet = new HttpGet(url);
response1 = httpClient.execute(httpGet);
try {
HttpEntity entity = response1.getEntity();
if (entity != null) {
in = entity.getContent();
try {
response = InputStreamToString.inputToStr(in);
} finally {
in.close();
}
}
} finally {
response1.close();
}
return response;
}
/**
* @param 待搜索的关键词
* @return 网页正文string
*/
public static String getBaiDu(String keyWord) throws Exception {
String response = "";
InputStream in = null;
CloseableHttpClient httpClient = HttpClients.createDefault();
URI uri = new URIBuilder().setScheme("http").setHost("www.baidu.com").setPath("/s").setParameter("wd", keyWord)
.build();// 构建搜索网址:http://www.baidu.com/s?wd=地锅鸡
HttpGet httpGet = new HttpGet(uri);
CloseableHttpResponse response1 = httpClient.execute(httpGet);
try {
HttpEntity entity = response1.getEntity();
if (entity != null) {
in = entity.getContent();
try {
response = InputStreamToString.inputToStr(in);
} finally {
in.close();
}
}
} finally {
response1.close();
}
return response;
}
/**
* @param 待搜索的关键词
* @return 搜索结果的html链接
*/
public static String postKittyBt(String keuword) throws Exception {
String response = "";
String targetURL = "";
InputStream in = null;
// 构建post提交的参数
List<NameValuePair> formparas = new ArrayList<NameValuePair>();
formparas.add(new BasicNameValuePair("keyword", keuword));
formparas.add(new BasicNameValuePair("hidden", "true"));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparas, Consts.UTF_8);
HttpPost post = new HttpPost("http://btkitty.bid/");
// 设置请求头header
post.setEntity(entity);
post.addHeader("Cache-Control", "max-age=0");
post.addHeader("Content-Type", "application/x-www-form-urlencoded");
post.addHeader("User-Agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36");
post.addHeader("Accept-Encoding", "gzip, deflate");
post.addHeader("Accept-Language", "zh-CN,zh;q=0.8");
post.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
response1 = httpClient.execute(post);
try {
HttpEntity entity2 = response1.getEntity();
if (entity2 != null) {
in = entity2.getContent();
try {
// 获取目标网址的response的header,获取Location参数的值,即为目标网址
Header[] headers = response1.getAllHeaders();
System.out.println("----测试location:" + headers.toString());
for (int i = 0; i < headers.length; i++) {
System.out.println(headers[i].getName() + ":" + headers[i].getValue());
if (headers[i].getName().equalsIgnoreCase("Location")) {
targetURL = headers[i].getValue();
}
}
} finally {
in.close();
}
}
} finally {
response1.close();
}
return targetURL;
}
}
之所以post要解析response的header,是因为KittyBt这个网站在发送搜索关键词的请求后,返回的并不是目标html,而是返回一个空内容的网页,只有在header里附带了Location的属性里有目标网址链接。
下面是输入流转换为string文本的方法
public class InputStreamToString {
/**
* @param in
* @return 输入流的内容string
*/
public static String inputToStr(InputStream in) {
BufferedReader str = null;
StringBuffer buffer = null;
InputStreamReader reader = null;
try {
reader = new InputStreamReader(in, "UTF-8");
str = new BufferedReader(reader);
buffer = new StringBuffer();
String line = "";
while ((line = str.readLine()) != null) {
buffer.append(line);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (str != null) {
str.close();
}
} catch (Exception e) {
e.printStackTrace();
}
try {
if (reader != null) {
reader.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return buffer.toString();
}
}
做个广告,之前那个java爬妹子图片的程序在:https://github.com/ztgreenleaves/ReptileLearning
有没有大佬能介绍个软件开发的实习啊!大三了 好急啊。2017.3.13