要进行网络通信,需要建立起通信双方的连接,连接的双方分别称为客户端和服务端,在Python中,使用套接字socket来建立起网络连接。 套接字包含在socket模块中:
import socket
socket.socket()
对于客户端和服务端,都是使用socket来建立连接的,但是在使用行为上,客户端和服务端会有一些不一样。
服务端建立需要四个步骤:新建socket、绑定IP和端口(bind)、监听连接(listen)、接受连接(accept)。
客户端建立则简单一些,仅需两个步骤:新建socket、连接服务端(connect)。 当网络连接上以后,客户端和服务端就可以进行数据通信了,套接字通过send()函数发送数据,通过recv()函数接收数据。
先看服务端的过程,新建一个server.py的文件:
import socket
server = socket.socket() # 1. 新建socket
server.bind(('127.0.0.1', 8999)) # 2. 绑定IP和端口(其中127.0.0.1为本机回环IP)
server.listen(5) # 3. 监听连接
s, addr = server.accept() # 4. 接受连接
print('connect addr:{}'.format(addr))
content =s.recv(1024)
print(str(content, encoding='utf-8')) # 接受来自客户端的消息,并编码打印出来
s.close()
如上,服务端就编写完毕,接下来是编写客户端,新建一个client.py的文件:
import socket
client = socket.socket() # 1. 新建socket
client.connect(('127.0.0.1', 8999)) # 2. 连接服务端(注意,IP和端口要和服务端一致)
client.send(bytes('Hello World. Hello Socket', encoding='utf-8')) # 发送内容,注意发送的是字节字符串。
client.close()
接着在一个终端先运行服务端:
python server.py
然后再在另外一个终端运行客户端:
python client.py
在服务端的终端,将会输出以下信息:
connect addr:('127.0.0.1', 50382)
b'Hello World. Hello Socket'
在互联网的世界中,网页、手机H5等都是通过HTTP向用户提供服务的,这些信息存储在HTTP服务器中,HTTP服务器是一种特殊的Socket服务器,它在网络连接之上,定义了HTTP协议,使得网页、手机H5等数据,都可以以标准的HTTP协议进行传输。
Python提供了简易的HTTP服务器,可以直接运行起来。 在终端,输入这条命令,就可以启动一个HTTP服务器。
python -m http.server
启动成功后,会输出以下信息:
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
提示HTTP服务器在本机8000端口运行,接着就可以在浏览器输入http://127.0.0.1:8000看到由这个服务器提供的网页。
这个HTTP服务器会把运行目录的所有文件列出来,并提供下载功能。
在上一节,使用了Python自带的功能启动了一个HTTP服务器,并通过浏览器浏览到了这个HTTP服务器提供的页面。在浏览的过程中,实际上是浏览器向HTTP服务器发送了一个HTTP请求。
除了使用浏览器发送HTTP请求,通过代码也可以向HTTP服务器发送请求,Python提供了相关的库urllib,通过urllib包里面的request,可以向其他HTTP服务器发起请求。
from urllib import request
response = request.urlopen('https://www.imooc.com') # 向慕课网官网发出请求
print(response) # ==> <http.client.HTTPResponse object at 0x000001377D631948>
请求成功的话,会得到一个HTTPResponse,它是来自HTTP服务器的一个回应,可以把这个回应的一些信息打印出来。
状态码:
print(response.status) # ==> 200
状态码是一个三位整数,在HTTP协议的标准里面,定义了很多状态码,其中200表示请求是正常的。
响应头:
for k, v in response.getheaders():
print('{}: {}'.format(k, v))
将会输出以下信息,这是HTTPResponse附带的一些信息,包括服务端的服务器是什么、请求时间、内容类型、内容长度等等。
Server: openresty
Date: Thu, 20 Aug 2020 08:16:07 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 376639
Connection: close
Vary: Accept-Encoding
Vary: Accept-Encoding
X-Varnish: 280516221 281284036
Age: 29
Via: 1.1 varnish (Varnish/6.0)
X-Cache: HIT from CS42
Accept-Ranges: bytes
Python官方提供的urllib库可以满足一般情况下的HTTP操作,但是urllib这个库设计是用来处理url地址的,并不是专门处理HTTP操作的包。因此,在很多场景下,一般会使用requests库来进行HTTP请求。
requests库是著名的Python第三方库,使用requests库,可以定制化你的HTTP请求,包括请求方法,请求参数等等。
由于requests是第三方库,因此在使用前,需要安装。
pip install requests
安装完成后,使用requests库来请求百度。
response = requests.get('https://www.baidu.com')
# 打印状态码
print(response.status_code)
# 打印回应头
print(response.headers)
在一般的使用上,requests和urllib没有太大区别,但是在复杂的场景中,requests可以提供urllib无法提供的强大功能。因此,在使用上,建议使用requests库代替urllib库来进行HTTP请求等的操作。
通过urllib或者requests请求后,会得到一个HTTPResponse,HTTPResponse拥有状态码、回应头等的信息。
但我们知道,对于一个页面,通常是由文字、图片等信息组成的,这些属于一个HTTPResponse的内容。
import requests
response = requests.get('https://www.baidu.com')
content = str(response.content, encoding='utf-8') # ==> 打印具体内容
打印的结果是一个很长的字符串,显得杂乱无章,但其实它是由结构的,它是一个标准的HTML页面,可以从页面内容里面获取很多有用的数据。
网络爬虫是典型的应用程序,它的工作原理就是通过不断的请求互联网的页面,并从回应中解析获取出有用的数据;数据积累后,可以有很多用处。
通过requests获得网页的内容后,我们可以尝试使用一些简单的方法获取页面的内容。
content_list = content.split('\n') # 分行
len(content_list) # 打印页面内容的行数
在网页中,页面内部链接其他资源的信息是通过href提供的,通过字符串匹配的方式可以过滤出包含链接的行。
for line in content_list:
if 'href' in line:
print(line.strip())
过滤出来的信息或许有些杂乱,但也包含了一些有用的数据,我们可以从过滤后的信息中找到链接相关的信息。不过我们过滤的方式比较简单,通过优化过滤的方式可以匹配到更加精准的数据。而爬虫正是这样工作的。