Java网络编程下载文件和图片、session/cookie - 图1

写文件

写入文本文件

  1. import java.io.File;
  2. import java.io.FileWriter;
  3. //创建文件对象
  4. File file = new File("a.txt");
  5. //写入内容
  6. FileWriter fileWriter = new FileWriter(file.getName());
  7. fileWriter.write(content);
  8. //关闭
  9. fileWriter.close();

写入二进制文件

  1. import java.io.File;
  2. import java.io.FileOutputStream;
  3. //创建文件对象
  4. File file = new File("a.xlsx");
  5. //写入内容
  6. FileOutputStream fos = new FileOutputStream(file);
  7. fos.write(data);//data是字节数组类型
  8. //关闭
  9. fos.flush();//先刷新
  10. fos.close();

解析execl

添加依赖库

  1. <dependency>
  2. <groupId>com.alibaba</groupId>
  3. <artifactId>easyexcel</artifactId>
  4. <version>2.1.6</version>
  5. </dependency>

调用库

excel文件是多表模式,每个sheet是一个表,所以解析数据的顺序一定是: sheet->行->列
第一个单元格的位置是0,第一个sheet,第一行,第一列的位置是0,0,0。下面的例子用Map存放列值是因为我们不能确定excel每一列的含义。

  1. import com.alibaba.excel.EasyExcel;
  2. import java.util.Map;
  3. import java.util.List;
  4. //读取第一个sheet
  5. List<Map<Integer,String>> sheetDatas = EasyExcel.read("a.xlsx").sheet(0).doReadSync();
  6. //List数组中每个元素存放的是一行数据
  7. for(Map<Integer,String> rowDatas:sheetDatas){
  8. //Map中用序号指代每一列
  9. for(Integer index:rowData.keySet()){
  10. //列值
  11. String columuValue = rowData.get(index);
  12. }
  13. }

自动转换为类

当我们提前确定了每一列的含义就可以用对象来表示。

  1. public class DemoData {
  2. private String code1;
  3. private String city1;
  4. private String code2;
  5. private String city2;
  6. private String code3;
  7. private String city3;
  8. //setter,getter省略
  9. }

head(DemoData.class) 表示一行数据,此类的每一个属性表示一列值,返回值为 List<DomeData> 表示每一行转换为一个 DomeData 的实例对象,放入List集合中。

  1. import com.alibaba.excel.EasyExcel;
  2. import java.util.List;
  3. List<DemoData> sheetDatas = EasyExcel.read("a.xlsx").head(DemoData.class).sheet(0).doReadSync();
  4. for(DemoData rowData:datas){
  5. System.out.println(JSON.toJSONString(rowData))
  6. }

查看输出结果(仅展示部分):

  1. {
  2. "city1": "澳门",
  3. "city2": "澳门",
  4. "city3": "花地玛堂区",
  5. "code1": "820000",
  6. "code2": "820000",
  7. "code3": "820008"
  8. }
  9. {
  10. "city1": "澳门",
  11. "city2": "澳门",
  12. "city3": "澳门特别行政区直辖",
  13. "code1": "820000",
  14. "code2": "820000",
  15. "code3": "820010"
  16. }

总结

无论是用Map还是类存放, EasyExcel.XXXXXX.doReadSync(); 最终返回值都是List类型。集合中的每一个元素都是一行数据,这个要理解。

session

需要session的原因是cookie是存放在客户端浏览器的,而且是临时的。

收集session信息

  1. 登录地址
  2. 执行方式(GET/POST)
  3. Host
  4. Referer
  5. User-Agent
  6. 表单数据,数据名称和数据值

以我登录时光网为例子:
QQ图片20200617204501.png
点击登录,之后
QQ图片20200617204814.png
点击 signinLogin ,红框里面的内容就是需要的信息。
QQ图片20200617205114.png
QQ图片20200617205215.png

编程实现

把OkHttpClient改为类变量,目的是在整个类中使用同一个对象执行HTTP请求,提升效率。

  1. package com.youkeda.test.http;
  2. import java.io.IOException;
  3. import java.util.ArrayList;
  4. import java.util.HashMap;
  5. import java.util.List;
  6. import java.util.Map;
  7. import okhttp3.Cookie;
  8. import okhttp3.CookieJar;
  9. import okhttp3.FormBody;
  10. import okhttp3.FormBody.Builder;
  11. import okhttp3.HttpUrl;
  12. import okhttp3.OkHttpClient;
  13. import okhttp3.Request;
  14. public class PageLoginer {
  15. // 用 CookieJar 实现 cookie 的存储,便于登录后请求其它 URL 可以复用
  16. private static final OkHttpClient okHttpClient = new OkHttpClient.Builder()
  17. .cookieJar(new CookieJar() {
  18. // 把登录完毕后的 cookie 存储下来,再次发请求的时候复用
  19. private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
  20. @Override
  21. public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
  22. cookieStore.put("mtime.com", cookies);
  23. System.out.println("[saveFromResponse]url.host()=" + url.host());
  24. }
  25. @Override
  26. public List<Cookie> loadForRequest(HttpUrl url) {
  27. System.out.println("[loadForRequest]url.host()=" + url.host());
  28. List<Cookie> cookies = cookieStore.get("mtime.com");
  29. return cookies != null ? cookies : new ArrayList<>();
  30. }
  31. })
  32. .build();
  33. public String postContent(String url, Map<String, String> formData) {
  34. //post方式提交的数据
  35. Builder builder = new FormBody.Builder();
  36. // 放入表单数据
  37. for (String key : formData.keySet()) {
  38. builder.add(key, formData.get(key));
  39. }
  40. // 构建 FormBody 对象
  41. FormBody formBody = builder.build();
  42. // 指定 post 方式提交FormBody
  43. Request request = new Request.Builder()
  44. .url(url)
  45. .post(formBody)
  46. .addHeader("User-Agent",
  47. "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")
  48. .addHeader("Referer","https://passport.mtime.com/member/signin/?redirectUrl=http%3A%2F%2Fwww.mtime.com%2F")
  49. .addHeader("Host","passport.mtime.com")
  50. .build();
  51. // 返回结果字符串
  52. String result = null;
  53. try {
  54. result = okHttpClient.newCall(request).execute().body().string();
  55. } catch (IOException e) {
  56. System.out.println("request " + url + " error . ");
  57. e.printStackTrace();
  58. }
  59. return result;
  60. }
  61. public static void main(String[] args) {
  62. // 登录页面 url
  63. String url = "https://passport.mtime.com/member/signinLogin";
  64. // 登录表单数据
  65. Map<String, String> formData = new HashMap();
  66. formData.put("loginEmailText", "1885207xxxx");
  67. formData.put("loginPasswordText","1848b7d334d85c484d315e53d43cfda6");
  68. formData.put("isvcode","true");
  69. formData.put("isAutoSign","false");
  70. PageLoginer asker = new PageLoginer();
  71. String content = asker.postContent(url, formData);
  72. System.out.println(content);
  73. }
  74. }

