写文件
写入文本文件
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;//读取第一个sheetList<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<>();@Overridepublic void saveFromResponse(HttpUrl url, List<Cookie> cookies) {cookieStore.put("mtime.com", cookies);System.out.println("[saveFromResponse]url.host()=" + url.host());}@Overridepublic 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 方式提交FormBodyRequest 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) {// 登录页面 urlString 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<>();@Overridepublic void saveFromResponse(HttpUrl url, List<Cookie> cookies) {cookieStore.put("mtime.com", cookies);}@Overridepublic 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 方式提交FormBodyRequest 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) {// 定义一个requestRequest 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);}}

