欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

模拟登录系列4-java 登录网站后保持会话下载文件

程序员文章站 2022-07-14 08:16:28
...

文本是继上次百度开发者接口图文识别、模拟登录网站 两篇文章后的;这里直接引用前两次的成果;源码附在博客中了,在顶部↑↑↑↑;(如果有疑问或者要源码可以发送邮件给我 aaa@qq.com)。

需求场景:登录某一个特定的网站,在保持会话的同时,并从该网站下载指定的文件到本地。

注意:这里只有 等会后的保持会话和下载,验证和登录请查看我另一篇文章。

准备工作:

1、确保已经对改网站模拟登录成功,并获取到相关需要的参数(根据网站具体的情况来)。

2、分析并获取到网站下载文件的url 和 传入参数,采用F12直接可以参考,对于下载的请求,火狐我这边无法监控到,所以我使用了google浏览器;我这边如下图(经过我测试,发现只需要一个时间参数即可):

模拟登录系列4-java 登录网站后保持会话下载文件

 

java 代码:

代码目录情况:

模拟登录系列4-java 登录网站后保持会话下载文件

因为这里是模拟登录,网站基本都有cookie,所以需要保持会话,这里采用httpClient4.5的cookie来保持会话(核心代码如下)。

public static CloseableHttpClient getConnection() {
		if (CheckCodeUtil.thread.get() == null) {
			CookieStore cookieStore = new BasicCookieStore();//httpClient4.x 使用cookie保持会话
			CheckCodeUtil.thread.set(cookieStore);
		}
		CloseableHttpClient httpClient = HttpClients.custom().setDefaultCookieStore(CheckCodeUtil.thread.get()).build();
		
		return httpClient;
	}

说明:这里需要和登录的ThreadLocal 采用同一个(简单的说,你登录也得调用这个方法);所以在之前建立CheckCodeUtil.java文件加入(之前登录的文件中我早放了,这里直接贴文件吧)。

package com.baidu.api;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.http.HttpHost;
import org.apache.http.client.CookieStore;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;



public class CheckCodeUtil {

	public static final ThreadLocal<CookieStore> thread = new ThreadLocal<CookieStore>();
	public static Set<String> codeSet;
	private static final Logger mylog = Logger.getLogger(CheckCodeUtil.class);;

	
	//检查是否
	public static boolean checkCode(String code) {

		return codeSet.contains(code);
	}
	/**
	 * 干扰码较多或者识别度不高时,调用转换验证码识别接口(这里是公司的识别平台)
	 * @param image_save_path
	 * @param codeType
	 * @param imgurl
	 * @return
	 */
	public static  String analysisCode(String image_save_path,String codeType,String imgurl) {
		//优先调用讯策提供的验证码 解析。20190426
		if("3".equals(codeType)){
			codeType="30400";//4位数字和字母组合
		}else if("4".equals(codeType)){
			codeType="10400";//4位数字
		}else if("5".equals(codeType)){
			codeType="30500";//5位数字和字母组合
		}else if("6".equals(codeType)){
			codeType="30600";//6位数字和字母组合
		}else if("7".equals(codeType)){
			codeType="30700";//7位数字和字母组合
		}else if("8".equals(codeType)){
			codeType="30800";//8位数字和字母组合
		}else if("10".equals(codeType)){
			codeType="50100";//简单计算图
		}else if("20".equals(codeType)){
			codeType="50200";//复杂计算图
		}
		
		String code =VerifyCode.getVerifyCode(image_save_path,codeType,imgurl);
		if(!"".equals(code)){
			return code;
		}
		
		return code;
	}
	public static  String getComplexCode(String image_save_path,String imgurl) {
		String codeStr="";
		try {
			codeStr = MyImgCheck.checkFile(image_save_path);
			
		} catch (URISyntaxException e) {
			mylog.error("调用百度中心接口失败~");
			e.printStackTrace();
		} catch (IOException e) {
			mylog.error("调用百度中心接口失败~");
			e.printStackTrace();
		}
		String code="";
		try {
			Map<String,Object> m = JSON.parseObject(codeStr,Map.class);  
			List<String> lst = JSONObject.parseArray(m.get("words_result")+"", String.class);
			if(lst.size()>0){
				Map<String,Object> m1= JSON.parseObject(lst.get(0),Map.class);  
				code = m1.get("words")+"";
				mylog.info("用百度开发者中心接口验证码为:"+code);
			}
			
		}catch (Exception e) {
			mylog.error("调用百度开发者中心接口返回值 格式解析失败~");
			mylog.error("错误返回值【"+codeStr+"】");
			e.printStackTrace();
		}
		
		return code;
	}

