目录

HTTP协议概述

HTTP固定响应代码

浏览器向服务器发送请求并获得响应

爬取网页内容

爬取网页图片


HTTP协议概述

HTTP就是目前使用最广泛的Web应用程序使用的基础协议,例如,浏览器访问网站,手机App访问后台服务器,都是通过HTTP协议实现的,HTTP是HyperText Transfer Protocol的缩写,翻译为超文本传输协议,它是基于TCP协议之上的一种请求-响应协议。

当浏览器希望访问某个网站时,浏览器和网站服务器之间首先建立TCP连接,且服务器总是使用80端口和加密端口443,然后,浏览器向服务器发送一个HTTP请求,服务器收到后,返回一个HTTP响应,并且在响应中包含了HTML的网页内容,这样,浏览器解析HTML后就可以给用户显示网页了。一个完整的HTTP请求-响应如下:

            GET / HTTP/1.1Host: www.sina.com.cnUser-Agent: Mozilla/5 MSIEAccept: */*                ┌────────┐
┌─────────┐ Accept-Language: zh-CN,en  │░░░░░░░░│
│O ░░░░░░░│───────────────────────────>├────────┤
├─────────┤<───────────────────────────│░░░░░░░░│
│         │ HTTP/1.1 200 OK            ├────────┤
│         │ Content-Type: text/html    │░░░░░░░░│
└─────────┘ Content-Length: 133251     └────────┘Browser   <!DOCTYPE html>              Server<html><body><h1>Hello</h1>...

HTTP请求的格式是固定的,它是由HTTP Header和HTTP Body两部分构成。第一行总是请求方法 路径 HTTP版本 :例如, GET / HTTP/1.1 表示使用GET请求,路径是 /,版本是HTTP/1.1。后续的每一行都是固定的Header:Value格式,我们称为HTTP Header,服务器依靠某些特定的Header来识别客户端的请求,例如:

Host:表示请求的域名,因为一台服务器上可能有多个网站,因此有必要依靠Host来识别请求是发给哪个网站的;

User-Agent:表示客户端自身表示信息,不同的浏览器有不同的标识,服务器依靠User-Agent判断客户端类型是IE还是Chrome,是Firefox还是一个Python爬虫;

Accept:表示客户端接收能处理的HTTP响应格式,*/*表示任意格式,text/*表示任意文本,image/png表示PNG格式的图片;

Accept-Language:表示客户端接收的语言,多种语言按优先级排序,服务器依靠该字段给用户返回特定语言的网页脚本。

GET请求没用HTTP Body。只有HTTP Header,POST请求带有Body,以一个空行分隔。带Body的HTTP请求如下:

POST /login HTTP/1.1
Host: www.example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 30username=hello&password=123456

HTTP响应也是有Header和Body两部分组成,一个典型的HTTP响应如下:

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 133251<!DOCTYPE html>
<html><body>
<h1>Hello</h1>
...

响应的第一行总是HTTP版本 响应代码 响应说明:例如:HTTP/1.1 200 OK 表示版本是HTTP/1.1,响应代码是200,响应说明是OK。客户端值依赖响应代码判断HTTP响应是否成功。

HTTP固定响应代码

1xx:表示一个提示性响应,例如101表示将切换协议,常见于WebSocket连接;

2xx:表示一个成功的响应,例如200表示响应成功,206表示值发送了部分内容;

3xx:表示一个重定向的响应,例如301表示永久重定向,303表示客户端该按指定路径重新发送请求。

4xx:表示一个因为客户端问题导致的错误响应,例如400表示因为Content-Type等各种原因导致的无效请求,404表示指定的路径不存在;

5xx:表示一个因为服务器问题导致的错误响应,例如500表示服务器内部故障,503表示服务器再试无法响应。

服务器总是被动地接收客户端的一个HTTP请求,然后响应它。客户端则根据需要发送若干个HTTP请求。

对于早期的HTTP/1.0协议,每次发送一个HTTP请求,客户端都需要先创建一个新的TCP连接,然后,收到服务器响应后,关闭这个TCP连接。由于建立TCP连接就比较耗时,因此,为了提高效率,HTTP/1.1协议允许在一个TCP连接中反复发送-响应,这样就能大大提高效率:

                       ┌─────────┐
┌─────────┐            │░░░░░░░░░│
│O ░░░░░░░│            ├─────────┤
├─────────┤            │░░░░░░░░░│
│         │            ├─────────┤
│         │            │░░░░░░░░░│
└─────────┘            └─────────┘│      request 1       ││─────────────────────>││      response 1      ││<─────────────────────││      request 2       ││─────────────────────>││      response 2      ││<─────────────────────││      request 3       ││─────────────────────>││      response 3      ││<─────────────────────│▼                      ▼

因为HTTP协议是一个请求-响应协议,客户端在发送了一个HTTP请求后,必须等待服务器响应后,才能发送下一个请求,这样一来,如果某个响应太慢,它就会堵住后面的请求。所以,为了进一步提速,HTTP/2.0允许客户端在没有收到响应的时候,发送多个HTTP请求,服务器响应的时候,不一定按顺序返回,只要双方能识别那个响应对应那个请求,就可以做到并行发送和节后:

                       ┌─────────┐
┌─────────┐            │░░░░░░░░░│
│O ░░░░░░░│            ├─────────┤
├─────────┤            │░░░░░░░░░│
│         │            ├─────────┤
│         │            │░░░░░░░░░│
└─────────┘            └─────────┘│      request 1       ││─────────────────────>││      request 2       ││─────────────────────>││      response 1      ││<─────────────────────││      request 3       ││─────────────────────>││      response 3      ││<─────────────────────││      response 2      ││<─────────────────────│▼                      ▼

浏览器向服务器发送请求并获得响应

public static void main(String[] args) {//服务器监听端口try (ServerSocket server = new ServerSocket(8888)) {while(true) {//获取客户端连接Socket browserClient = server.accept();
//              BufferedReader reader = new BufferedReader(new InputStreamReader(browserClient.getInputStream()));
//              String line = null;
//              while((line = reader.readLine())!=null) {
//                  System.out.println(line);
//              }//模拟服务器响应try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(browserClient.getOutputStream()))){writer.write("HTTP/1.1 200 OK");writer.newLine();writer.newLine();writer.write("服务器返回一个相应!内容为:");writer.write(UUID.randomUUID().toString());} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}

 服务器获得请求:

浏览器收到响应:

浏览器通过IP地址和端口号与服务器建立连接后,向服务器发送请求,服务器收到后向浏览器返回一个相应。

爬取网页内容

public static void main(String[] args) {try {// 统一资源定位符URL url = new URL("http://www.baidu.com/index.html");// 应用层:URLConnection,打开链接URLConnection connection = url.openConnection();System.out.println(connection);System.out.println("HTTP连接类型:" + connection.getClass());// 通过输入流,获取网页内容BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));String line = null;while ((line = reader.readLine()) != null) {System.out.println(line);}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}

当客户端与网页建立连接后,可用Url对象的openConnection()方法返回一个URLConnetion对象,然后通过此对象获得输入流来获取网页的源代码。

爬取网页图片

package x.cc;import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;public class Work7184 {public static void main(String[] args) {HttpURLConnection connection;try {URL imageUrl = new URL("https://movie.douban.com/");connection = (HttpURLConnection) imageUrl.openConnection();connection.setRequestMethod("GET");connection.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.62");try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {String line = null;while ((line = reader.readLine()) != null) {line = line.trim();if (line.contains("jpg") && line.startsWith("<img") && line.contains("https://img")) {System.out.println(line);//提取图片的路径src、电影名称altString src = "",alt = "";//解析生成Document对象Document doc = Jsoup.parse(line);//从Document中获取名称为img的所有标签元素(Elements)//从所有代表img的Elements元素集合中获取第一个Element imgElement = doc.getElementsByTag("img").first();//获取img标签元素src属性和alt属性src = imgElement.attr("src");alt = imgElement.attr("alt");URL resultUrl = new URL(src);HttpURLConnection imageUrlConnection = (HttpURLConnection) resultUrl.openConnection();try (BufferedInputStream in = new BufferedInputStream(imageUrlConnection.getInputStream());BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("C:\\Users\\admin\\Desktop\\ABCD\\"+alt+".jpg"));){byte[] buff = new byte[1024];int len = -1;while((len = in.read(buff))!=-1) {out.write(buff,0,len);}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}

当我们获得网页的内容后使用Jsoup解析html,Jsoup的parse()方法是返回一个Document对象,然后从Document中获取名称为img的所有标签元素Elements,然后从所有代表ima的Elements元素集合中获取第一个就是我们想要的Element对象。然后就可以获取img标签元素src属性和alt属性。然后创建出URL对象和HttpUrlConnection对象结合输入输出流就能获取网页中我们想要的图片。

​​​​​​​​​​​​​​

Java之HTTP编程相关推荐

  1. Scala程序设计:Java虚拟机多核编程实战(国内第一本Scala图书)

    Scala程序设计:Java虚拟机多核编程实战(国内第一本Scala图书) 基本信息 作者: (美)Venkat Subramaniam  译者: 郑晔 李剑 丛书名: 图灵程序设计丛书 出版社:人民 ...

  2. Netty:Java 领域网络编程的王者

    一.简介 1. 课程背景 分布式系统的根基在于网络编程,而 Netty 是 Java 领域网络编程的王者. 2. 课程内容 第一部分 NIO 编程,三大组件 第二部分 Netty 入门学习,Event ...

  3. Java 7并发编程实战手册

    2019独角兽企业重金招聘Python工程师标准>>> Java 7并发编程实战手册 本书是 Java 7 并发编程的实战指南,介绍了Java 7 并发API 中大部分重要而有用的机 ...

  4. JAVA网络IO编程

    2019独角兽企业重金招聘Python工程师标准>>> JAVA网络IO编程(BIO NIO AIO) 一.传统的BIO编程 1.网络编程的基本模型是C/S模型,即两个进程间的通信. ...

  5. 《Java Web高级编程——涵盖WebSockets、Spring Framework、JPA H

    2019独角兽企业重金招聘Python工程师标准>>> <Java Web高级编程--涵盖WebSockets.Spring Framework.JPA Hibernate和S ...

  6. Java 7 并发编程指南

    原文是发表在并发编程网上翻译后的 <Java 7 并发编程指南>,这里对其中的目录做个更加详细的描述,并且写出了重点说明,方便日后快速查阅.建议仔细查看每节的代码实现,非常具有参考价值.可 ...

  7. 阿里云 刷新缓存 java_【从入门到放弃-Java】并发编程-NIO-Buffer

    前言 上篇[从入门到放弃-Java]并发编程-NIO-Channel中我们学习到channel是双向通道,数据通过channel在实体(文件.socket)和缓冲区(buffer)中可以双向传输. 本 ...

  8. Java Review - 并发编程_ 回环屏障CyclicBarrier原理源码剖析

    文章目录 Pre 小Demo 类图结构 CyclicBarrier核心方法源码解读 int await() int await(long timeout, TimeUnit unit) int dow ...

  9. Java Review - 并发编程_ScheduledThreadPoolExecutor原理源码剖析

    文章目录 概述 类结构 核心方法&源码解析 schedule(Runnable command, long delay,TimeUnit unit) scheduleWithFixedDela ...

  10. Java Review - 并发编程_ArrayBlockingQueue原理源码剖析

    文章目录 概述 类图结构 构造函数 主要方法源码解析 offer操作 put操作 poll操作 take操作 peek操作 size 小结 概述 Java Review - 并发编程_LinkedBl ...

最新文章

  1. ubuntu安装和查看已安装
  2. php用ajaxs上传图片_php+ajax实现图片文件上传功能实例
  3. 白话Elasticsearch22- 深度探秘搜索技术之match_phrase_prefix实现search-time搜索推荐
  4. 听说Attention与Softmax更配哦~
  5. 深入理解javascript原型和闭包(3)——prototype原型
  6. linux jrdmm 命令 局部 编译,Cgminer-4.10.0 Linux 挖矿
  7. python清空列表的方法
  8. const 修饰函数参数,返回值,函数体,保护数据
  9. 关于自己的ES6使用姿势
  10. IO库----IO类,文件输入输出,string流
  11. DB2-SQLCODE 错误码大全---[IBM官方]
  12. 《老路用得上的商学课》91-95学习笔记
  13. PHOTOSHOP 小技巧
  14. MC开服教程2:材质包法自定义唱片音乐
  15. 李彦宏偷换概念还是危言耸听?
  16. 财报发布前获多家投行认可,借商流+物流闭环效应达达估值可期
  17. JAVA—— MySQL高级(二)
  18. IOS调起app的终极方法:Universal Links
  19. 获取指定日期所在月的最后一个工作日
  20. EclipseCDT

热门文章

  1. java pdf转word,没页数限制,去除水印
  2. MySQL 查询数据库和表在使用的引擎和编码并修改使用引擎和编码
  3. Canvas API
  4. 函数:判断表达式括弧是否匹配
  5. 108. SAP UI5 图片显示控件 Avatar 的使用方式介绍
  6. 格兰因果模型可以分析哪些东西_结构方程模型(SEM)和分段结构方程模型
  7. 系统学习Linux建议
  8. Vue Echarts 显示地图且根据坐标设置标注点
  9. 游戏制作之路-愤怒的小鸟-3(源码下载地址)
  10. 无重复字符的最长子串(加注释)