模拟登录系列4-java 登录网站后保持会话下载文件
程序员文章站
2022-07-14 08:16:28
...
文本是继上次百度开发者接口图文识别、模拟登录网站 两篇文章后的;这里直接引用前两次的成果;源码附在博客中了,在顶部↑↑↑↑;(如果有疑问或者要源码可以发送邮件给我 aaa@qq.com)。
需求场景:登录某一个特定的网站,在保持会话的同时,并从该网站下载指定的文件到本地。
注意:这里只有 等会后的保持会话和下载,验证和登录请查看我另一篇文章。
准备工作:
1、确保已经对改网站模拟登录成功,并获取到相关需要的参数(根据网站具体的情况来)。
2、分析并获取到网站下载文件的url 和 传入参数,采用F12直接可以参考,对于下载的请求,火狐我这边无法监控到,所以我使用了google浏览器;我这边如下图(经过我测试,发现只需要一个时间参数即可):
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);
调用效果:
上一篇: matplotlib-plt.title
下一篇: git克隆历史版本(下载指定版本的代码)