python模拟浏览器请求web服务器的网页过程


一、浏览器请求的基本流程:

  1. 用户输入网址.
  2. 浏览器请求DNS服务器, 获取域名对应的IP地址.
  3. 请求连接该IP地址服务器.
  4. 发送资源请求. (HTTP协议)
  5. web服务器接收到请求, 并解析请求, 判断用户意图.
  6. 获取用户想要的资源.
  7. 将资源返回给web服务器程序.
  8. web服务器程序将资源数据通过网络发送给浏览器.
  9. 浏览器解析请求的数据并且完成网页数据的显示.

通过火狐或者谷歌可以调出开发者工具,浏览器右侧菜单-->开发者工具,或者使用快捷键F12

打开的页面如图所示

二、HTTP请求报文协议分析

消息头中,请求头的报文数据内容,下面就是我们要请求的报文示例数据:

HTTP/1.1 200 OK
Date: Sat, 07 Apr 2018 03:05:08 GMT
Content-Type: text/html
Content-Length: 14615
Last-Modified: Fri, 30 Mar 2018 07:37:00 GMT
Connection: Keep-Alive
Vary: Accept-Encoding
Set-Cookie: BAIDUID=18857CBD0F662F5B63E90ECB144BDF06:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: BIDUPSID=18857CBD0F662F5B63E90ECB144BDF06; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: PSTM=1523070308; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
P3P: CP=" OTI DSP COR IVA OUR IND COM "
Server: BWS/1.1
X-UA-Compatible: IE=Edge,chrome=1
Pragma: no-cache
Cache-control: no-cache
Accept-Ranges: bytes

GET / HTTP/1.1 叫做请求行. 里面包含3个信息, 以空格隔开

  • GET:第一个叫做请求方法, 除了 GET 方法外, 还有 POST 方法, 除此之外还有其他方法, 这两种最常用. GET 主要用于从服务器获得数据, POST 主要用于从浏览器提交数据到服务器. 比如注册账号的时候,需要提交信息到服务器上.

  • /:第二个表示请求的资源路径.

  • HTTP/1.1:第三个表示 HTTP 协议的版本.

请求头. 除了第一行之外, 剩下的所有数据的格式都是类似的

  • Host 表示浏览器要请求的主机地址.

  • Connection 表示浏览器和服务器之间的连接方式, 浏览器和服务器连接是长连接还是短连接.

  • User-Agent 用户代理, 我们使用谷歌浏览器和火狐浏览器分别请求百度, 那么会发现 User-Agent 的值是不一样的, 它主要是用于浏览器告诉服务器自己的身份, 比如浏览器端使用的操作系统是什么版本, 浏览器是什么版本等等,如果服务器端就会有反爬机制, 服务器不希望爬虫来获取数据, 所以通过该项可以知道客户端是否是爬虫程序. 如果爬虫程序想伪装成一个浏览器的请求, 就必须设置此项.

  • Accept 表示浏览器告诉服务器, 自己能够接收并识别的文件类型.

  • Accept-Encoding 表示浏览器能够处理的压缩方式. 为什么需要压缩呢? 当网页数据量大的时候, 压缩之后可以提高传输速率, 提高用户体验.
  • Accept-Language 浏览器可以接收的文本语言, 如果非中文编码可能会出现乱码.

请求报文格式总结

三、HTTP相应报文协议分析

消息头中,响应头的报文数据内容:


第一行 HTTP/1.1 200 OK 叫做响应行, 共分成3部分, 

HTTP/1.1:表示 HTTP协议的版本

200:表示响应状态码, 用户向服务器发出了请求, 如果服务器正常返回响应报文, 那么状态码一般都是200

OK: 表示原因短语, 表示对前面状态码的简单描述. 

    响应的状态码除了 200 之外, 还有其他的状态码, 下面是常见的状态码:

    302 redirect, 我们通过 302 状态码可以指示浏览器跳转到某一个 URL.

    404 NOT FOUND, 当我们访问一个不存在的 URL 时, 一般会返回404状态码, 告诉浏览器, 你访问的 URL 是不存在的.

    500 Internal Server Error, 服务器遇到了一个未曾预料的状况, 导致了它无法完成对请求的处理. 一般来说, 这个问题都会在服务器端的源代码出现错误时出现.

第二行下面的所有内容, 我们叫做响应头. Content-Type 表示响应内容的文本格式和编码方式.

响应报文格式总结


下面就来模拟浏览器请求web服务器的网页过程,使用TCP实现 HTTP协议(请求报文格式和响应报文格式)


import socket
import re


# 创建tcp套接字
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 创建和服务器的连接
tcp_socket.connect(("www.baidu.com", 80))

# 拼接请求报文
request_line = "GET / HTTP/1.1\r\n"
request_header = "Host: www.baidu.com\r\n"
User_Agent = "User-Agent: Mozilla/5.0 (Windows NT 6.1; W…) Gecko/20100101 Firefox/59.0\r\n"
request_data = request_line + request_header + User_Agent + "\r\n"

# 发送请求报文,编码
tcp_socket.send(request_data.encode())

# 接收响应报文
recv_data = tcp_socket.recv(4096)
# 解码
recv_data = recv_data.decode()
print(recv_data)
# 关闭连接
tcp_socket.close()


得到的结果:

和之前在浏览器中看到的HTTP响应头是一样的结果

HTTP/1.1 200 OK
Date: Sat, 07 Apr 2018 03:38:09 GMT
Content-Type: text/html
Content-Length: 14615
Last-Modified: Fri, 30 Mar 2018 07:37:00 GMT
Connection: Keep-Alive
Vary: Accept-Encoding
Set-Cookie: BAIDUID=EC4E6F3C74FB72E2594C60BAC6D4A8B9:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: BIDUPSID=EC4E6F3C74FB72E2594C60BAC6D4A8B9; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: PSTM=1523072289; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
P3P: CP=" OTI DSP COR IVA OUR IND COM "
Server: BWS/1.1
X-UA-Compatible: IE=Edge,chrome=1
Pragma: no-cache
Cache-control: no-cache
Accept-Ranges: bytes








猜你喜欢

转载自blog.csdn.net/anyiVIP/article/details/79839863