写文件
写入文本文件
import java.io.File;
import java.io.FileWriter;
//创建文件对象
File file = new File("a.txt");
//写入内容
FileWriter fileWriter = new FileWriter(file.getName());
fileWriter.write(content);
//关闭
fileWriter.close();
写入二进制文件
import java.io.File;
import java.io.FileOutputStream;
//创建文件对象
File file = new File("a.xlsx");
//写入内容
FileOutputStream fos = new FileOutputStream(file);
fos.write(data);//data是字节数组类型
//关闭
fos.flush();//先刷新
fos.close();
解析execl
添加依赖库
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.6</version>
</dependency>
调用库
excel文件是多表模式,每个sheet是一个表,所以解析数据的顺序一定是: sheet->行->列
第一个单元格的位置是0,第一个sheet,第一行,第一列的位置是0,0,0。下面的例子用Map存放列值是因为我们不能确定excel每一列的含义。
import com.alibaba.excel.EasyExcel;
import java.util.Map;
import java.util.List;
//读取第一个sheet
List<Map<Integer,String>> sheetDatas = EasyExcel.read("a.xlsx").sheet(0).doReadSync();
//List数组中每个元素存放的是一行数据
for(Map<Integer,String> rowDatas:sheetDatas){
//Map中用序号指代每一列
for(Integer index:rowData.keySet()){
//列值
String columuValue = rowData.get(index);
}
}
自动转换为类
当我们提前确定了每一列的含义就可以用对象来表示。
public class DemoData {
private String code1;
private String city1;
private String code2;
private String city2;
private String code3;
private String city3;
//setter,getter省略
}
head(DemoData.class)
表示一行数据,此类的每一个属性表示一列值,返回值为 List<DomeData>
表示每一行转换为一个 DomeData
的实例对象,放入List集合中。
import com.alibaba.excel.EasyExcel;
import java.util.List;
List<DemoData> sheetDatas = EasyExcel.read("a.xlsx").head(DemoData.class).sheet(0).doReadSync();
for(DemoData rowData:datas){
System.out.println(JSON.toJSONString(rowData))
}
查看输出结果(仅展示部分):
{
"city1": "澳门",
"city2": "澳门",
"city3": "花地玛堂区",
"code1": "820000",
"code2": "820000",
"code3": "820008"
}
{
"city1": "澳门",
"city2": "澳门",
"city3": "澳门特别行政区直辖",
"code1": "820000",
"code2": "820000",
"code3": "820010"
}
总结
无论是用Map还是类存放, EasyExcel.XXXXXX.doReadSync();
最终返回值都是List类型。集合中的每一个元素都是一行数据,这个要理解。
session
需要session的原因是cookie是存放在客户端浏览器的,而且是临时的。
收集session信息
- 登录地址
- 执行方式(GET/POST)
- Host
- Referer
- User-Agent
- 表单数据,数据名称和数据值
以我登录时光网为例子:
点击登录,之后
点击 signinLogin ,红框里面的内容就是需要的信息。
编程实现
把OkHttpClient改为类变量,目的是在整个类中使用同一个对象执行HTTP请求,提升效率。
package com.youkeda.test.http;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.FormBody;
import okhttp3.FormBody.Builder;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
public class PageLoginer {
// 用 CookieJar 实现 cookie 的存储,便于登录后请求其它 URL 可以复用
private static final OkHttpClient okHttpClient = new OkHttpClient.Builder()
.cookieJar(new CookieJar() {
// 把登录完毕后的 cookie 存储下来,再次发请求的时候复用
private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
cookieStore.put("mtime.com", cookies);
System.out.println("[saveFromResponse]url.host()=" + url.host());
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
System.out.println("[loadForRequest]url.host()=" + url.host());
List<Cookie> cookies = cookieStore.get("mtime.com");
return cookies != null ? cookies : new ArrayList<>();
}
})
.build();
public String postContent(String url, Map<String, String> formData) {
//post方式提交的数据
Builder builder = new FormBody.Builder();
// 放入表单数据
for (String key : formData.keySet()) {
builder.add(key, formData.get(key));
}
// 构建 FormBody 对象
FormBody formBody = builder.build();
// 指定 post 方式提交FormBody
Request request = new Request.Builder()
.url(url)
.post(formBody)
.addHeader("User-Agent",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36")
.addHeader("Referer","https://passport.mtime.com/member/signin/?redirectUrl=http%3A%2F%2Fwww.mtime.com%2F")
.addHeader("Host","passport.mtime.com")
.build();
// 返回结果字符串
String result = null;
try {
result = okHttpClient.newCall(request).execute().body().string();
} catch (IOException e) {
System.out.println("request " + url + " error . ");
e.printStackTrace();
}
return result;
}
public static void main(String[] args) {
// 登录页面 url
String url = "https://passport.mtime.com/member/signinLogin";
// 登录表单数据
Map<String, String> formData = new HashMap();
formData.put("loginEmailText", "1885207xxxx");
formData.put("loginPasswordText","1848b7d334d85c484d315e53d43cfda6");
formData.put("isvcode","true");
formData.put("isAutoSign","false");
PageLoginer asker = new PageLoginer();
String content = asker.postContent(url, formData);
System.out.println(content);
}
}
下面的代码是将执行的过程拎出来放在了doExcute()方法中,在postContent()和getContent()中 return doExcute(request);
,postContent()和getContent()过程是类似的,Request不同而已,所以将方法重构,这就是抽象的过程,见扫重复代码,提高可阅读性和可维护性。
package com.youkeda.test.http;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.FormBody;
import okhttp3.FormBody.Builder;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
public class PageLoginer {
// 用 CookieJar 实现 cookie 的存储,便于登录后请求其它 URL 可以复用
private static final OkHttpClient okHttpClient = new OkHttpClient.Builder()
.cookieJar(new CookieJar() {
private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
cookieStore.put("mtime.com", cookies);
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
List<Cookie> cookies = cookieStore.get("mtime.com");
return cookies != null ? cookies : new ArrayList<>();
}
})
.build();
/**
* 向指定的 URL 提交数据,并返回提交后的结果,post请求
*/
public String postContent(String url, Map<String, String> formData) {
//post方式提交的数据
Builder builder = new FormBody.Builder();
// 放入表单数据
for (String key : formData.keySet()) {
builder.add(key, formData.get(key));
}
// 构建 FormBody 对象
FormBody formBody = builder.build();
// 指定 post 方式提交FormBody
Request request = new Request.Builder()
.url(url)
.post(formBody)
.addHeader("User-Agent",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36")
.addHeader("Referer",
"https://passport.mtime.com/member/signin/?redirectUrl=http%3A%2F%2Fwww.mtime.com%2F")
.addHeader("Host", "passport.mtime.com")
.build();
return doExcute(request);
}
/**
* 根据输入的url,读取页面内容并返回,get请求
*/
public String getContent(String url) {
// 定义一个request
Request request = new Request.Builder()
.url(url)
.addHeader("User-Agent",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36")
.addHeader("Host","my.mtime.com")
.build();
return doExcute(request);
}
//执行的过程
private String doExcute(Request request) {
// 返回结果字符串
String result = null;
try {
result = okHttpClient.newCall(request).execute().body().string();
} catch (IOException e) {
// 抓取异常
System.out.println("request " + request.url() + " error . ");
e.printStackTrace();
}
return result;
}
public static void main(String[] args) {
PageLoginer asker = new PageLoginer();
// 完成登录
String url = "https://passport.mtime.com/member/signinLogin";
// 登录表单数据
Map<String, String> formData = new HashMap();
formData.put("loginEmailText", "1885207xxxx");
formData.put("loginPasswordText", "1848b7d334d85c484d315e53d43cfda6");
formData.put("isvcode", "true");
formData.put("isAutoSign", "false");
String content = asker.postContent(url, formData);
System.out.println("login result:");
System.out.println(content);
// 请求我的订单
String myOrderUrl = "http://my.mtime.com/account/ecommerce/orderList/";
String content2 = asker.getContent(myOrderUrl);
System.out.println("order result:");
System.out.println(content2);
}
}