23中级 - Java Web:HTTP基础【爬虫项目实战】

488 阅读3分钟

互联网所有的基石

  • http协议

1.png - 第一行请求跟路径 - User-Agent用户代理,浏览器,后端可以根据这个信息知道是谁 - 实战反爬虫

2.png

  • post 数据放body,会有request payload,放json数据

  • 上传文件也会方body

状态码

  • 响应第一行决定
  • 101,1开头很少见,101切换协议
  • 200 成功
  • 3xx重定向,301永久重定向
  • 4xx,客户端有问题,405请求方法被禁止,有趣网站,451,来自小说梗《华氏451度》,表示因为一些法律的原因。418 我是一个咖啡壶,表示服务器拒绝冲泡咖啡,生产环境没用,1998年的愚人节玩笑
  • 5**,服务器的错误

HTTP的header与body

  • HTTP的Header有两种,request Header和response Header
  • java代码模仿的请求头,区分是否是爬虫,实现基本的伪装

3.png

package com.github.hcsp;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

import java.io.IOException;
import java.io.InputStream;

public class Main {
    public static void main(String[] args) throws IOException {
        // 创建一个default 客户端
        CloseableHttpClient httpclient = HttpClients.createDefault();
        // 发起了一个http Get请求

        HttpGet httpGet = new HttpGet("http://localhost:8080/auth");
        // 伪装成浏览器
        httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)");
        // 执行这个请求拿到response
        CloseableHttpResponse response = httpclient.execute(httpGet);
        try {
            // getStatusLine就是http response的第一行
            System.out.println(response.getStatusLine());
            HttpEntity entity1 = response.getEntity();
            InputStream is = entity1.getContent();

            String html = IOUtils.toString(is, "UTF-8");
            System.out.println(html);
        } finally {
            response.close();
        }
    }
}

request Header里面的的属性

  • referer,网页从哪里来的,正确的拼写方法其实是referrer
  • accept-header

response Header

  • 使用content type这种response header,服务器就告诉浏览器,当前的字节流是什么数据,下载,图片

Http协议是无状态的

  • cookie是最重要的响应头,是整个网络请求的安全基石

4非常重要的Set-Cookie响应.png

  • 第一次访问的时候会返回setCookie,之后每一次都会访问都会带上cookie,cookie只对同一个域名有效

5.png

  • java模仿携带cookie访问

6.png

  • cookie是有效期的

课后练习题

  • 读写文件
package com.github.hcsp.io;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class FileAccessor {
    public static List<String> readFile1(File file) throws IOException {
        // 声明输出流
        InputStream inputStream = new FileInputStream(file);
        // 声明输出流的缓存
        StringBuffer stringBuffer = new StringBuffer();
        // 读取输出流
        int readInt = inputStream.read();
        // 只要能读取
        while (readInt != -1) {
            // 写入输出流的缓存
            stringBuffer.append((char) readInt);
            readInt = inputStream.read();
        }
        // 将输出流的缓存转换成字符串
        String intputStr = new String(stringBuffer);
        // 对字符串根据空格进行分割,并添加到列表
        List<String> list = Arrays.asList(intputStr.split("\n"));
        // 输入流关闭
        inputStream.close();
        // 返回列表
        return list;
    }


    public static List<String> readFile2(File file) throws IOException {
        // 声明空的数组
        List<String> list = new ArrayList<>();
        // 声明BufferedReader的类对FileReader包装
        BufferedReader bufferedReader = new BufferedReader(new FileReader(String.valueOf(file.toPath())));
        // 读取一行
        String lineStr = bufferedReader.readLine();
        while (lineStr != null) {
            // 将读取的行添加到列表,只要不为空就一直添加
            list.add(lineStr);
            lineStr = bufferedReader.readLine();
        }

        // 关闭bufferedReader
        bufferedReader.close();
        return list;
    }

    public static List<String> readFile3(File file) throws IOException {
        return Files.readAllLines(file.toPath());
    }

    public static void writeLinesToFile1(List<String> lines, File file) throws IOException {
        // 声明文件输出流
        FileOutputStream fileOutputStream = new FileOutputStream(file);
        for (String string : lines) {
            // 获取string的二进制字节流
            byte b[] = string.getBytes();
            // 输出流将二进制
            fileOutputStream.write(b);
            // 输入空白字符
            fileOutputStream.write('\n');
        }
        // 输出流关闭
        fileOutputStream.close();
    }

    public static void writeLinesToFile2(List<String> lines, File file) throws IOException {
        // 用bufferedWriter类包装fileWriter类
        // fileWriter类 传入路径
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(String.valueOf(file.toPath())));
        String write = "";
        for (String string : lines) {
            write += string + "\n";
        }
        // bufferedWriter写入字符串
        bufferedWriter.write(write);
        // 关闭bufferedWriter
        bufferedWriter.close();
    }

    public static void writeLinesToFile3(List<String> lines, File file) throws IOException {
        Files.write(file.toPath(), lines);
    }

    public static void main(String[] args) throws IOException {

    }
}