	/**
	 * 
	 * @param in
	 *            输入流
	 * @param path
	 *            地址
	 * @return 是否成功
	 */
	public static synchronized boolean download(InputStream in, String path) {
		FileOutputStream out = null;
		try {
			out = new FileOutputStream(path);
			// out = new FileOutputStream("D:\\abb.jpg");
			byte b[] = new byte[1024];
			int j = 0;
			while ((j = in.read(b)) != -1) {
				out.write(b, 0, j);
			}
			out.flush();
			File file = new File(path);
			if (file.exists() && file.length() == 0)
				return false;
			return true;
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			if ("FileNotFoundException".equals(e.getClass().getSimpleName()))
				System.err.println("download FileNotFoundException");
			if ("SocketTimeoutException".equals(e.getClass().getSimpleName()))
				System.err.println("download SocketTimeoutException");
			else
				e.printStackTrace();
		} finally {
			if (out != null)
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			if (in != null)
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
		return false;
	}

	public static CloseableHttpClient getConnection() {
		if (CheckCodeUtil.thread.get() == null) {
			CookieStore cookieStore = new BasicCookieStore();//httpClient4.x 使用cookie保持会话
			CheckCodeUtil.thread.set(cookieStore);
		}
		CloseableHttpClient httpClient = HttpClients.custom().setDefaultCookieStore(CheckCodeUtil.thread.get()).build();
		
		return httpClient;
	}
	
	
	 
	/**
	 * 关闭连接~
	 * 
	 */
	public static void removeConn() {
		if (CheckCodeUtil.thread.get() != null) {
			CheckCodeUtil.thread.remove();
		}
	}

	public static String getFileName() {

		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");

		return sdf.format(new Date());

	}

	/**
	 * 获取session
	 * 
	 * @return
	 */
	public static CookieStore getCok() {
		return CheckCodeUtil.thread.get();
	}

	/**
	 * 获取本月最后一天
	 * 
	 * @return
	 */
	public static String getLastMonth() {
		Calendar cal_1 = Calendar.getInstance();// 获取当前日期
		// cal_1.add(Calendar.MONTH, -1);
		cal_1.set(Calendar.DAY_OF_MONTH, 1);
		cal_1.add(Calendar.DATE, -1);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

		return sdf.format(cal_1.getTime());
	}

}

FileUtil.java  处理文件下载(再次说明这里的获取连接方法必须和登录采用同一个,否则无法保持会话)

package com.baidu.api;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.log4j.Logger;

public class FileUtil {
	private static final Logger mylog = Logger.getLogger(FileUtil.class);
	/**
	 * 上传准备工作 要求先下载模板
	 * @param url 下载地址
	 * @param filePath 模板文件路径
	 * @param fileName 模板文件名称
	 * @param param 下载参数
	 * @return
	 */
	public static void uploadPrepare(String url,String filePath,String fileName,Map<String,String> param) {
		//httpClient4.x 使用cookie保持会话
		CloseableHttpClient httpclient = CheckCodeUtil.getConnection(); // 获取连接
		List<NameValuePair> qparams = new ArrayList<NameValuePair>(); // 访问
		
		HttpPost httpost = new HttpPost(url);//设置路径
		//设置参数
		for (Map.Entry<String, String> enetiy : param.entrySet()) {
			mylog.debug("添加变量" + enetiy.getKey() + "<---->" + enetiy.getValue());
			qparams.add(new BasicNameValuePair(enetiy.getKey(), enetiy.getValue()));
		}
		try {
			//获取文件资源
			httpost.setEntity(new org.apache.http.client.entity.UrlEncodedFormEntity(qparams));
			HttpResponse response = httpclient.execute(httpost);
			
			//接收转换文件流输出
			ByteArrayOutputStream abos = new ByteArrayOutputStream();
    		response.getEntity().writeTo(abos);
    		ByteArrayInputStream bis = new ByteArrayInputStream(abos.toByteArray());
    		
    		//判断文件的保存路径后面是否以/结尾  
	         if (!filePath.endsWith("/")) {  
	             filePath += "/";  
	         }  
	         FileOutputStream fileOut = null;  
	         //写入到文件(注意文件保存路径的后面一定要加上文件的名称)  
	         fileOut = new FileOutputStream(filePath+fileName);  
	         BufferedOutputStream bos = new BufferedOutputStream(fileOut);  
	           
	         byte[] buf = new byte[4096];  
	         int length = bis.read(buf);
	         //保存文件  
	         while(length != -1)  
	         {  
	             bos.write(buf, 0, length);  
	             length = bis.read(buf);  
	         }  
	        //关闭流
	        bos.close();  
	       // bis.close();  
	        //abos.close();
			httpost.abort();
			httpclient.close();
			mylog.info("已成功下载文件到:"+filePath+fileName);
			
		} catch (UnsupportedEncodingException e) {
			mylog.error("不支持格式" + e.getMessage());
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			mylog.error("httpclient连接池异常" + e.getMessage());
			e.printStackTrace();
		} catch (IOException e) {
			mylog.error("读写异常" + e.getMessage());
			e.printStackTrace();
		} catch (Exception e) {
			mylog.error("dom4j文档解析异常" + e.getMessage());
			e.printStackTrace();
		} finally {
			httpost.abort();
			try {
				httpclient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

DateUtil.java 时间帮助类

package com.baidu.api;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtil { 
/**
	 * 将Date对象转换为指定格式的字符串 支持 yyyyMMdd  数字格式
	 * @param date 日期
	 * @param pattern 格式
	 * @return
	 * @throws Exception 
	 */
	public static String formatDate(Date date, String pattern) {
		try {
			DateFormat formatter = new SimpleDateFormat(pattern);
			return formatter.format(date);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}
}

建立main,调用入口:

		String filePath= "E:\\home\\file\\";//下载模板文件存放路径
		
		String fileName = "非法人产品信息"+time+".xls";//文件名称
		//下载模板文件路径
		String downloadUrl="https://cmss.chinamoney.com.cn/AAMS/json/exportUnlegalFnclFile.do?uuid="+uuid;
		//组装参数
		Map<String,String> qparams = new HashMap<String,String>();
		qparams.put("belongsToData", DateUtil.formatDate(new Date(), "yyyy-MM-dd"));
		//调用下载模板文件
		FileUtil.uploadPrepare(downloadUrl,filePath, fileName,qparams);

调用效果:

模拟登录系列4-java 登录网站后保持会话下载文件

模拟登录系列4-java 登录网站后保持会话下载文件