返回
Featured image of post 模拟浏览器发请求

模拟浏览器发请求

用java代码模拟浏览器发请求

前言

模拟浏览器发请求有两种

第几种 原理 优点
第一种 HttpURLConnection 配合 流处理 拿状态码等头文件容易
第二种 HttpGet(模拟发送) 配合 CloseableHttpResponse(处理返回值) 解析字符串数据自动拿字符集(接口拿json用它)

目录

第一种代码

初始化

InputStream inputStream=null;
    //这个网站返回的是gbk字符集
    String urladdress="http://whois.pconline.com.cn/ipJson.jsp?ip="+"117.178.141.106"+"&json=true";
    String jsonStr = "";
    URL url;

模拟浏览器
1.用url创建HttpURLConnection对象
2.HttpURLConnection设置头文件属性以及连接属性
3.httpConn.setDoInput(true)设置是浏览器输出数据

    try
    {// 获取url连接对象
        url = new URL(urladdress);
        //根据url创建http对象
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
        // 设置连接属性
        httpConn.setConnectTimeout(3000);
        httpConn.setDoInput(true);
        httpConn.setRequestMethod("GET");
        //設置发出与接收的字符集
//        httpConn.setRequestProperty("Charsert", "UTF-8");

4.HttpURLConnection得到返回值(状态码和头文件属性和返回数据)



        // 获取相应状态码
        int respCode = httpConn.getResponseCode();

        httpConn.getContentType();  //返回内容字符集utf-8
        httpConn.getContentEncoding();//返回编码头字符集gzip


        //  如果成功发200状态码
        if (respCode == 200)
        {
             inputStream=httpConn.getInputStream();

4.对流解析这里是接口返回json数据

            // ByteArrayOutputStream相当于内存输出流
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            // 将输入流转移到内存输出流中

                while ((len = inputStream.read(buffer, 0, buffer.length)) != -1)
                {
                    out.write(buffer, 0, len);
                }
                // 将内存流转换为字符串"GB2312"是搜狐默认的,而且HttpURLConnection接收数据的时候 字符集默认的是GBK
                jsonStr=out.toString("GB2312");
//            new String(out.toByteArray(),"GB2312");
        }
    }
    catch (MalformedURLException e)
    {
        e.printStackTrace();
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }

第二种代码

初始化

  CloseableHttpClient httpClient;
         String body = null,status = null;
        // 1 HttpClients是java包里的,用它创建HttpClinet,相当于打开浏览器
        httpClient = HttpClients.createDefault();
        //url太平洋ip接口
        String url = "http://whois.pconline.com.cn/ipJson.jsp?ip="+"117.178.141.106"+"&json=true";

将url绑定到HttpGet里
1.1当无参数的绑定时

   HttpGet httpGet = new HttpGet(url);

1.2当有外界传来的map参数的绑定时
map.put(“ip”,ip);
map.put(“json”,“true”);
这里的String url = “http://whois.pconline.com.cn/ipJson.jsp"

        // 声明URIBuilder(动态加变量用)
        URIBuilder uriBuilder = new URIBuilder(url);

       //参数放map里
       Map<String, Object> map = null;
       // 判断参数map是否为非空
       if (map != null) {
           // 遍历参数
          for (Map.Entry<String, Object> entry : map.entrySet()) {
              // 给url上设置参数
               uriBuilder.setParameter(entry.getKey(), entry.getValue().toString());
          }
      }

        // 2 创建httpGet对象,相当于设置url请求地址(带参数的)
      HttpGet httpGet = new HttpGet(uriBuilder.build());

向浏览器请求
2.CloseableHttpClient绑定HttpGet并向浏览器请求execute

        // 3 使用HttpClient执行httpGet,相当于按回车,发起请求
        CloseableHttpResponse response = null;

        try {
            response = httpClient.execute(httpGet);
        } catch (IOException e) {
            logger.info(e+"浏览器请求错误");
        }

拿到请求返回来的结果
3.这里可以拿返回来的头文件
eg:返回来的字符集是什么
注意这里是还要用正则表达式解析数据(没写)

// todo:拿状态码(用正则)
        Header[] headers= response.getHeaders("content-type");//拿头文件字符集(包状态码)
        for (Header header : headers) {
            header.getName();               //拿key :content-type
            header.getValue();              //拿值text/html; charset=GBK
            logger.info(header.toString()); //拿全部Content-Type: text/html; charset=GBK
        }

对请求返回的请求体解析
注意CloseableHttpResponse.getEntity()只能用一次

3.1这一部分是对返回的结果是字符串形式的写法

//对返回数据解析
 try {
        if (response.getEntity() != null) {
            //拿状态码
            status= String.valueOf(response.getStatusLine().getStatusCode());

//请求体CloseableHttpResponse.getEntity()不能调用多次,只能调用获取一次
//这种是自动获取发的字符集在解码成字符串,如果没有获取到,在以后面的字符集解码(UTF-8与gbk都行)
            body=EntityUtils.toString(response.getEntity(),"gbk");//body是String


3.2这一部分是对返回的结果是其它文件,用2进制方式(没写)或者用流读取文件

InputToString inputToString = new InputToString();//工具类
  if (response.getEntity() != null) {
            //拿状态码
            status= String.valueOf(response.getStatusLine().getStatusCode());
	//以字节方式读传来的数据
       // byte[] bytes =   EntityUtils.toByteArray(response.getEntity());
//这种方式是以流方式拿数据,所以用gbk解码,因为发来的数据是gbk的
          InputStream in = response.getEntity().getContent();
          body=inputToString.InToString(in);

工具类代码

package com.xiao.demo.util;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class  InputToString{
    public String InToString(InputStream inputStream) throws IOException {
        String jsonStr;
        // ByteArrayOutputStream相当于内存输出流
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        // 将输入流转移到内存输出流中

        while ((len = inputStream.read(buffer, 0, buffer.length)) != -1) {
            out.write(buffer, 0, len);
        }
        // 将内存流转换为字符串"GB2312"是搜狐默认的,而且HttpURLConnection接收数据的时候 字符集默认的是GBK
        jsonStr = out.toString("GB2312");

        out.close();
        inputStream.close();

        return jsonStr;
    }
}


结尾


        } else {
            //状态码
            status= String.valueOf(response.getStatusLine().getStatusCode());
        }
 } catch (IOException e) {
     e.printStackTrace();
 }
 logger.info("请求体:"+body+"--状态码:"+status);

json解析器

//字符串是这样的{"地址":"内容"}
JSONObject jsonObject = JSONObject.parseObject(String类型);
//取出地址对应内容	
 String pro = jsonObject.getString("地址");
Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy