java使用HTTPclient访问网络

来源:互联网 发布:linux什么是管道 编辑:程序博客网 时间:2024/04/28 23:39


import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.cert.CertificateException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;

import javax.imageio.ImageIO;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

/**
 * 访问url的工具
 *
 * @author change by xin_luo
 * @version 1.0 2015/6/11
 *
 */
public class Request {

    private CloseableHttpClient client;
    // private HttpPost postMethod;
    // private HttpGet getMethod;
    // private HttpResponse httpResponse;
    private Logger logger = Logger.getLogger(Request.class);

    /**
     * 构造函数,仅指定编码
     *
     * @param charset
     *            编码名
     */
    public Request(String charset) {
        client = new DefaultHttpClient();
        client.getParams().setParameter(CoreProtocolPNames.USER_AGENT,
                UserAgent.getUserAgent());
        if (charset != null) {
            client.getParams().setParameter(
                    CoreProtocolPNames.HTTP_CONTENT_CHARSET, charset);
        }
        client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS,
                false);
        client.getParams().setParameter(ClientPNames.MAX_REDIRECTS, 10);
        client.getParams().setParameter(ClientPNames.COOKIE_POLICY,
                CookiePolicy.BROWSER_COMPATIBILITY);
        client.getParams().setParameter(
                CoreConnectionPNames.CONNECTION_TIMEOUT, 2 * 60 * 1000);
        client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,
                2 * 60 * 1000);
    }

    /**
     * 构造函数,指定代理的ip地址,端口,编码
     *
     * @param ip
     *            ip地址
     * @param port
     *            端口
     * @param charset
     *            编码名
     */
    public Request(String ip, int port, String charset) {
        client = new DefaultHttpClient();
        if (ip != null && port > 0) {
            HttpHost proxy = new HttpHost(ip, port);
            client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,
                    proxy);
        }
        client.getParams().setParameter(ClientPNames.HANDLE_REDIRECTS, false);
        client.getParams().setParameter(
                CoreProtocolPNames.HTTP_CONTENT_CHARSET, charset);
        client.getParams().setParameter(CoreProtocolPNames.USER_AGENT,
                UserAgent.getUserAgent());
        client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS,
                false);
        client.getParams().setParameter(ClientPNames.MAX_REDIRECTS, 10);
        client.getParams().setParameter(ClientPNames.COOKIE_POLICY,
                CookiePolicy.BROWSER_COMPATIBILITY);
        client.getParams().setParameter(
                CoreConnectionPNames.CONNECTION_TIMEOUT, 2 * 60 * 1000);
        client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,
                2 * 60 * 1000);
    }

    /**
     * 发出post请求
     *
     * @param url
     * @param form_data
     *            post请求所需的参数
     * @param headerMap
     *            需要添加的header头信息
     * @param charset
     *            编码名
     * @return url返回的byte[]
     */
    public synchronized byte[] postRequest(String url,
            List<NameValuePair> form_data, Map<String, String> headerMap,
            String charset) {
        try {
            url = filterURL(url);
        } catch (Exception e1) {
        }
        HttpPost postMethod = new HttpPost(url);
        if (headerMap != null && headerMap.size() > 0) {
            for (String k : headerMap.keySet()) {
                postMethod.addHeader(k, headerMap.get(k));
            }
        }
        postMethod.addHeader("User-Agent", UserAgent.getUserAgent());
        try {
            postMethod.setEntity(new UrlEncodedFormEntity(form_data, charset));
            HttpResponse httpResponse = client.execute(postMethod);
            int requestStatus = httpResponse.getStatusLine().getStatusCode();
            if (requestStatus == HttpStatus.SC_OK) {
                return getResponseBody(httpResponse);
            } else {
                logger.info(requestStatus + "\t" + url);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                postMethod.abort();
            } catch (Exception e) {
            }
        }
        return null;
    }

    /**
     * 发出post请求
     *
     * @param url
     * @param form_data
     *            post请求所需的参数
     * @param charset
     *            编码名
     * @param refererURL
     *            请求来源url
     * @return url返回的byte[]
     */
    public synchronized byte[] postRequest(String url,
            List<NameValuePair> form_data, String charset, String refererURL) {
        try {
            url = filterURL(url);
        } catch (Exception e1) {
        }
        HttpPost postMethod = new HttpPost(url);
        postMethod.addHeader("Referer", refererURL);
        postMethod.addHeader("Content-Type",
                "application/x-www-form-urlencoded");
        postMethod.addHeader("Host", getUrlHost(url));
        postMethod.addHeader("User-Agent", UserAgent.getUserAgent());
        try {
            postMethod.setEntity(new UrlEncodedFormEntity(form_data, charset));
            HttpResponse httpResponse = client.execute(postMethod);
            int requestStatus = httpResponse.getStatusLine().getStatusCode();
            byte[] html = getResponseBody(httpResponse);
            if (requestStatus == HttpStatus.SC_OK) {
                return html;
            } else {
                logger.info(requestStatus + "\t" + url);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                postMethod.abort();
            } catch (Exception e) {
            }
        }
        return null;
    }

    /**
     * 发出post请求
     *
     * @param url
     * @param formMap
     *            post请求所需的参数
     * @param headerMap
     *            需要添加的header头信息
     * @param charset
     *            编码名
     * @return 获得url中Header的location----转发的url
     */
    public synchronized String postRequestLocalHttps(String url,
            Map<String, String> formMap, Map<String, String> headerMap,
            String charset) {
        enableSSL(client);
        try {
            url = filterURL(url);
        } catch (Exception e1) {
        }
        HttpPost postMethod = new HttpPost(url);
        if (headerMap != null && headerMap.size() > 0) {
            for (String k : headerMap.keySet()) {
                postMethod.addHeader(k, headerMap.get(k));
            }
        }
        postMethod.addHeader("User-Agent", UserAgent.getUserAgent());
        List<NameValuePair> form_data = new ArrayList<NameValuePair>();
        if (formMap != null && formMap.size() > 0) {
            Set<String> sets = formMap.keySet();
            for (String k : sets) {
                form_data.add(new BasicNameValuePair(k, formMap.get(k)));
            }
        }
        try {
            postMethod.setEntity(new UrlEncodedFormEntity(form_data, charset));
            HttpResponse httpResponse = client.execute(postMethod);
            return httpResponse.getFirstHeader("location").getValue();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                postMethod.abort();
            } catch (Exception e) {
            }
        }
        return null;
    }

    /**
     * 发出get请求
     *
     * @param url
     * @param charset
     *            编码名
     * @param refererURL
     *            referer请求来源url
     * @param cookie
     *            cookie,可为空
     * @return url的字符串
     */
    public synchronized String getRequest(String url, String charset,
            String refererURL, String cookie) {
        if (url.contains("https://")) {
            enableSSL(client);
        }
        HttpGet getMethod = null;
        try {
            url = filterURL(url);
        } catch (Exception e1) {
        }
        int requestStatus = 0;
        int count = 0;
        HttpParams params = client.getParams();
        params.setParameter(ClientPNames.HANDLE_REDIRECTS, false);
        do {
            try {
                count++;
                getMethod = new HttpGet(url);
                getMethod.addHeader("User-Agent", UserAgent.getUserAgent());
                getMethod
                        .addHeader("Accept",
                                "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
                getMethod.addHeader("Accept-Language",
                        "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
                getMethod.addHeader("Accept-Encoding", "gzip, deflate");
                getMethod.addHeader("Content-Type",
                        "application/x-www-form-urlencoded");
                getMethod.addHeader("Host", getUrlHost(url));
                getMethod.addHeader("Connection", "close");
                getMethod.addHeader("Referer", refererURL);
                if (cookie != null) {
                    getMethod.removeHeaders("Cookie");
                    getMethod.addHeader("Cookie", cookie);
                } else {
                    getMethod.removeHeaders("Cookie");
                    getMethod.addHeader("Cookie", getCookie());
                }
                HttpResponse httpResponse = client.execute(getMethod);
                requestStatus = httpResponse.getStatusLine().getStatusCode();
                if (requestStatus == HttpStatus.SC_OK) {
                    return new String(getResponseBody(httpResponse), charset);
                } else if (requestStatus == 301 || requestStatus == 302
                        || requestStatus == 303) {
                    // 301 永久重定向,告诉客户端以后应从新地址访问.
                    // 302 代表暂时性转移(Temporarily Moved )
                    // 303:对于POST请求,它表示请求已经被处理,客户端可以接着使用GET方法去请求Location里的URI。
                    Header locationHeader = httpResponse
                            .getFirstHeader("location");
                    url = connectUrl(url, locationHeader.getValue());
                    if (url.contains("https://")) {
                        enableSSL(client);
                    }
                } else {
                    logger.info(requestStatus + "\t" + url);
                }
            } catch (ClientProtocolException de) {
                break;
            } catch (Exception e) {
                e.printStackTrace();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
            } finally {
                try {
                    getMethod.abort();
                } catch (Exception e) {
                }
            }
        } while (requestStatus != HttpStatus.SC_OK && count < 2);
        return null;
    }

    /**
     * 发出get请求,xin_luo新增的方法
     *
     * @param url
     * @param charset
     *            编码名
     * @param refererURL
     *            referer请求来源url
     * @param cookie
     * @return 访问url得到的byte[]
     */
    public synchronized byte[] getRequestByte(String url, String charset,
            String refererURL, String cookie) {
        if (url.contains("https://")) {
            enableSSL(client);
        }
        HttpGet getMethod = null;
        try {
            url = filterURL(url);
        } catch (Exception e2) {
        }
        int requestStatus = 0;
        int count = 0;
        HttpParams params = client.getParams();
        params.setParameter(ClientPNames.HANDLE_REDIRECTS, false);
        do {
            try {
                count++;
                getMethod = new HttpGet(url);
                getMethod.addHeader("User-Agent", UserAgent.getUserAgent());
                getMethod
                        .addHeader("Accept",
                                "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
                getMethod.addHeader("Accept-Language",
                        "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
                getMethod.addHeader("Accept-Encoding", "gzip, deflate");
                getMethod.addHeader("Content-Type",
                        "application/x-www-form-urlencoded");
                getMethod.addHeader("Host", getUrlHost(url));
                getMethod.addHeader("Connection", "close");
                getMethod.addHeader("Referer", refererURL);
                if (cookie != null) {
                    getMethod.removeHeaders("Cookie");
                    getMethod.addHeader("Cookie", cookie);
                }
                HttpResponse httpResponse = client.execute(getMethod);
                requestStatus = httpResponse.getStatusLine().getStatusCode();
                if (requestStatus == HttpStatus.SC_OK) {
                    return getResponseBody(httpResponse);
                } else if (requestStatus == 301 || requestStatus == 302
                        || requestStatus == 303) {
                    // 301 永久重定向,告诉客户端以后应从新地址访问.
                    // 302 代表暂时性转移(Temporarily Moved )
                    // 303:对于POST请求,它表示请求已经被处理,客户端可以接着使用GET方法去请求Location里的URI。
                    Header locationHeader = httpResponse
                            .getFirstHeader("location");
                    url = connectUrl(url, locationHeader.getValue());
                    if (url.contains("https://")) {
                        enableSSL(client);
                    }
                } else {
                    logger.info(requestStatus + "\t" + url);
                }
            } catch (ClientProtocolException de) {
                break;
            } catch (Exception e) {
                e.printStackTrace();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
            } finally {
                try {
                    getMethod.abort();
                } catch (Exception e) {
                }
            }
        } while (requestStatus != HttpStatus.SC_OK && count < 2);
        return null;
    }

    /**
     * 处理可能出现的压缩格式
     *
     * @param method
     * @return byte[]
     */
    public synchronized byte[] getResponseBody(HttpResponse response) {
        try {
            Header contentEncodingHeader = response
                    .getFirstHeader("Content-Encoding");
            HttpEntity entity = response.getEntity();
            if (contentEncodingHeader != null) {
                String contentEncoding = contentEncodingHeader.getValue();
                if (contentEncoding.toLowerCase(Locale.US).indexOf("gzip") != -1) {
                    GZIPInputStream gzipInput = null;
                    try {
                        gzipInput = new GZIPInputStream(entity.getContent());
                    } catch (EOFException e) {
                        logger.error("read gzip inputstream eof exception!");
                    }
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    byte[] buffer = new byte[256];
                    int n;
                    while ((n = gzipInput.read(buffer)) >= 0) {
                        out.write(buffer, 0, n);
                    }
                    return out.toByteArray();
                }
            }
            return EntityUtils.toByteArray(entity);
        } catch (Exception e) {
            logger.error("read response body exception! ", e);
        }

        return null;
    }

    /**
     * 获取cookie信息
     *
     * @return
     */
    public String getCookie() {
        List<Cookie> cookies = ((AbstractHttpClient) client).getCookieStore()
                .getCookies();
        StringBuilder sb = new StringBuilder();

        for (Cookie cookie : cookies) {
            sb.append(cookie.getName() + "=" + cookie.getValue() + "; ");
        }
        return sb.toString();
    }

    /**
     * 下载图片
     * @param url
     * @param charset    编码
     * @param filePath    保存文件的路径
     * @param type        文件后缀
     * @return    下载完成后的文件名
     */
    public synchronized String downloadPicByDate(String url, String charset,
            String filePath,String  type) {
        HttpGet getMethod = null;
        try {
            String readPath = new SimpleDateFormat("yyyy" + File.separator
                    + "MM" + File.separator + "dd").format(new Date())
                    + File.separator + EncodeUtil.getMD5(url) + "." + type;
            String fileName = filePath + File.separator + readPath;
            File picFile = new File(fileName);
            if (picFile.exists()) {
                return readPath;
            }
            url = encodeURL(url, charset);
            try {
                url = filterURL(url);
            } catch (Exception e1) {
            }
            getMethod = new HttpGet(url);
            getMethod.getParams().setParameter(
                    ClientPNames.ALLOW_CIRCULAR_REDIRECTS, false);
            getMethod.addHeader("User-Agent", UserAgent.getUserAgent());
            HttpResponse response = client.execute(getMethod);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                // 得到网络资源的字节数组,并写入文件
                InputStream in = entity.getContent();
                BufferedImage img = ImageIO.read(in);
                in.close();
                if (img == null) {
                    return null;
                }
                if (!picFile.getParentFile().exists()) {
                    picFile.getParentFile().mkdirs();
                }
                AffineTransformOp op = new AffineTransformOp(
                        AffineTransform.getScaleInstance(1, 1), null);
                BufferedImage new_img = op.filter(img, null);
                FileOutputStream out = new FileOutputStream(picFile);
                JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
                encoder.encode(new_img);
                out.close();
                return readPath;
            }
        } catch (Exception e) {
            logger.error("download picture exception! " + url, e);
        } catch (OutOfMemoryError error) {
            logger.error("There is not enough memory to use while downloading picture '"
                    + url + "'! ");
            System.gc();
        } finally {
            try {
                getMethod.abort();
            } catch (Exception e) {
            }
        }
        return null;
    }

    /**
     * 对url中的中文进行编码
     *
     * @param url
     * @param charset
     * @return
     */
    private synchronized String encodeURL(String url, String charset) {
        StringBuffer encodeURL = new StringBuffer();
        try {
            Pattern pattern = Pattern.compile("[ \\[\\]{}\\s\u4e00-\u9fa5]");
            Matcher matcher = pattern.matcher(url);
            while (matcher.find()) {
                matcher.appendReplacement(encodeURL,
                        URLEncoder.encode(matcher.group(), charset));
            }
            matcher.appendTail(encodeURL);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return encodeURL.toString();
    }

    /**
     * 访问https的网站
     *
     * @param httpclient
     */
    @SuppressWarnings("deprecation")
    private void enableSSL(HttpClient httpclient) {
        // 调用ssl
        try {
            SSLContext sslcontext = SSLContext.getInstance("TLS");
            sslcontext.init(null, new TrustManager[] { truseAllManager }, null);
            SSLSocketFactory sf = new SSLSocketFactory(sslcontext);
            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            Scheme https = new Scheme("https", sf, 443);
            httpclient.getConnectionManager().getSchemeRegistry()
                    .register(https);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 重写验证方法,取消检测ssl
     */
    private TrustManager truseAllManager = new X509TrustManager() {

        public void checkClientTrusted(
                java.security.cert.X509Certificate[] arg0, String arg1)
                throws CertificateException {
        }

        public void checkServerTrusted(
                java.security.cert.X509Certificate[] arg0, String arg1)
                throws CertificateException {
        }

        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    };

    /**
     * 过滤url中的杂七杂八的字符
     *
     * @param url
     * @return
     * @throws Exception
     */
    private String filterURL(String url) throws Exception {
        url = url.replaceAll("wiki\\?(.)*?/", "wiki/");
        url = url.replaceAll("\"", URLEncoder.encode("\"", "UTF-8"));
        url = url.replaceAll("`", URLEncoder.encode("`", "UTF-8"));
        url = url.replaceAll(" ", URLEncoder.encode(" ", "UTF-8"));
        url = url.replaceAll("%.", URLEncoder.encode("%", "UTF-8") + ".");
        url = url.replaceAll("}", URLEncoder.encode("}", "UTF-8"));
        url = url.replaceAll("\\{", URLEncoder.encode("{", "UTF-8"));
        url = url.replaceAll(" ", "%20");
        return url;
    }

    /**
     * 拼接url,通过请求的url和请求返回的url进行拼接
     *
     * @param requestUrl
     *            第一次访问的url
     * @param href
     *            重定向的url
     * @return 返回拼接完成的url
     */
    private static String connectUrl(String requestUrl, String href) {
        try {
            if (href == null) {
                return null;
            }
            if (href.startsWith("http://")) {
                return href;
            }

            if (href.startsWith("?")) {
                if (requestUrl.contains("?")) {
                    return requestUrl.substring(0, requestUrl.lastIndexOf("?"))
                            + href;
                } else {
                    return requestUrl + href;
                }
            }
            if (requestUrl.endsWith("/") && href.startsWith("./")) {
                return requestUrl + href.substring(2, href.length());
            }
            if (!requestUrl.endsWith("/") && href.startsWith("./")) {
                return requestUrl.substring(0, requestUrl.lastIndexOf("/"))
                        + href.substring(2, href.length());
            }
            String host = getUrlHost(requestUrl);
            if (href.startsWith("/")) {
                return host + href;
            }
            if (href.startsWith("../")) {
                href = href.replace("../", "");
                return host + "/" + href;
            }
            if (!href.startsWith("/") && !href.startsWith(".")) {
                if (!requestUrl.endsWith("/")) {
                    requestUrl = requestUrl.substring(0,
                            requestUrl.lastIndexOf("/") + 1);
                }
                return requestUrl + href;
            } else {
                return connectUrlForComparatively(requestUrl, href);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 拼接url
     *
     * @param host
     * @param href
     * @return
     */
    private static String connectUrlForComparatively(String host, String href) {
        String doc = "";
        if (href.startsWith(".")) {
            doc = "/";
        }
        Pattern pattern1 = Pattern.compile("\\./");
        Matcher matcher1 = pattern1.matcher(href);
        while (matcher1.find()) {
            href = href.replaceFirst("\\.\\./", "");
            host = host.substring(0, host.lastIndexOf("/"));
        }
        if (host.lastIndexOf("/") == host.length() - 1) {
            host = host.substring(0, host.length() - 1);
        }
        String url = host + doc + href;
        return url;
    }

    /**
     * 得到url的host 如http://weibo.com
     *
     * @param url
     * @return
     */
    public static String getUrlHost(String url) {
        if (url == null) {
            return null;
        }
        // ^行的开头 $行的结尾
        url = url.replaceAll("^https?://", "").replaceAll("([^/]+).*", "$1");
        return url;
    }
}

0 0
原创粉丝点击