HTTP编程

首先要知道什么是HTTP?

HTTP也是一种协议,是目前最为广泛的基础协议,就是只要需要网络的都需要 HTTP,这也就是所有网址前面都是http.什么东西,它的底层也是基于TCP协议之上的请求-响应的协议,览器请求访问某个网站时发送的HTTP请求-响应。当浏览器希望访问某个网站时,浏览器和网站服务器之间首先建立 TCP 连接,目服务器总是使用 80 端口和加密端口 443,然后,浏览器向服务器发送一个 HTTP 请求,服务器收到后,返回一个 HTTP 响应,并且在响应中包含了 HTML 的网页内容,这样,浏览器解析 HTML 后就可以给用户显示网页了一个完整的 HTTP 请求-响应。

HTTP格式:包括请求头和请求体分别是HTTP Header 和 HTTP  Body,他们的第一行总是请求方法例如,
GET / HTTP/1.1 表示使用 GET 请求,路径是 !,版本是 HTTP/1.1。后续的每一行都是固定的 Header:value 格式,我们称为 HTTP Header ,服务器依靠某些特定的 Header 来识别客
户端请求,例如:
Host:表示请求的域名,因为一台服务器上可能有多个网站,因此有必要依靠 Host 来识別请求是发给哪个网站
Ag;user-Agent :表示客户端自身标识信息,不同的浏览器有不同的标识,服务器依靠 User-Agent 判断客户端类型是 工还是Chrome,是Firefox 还是一个Python 爬虫;
Accept:表示客户端能处理的 HTTP 响应格式,*/* 表示任意格式,text/* 表示任意文本,
image/ png 表示PNG格式的图片:Accept -Language :表示客户端接收的语言,多种语言按优级排序,服务器依靠该字段给用户返回特定语言的网页版本。

请求:
如果是 GET请求,那么该HTTP请求只有HTTP Header,没有HTTP Body。如果是 POST请求,那么该HTTP请求带有Body,以一个空行分隔。    

响应:

响应的第一行总是 HTTP版本 响应代码 响应说明:例如,
HTTP/1.1200 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/1.0协议,每次发送一个HTTP请求,客户端都需要先创建一个新的TCP连接,然后,收到服务器响应后,关闭这个TCP连接。由于建立TCP连接就比较耗时,因此,为了提高效率,HTTP/1.1协议允许在一个TCP连接中反复发送-响应,这样就能大大提高效率:
因为HTTP协议是一个请求-响应协议,客户端在发送了一个HTTP请求后,必须等待服务器响应后,才能发送下一个请求,这样一来,如果某个响应太慢,它就会堵住后面的请求。所以,为了进一步提速,HTTP/2.0允许客户端在没有收到响应的时候,发送多个HTTP请求,服务器返回响应的时候,不一定按顺序返回,只要双方能识别出哪个响应对应哪个请求,就可以做到并行发送和接收:
 

代码的实现

我们可以基于Http编程写一个“爬虫”就是获取某个网站上资源(具体的方法解释代码里有注解)

public static void main(String[] args) {
		try {// 访问豆瓣官网的首页
			URL url = new URL("https://movie.douban.com/");
			// 打开连接
			HttpURLConnection connection = (HttpURLConnection) url.openConnection();
			// 设置请求方式GET(为防止本地网站发现是爬虫)
			connection.setRequestMethod("GET");
			// 设置请求属性(为防止本地网站发现是爬虫,所以是设置一些象人操作的格式 )
			connection.setRequestProperty("user-agent",
					"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3880.400 QQBrowser/10.8.4554.400");
			// 读取到来自网站图片网站
			BufferedReader reader = new BufferedReader(
					new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
			// 用字符串拼接起来
			StringBuilder sb = new StringBuilder();
			String line = null;
			while ((line = reader.readLine()) != null) {
				line = line.trim();
				// 筛选出想要的是图片的地址
				if (line.contains(".jpg") && line.startsWith("<img") && line.contains("https://img")) {
					String ipstr = "";
					String imgstr = "";
					// 方法二用第三方包Jsoup专门用来解析网页的
					// jsoup作用进行原始解析
					// Document类:网页文档(解析到所有所有)
					// elements类:若干元素形成集合(继承子Arraylist)
					// element类; 某一个html
					sb.append(line);
					// 把StringBuilder里边变成字符串
					String strall = sb.toString();

					// 解析Document对象(拿到这个网页的所有文档)
					Document doc = Jsoup.parse(strall);
					// 从Document中获取名称为img所有标签元素(elements)
					// 从所有代表img的elements元素集合中获取元素
					org.jsoup.select.Elements elements = doc.getElementsByTag("img");
					// 因为elements继承自Arraylist所以可以遍历(foreach遍历)
					for (int i = 0; i < elements.size(); i++) {
						Element element = doc.getElementsByTag("img").get(i);
						// 获取img标签元素src和alt属性
						ipstr = element.attr("src");
						imgstr = element.attr("alt");
						System.out.println(ipstr);
						System.out.println(imgstr);
					}
//				for (Element element : elements) {
//					ipstr = element.attr("src");
//					imgstr = element.attr("alt");
//					System.out.println(ipstr);
//					System.out.println(imgstr);
//				}
					// 访问照片连接
					URL urlimg = new URL(ipstr);
					// 与照片地址建立连接
					HttpURLConnection imgconnection = (HttpURLConnection) urlimg.openConnection();
					// 照片读到是流,所以拿一个输入流来获取
					try (BufferedInputStream in = new BufferedInputStream(imgconnection.getInputStream());
							BufferedOutputStream out = new BufferedOutputStream(// 写在某文件夹里
									new FileOutputStream("C:\\pic\\pic1\\" + imgstr + ".jpg"));) {

						byte[] buff = new byte[1024];
						int len = -1;
						while ((len = in.read(buff)) != -1) {
							out.write(buff, 0, len);
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

运行结果

 

  • 10
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值