下面的代码是将执行的过程拎出来放在了doExcute()方法中,在postContent()getContent()return doExcute(request); ,postContent()和getContent()过程是类似的,Request不同而已,所以将方法重构,这就是抽象的过程,见扫重复代码,提高可阅读性和可维护性。

  1. package com.youkeda.test.http;
  2. import java.io.IOException;
  3. import java.util.ArrayList;
  4. import java.util.HashMap;
  5. import java.util.List;
  6. import java.util.Map;
  7. import okhttp3.Cookie;
  8. import okhttp3.CookieJar;
  9. import okhttp3.FormBody;
  10. import okhttp3.FormBody.Builder;
  11. import okhttp3.HttpUrl;
  12. import okhttp3.OkHttpClient;
  13. import okhttp3.Request;
  14. public class PageLoginer {
  15. // 用 CookieJar 实现 cookie 的存储,便于登录后请求其它 URL 可以复用
  16. private static final OkHttpClient okHttpClient = new OkHttpClient.Builder()
  17. .cookieJar(new CookieJar() {
  18. private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
  19. @Override
  20. public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
  21. cookieStore.put("mtime.com", cookies);
  22. }
  23. @Override
  24. public List<Cookie> loadForRequest(HttpUrl url) {
  25. List<Cookie> cookies = cookieStore.get("mtime.com");
  26. return cookies != null ? cookies : new ArrayList<>();
  27. }
  28. })
  29. .build();
  30. /**
  31. * 向指定的 URL 提交数据,并返回提交后的结果,post请求
  32. */
  33. public String postContent(String url, Map<String, String> formData) {
  34. //post方式提交的数据
  35. Builder builder = new FormBody.Builder();
  36. // 放入表单数据
  37. for (String key : formData.keySet()) {
  38. builder.add(key, formData.get(key));
  39. }
  40. // 构建 FormBody 对象
  41. FormBody formBody = builder.build();
  42. // 指定 post 方式提交FormBody
  43. Request request = new Request.Builder()
  44. .url(url)
  45. .post(formBody)
  46. .addHeader("User-Agent",
  47. "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")
  48. .addHeader("Referer",
  49. "https://passport.mtime.com/member/signin/?redirectUrl=http%3A%2F%2Fwww.mtime.com%2F")
  50. .addHeader("Host", "passport.mtime.com")
  51. .build();
  52. return doExcute(request);
  53. }
  54. /**
  55. * 根据输入的url,读取页面内容并返回,get请求
  56. */
  57. public String getContent(String url) {
  58. // 定义一个request
  59. Request request = new Request.Builder()
  60. .url(url)
  61. .addHeader("User-Agent",
  62. "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")
  63. .addHeader("Host","my.mtime.com")
  64. .build();
  65. return doExcute(request);
  66. }
  67. //执行的过程
  68. private String doExcute(Request request) {
  69. // 返回结果字符串
  70. String result = null;
  71. try {
  72. result = okHttpClient.newCall(request).execute().body().string();
  73. } catch (IOException e) {
  74. // 抓取异常
  75. System.out.println("request " + request.url() + " error . ");
  76. e.printStackTrace();
  77. }
  78. return result;
  79. }
  80. public static void main(String[] args) {
  81. PageLoginer asker = new PageLoginer();
  82. // 完成登录
  83. String url = "https://passport.mtime.com/member/signinLogin";
  84. // 登录表单数据
  85. Map<String, String> formData = new HashMap();
  86. formData.put("loginEmailText", "1885207xxxx");
  87. formData.put("loginPasswordText", "1848b7d334d85c484d315e53d43cfda6");
  88. formData.put("isvcode", "true");
  89. formData.put("isAutoSign", "false");
  90. String content = asker.postContent(url, formData);
  91. System.out.println("login result:");
  92. System.out.println(content);
  93. // 请求我的订单
  94. String myOrderUrl = "http://my.mtime.com/account/ecommerce/orderList/";
  95. String content2 = asker.getContent(myOrderUrl);
  96. System.out.println("order result:");
  97. System.out.println(content2);
  98. }
  99. }