在 Python 的网络编程领域中,requests模块就如同一位得力助手,为开发者们在网络数据交互的世界里披荆斩棘。它的存在,极大地简化了 HTTP 请求的发送与处理过程,让原本复杂繁琐的网络操作变得轻松易懂。
与 Python 标准库中的urllib、urllib3等网络请求库相比,requests模块有着诸多令人瞩目的优势。首先,它的 API 设计简洁明了,极为人性化,即便是刚接触 Python 网络编程的新手,也能迅速上手。以发送 GET 请求为例,在urllib库中,你可能需要这样编写代码:
import urllib.request
url = 'https://www.example.com'
req = urllib.request.Request(url)
with urllib.request.urlopen(req) as response:
data = response.read().decode('utf-8')
print(data)
而使用requests模块,只需简单的两行代码:
import requests
response = requests.get('https://www.example.com')
print(response.text)
如此对比,高下立判,requests模块的代码简洁性不言而喻。
其次,requests模块在功能的丰富性与全面性上表现出色。它不仅对各种 HTTP 请求方法,如 GET、POST、PUT、DELETE、HEAD、OPTIONS 等提供了原生支持,还能轻松处理请求参数、请求头、Cookies、文件上传等复杂操作。在处理 POST 请求时,若要传递表单数据,requests模块只需将数据以字典形式传递给data参数即可,如下所示:
import requests
url = 'https://www.example.com/login'
data = {'username': 'user', 'password': 'pass'}
response = requests.post(url, data=data)
print(response.text)
反观urllib库,处理此类操作则需要更多的步骤和代码量。
另外,requests模块还具备出色的可扩展性。通过插件和适配器,它能够满足各种特定场景下的需求,例如在处理代理服务器、自定义认证机制等方面,都展现出了强大的灵活性。
从社区支持的角度来看,requests模块拥有庞大且活跃的社区。在遇到问题时,开发者可以轻松地在社区中找到丰富的文档、教程、示例代码以及其他开发者的经验分享,这无疑为解决问题提供了极大的便利,也加快了开发的速度。
在开始使用requests模块之前,首先需要确保它已经被安装到你的 Python 环境中。安装requests模块的方法多种多样,下面为你详细介绍在不同环境下的安装方式。
pip install requests
在安装过程中,pip会自动从 Python Package Index(PyPI)上下载requests模块及其依赖项,并将它们安装到你的 Python 环境中。
若你的pip版本较低,可能会遇到一些问题,此时可以先更新pip:
python -m pip install --upgrade pip
更新完成后,再执行安装requests的命令。
import requests
url = 'https://www.baidu.com'
response = requests.get(url)
print(response.text)
在上述代码中:
import requests
url = 'https://www.baidu.com/s'
params = {'wd': 'Python教程'}
response = requests.get(url, params=params)
print(response.url)
print(response.text)
在这段代码中:
在requests模块中,将请求参数构造成字典,然后利用requests.post()的data参数以 form 表单形式提交数据。下面是一个模拟用户登录的示例:
import requests
url = 'https://example.com/login'
data = {
'username': 'your_username',
'password': 'your_password'
}
response = requests.post(url, data=data)
print(response.text)
在上述代码中:
以下是一个向服务器发送 JSON 数据的示例:
import requests
import json
url = 'https://example.com/api/data'
data = {
'name': 'John',
'age': 30,
'email': '[email protected]'
}
headers = {'Content-Type': 'application/json'}
response = requests.post(url, data=json.dumps(data), headers=headers)
print(response.text)
在这段代码中:
import requests
response = requests.get('https://www.example.com')
print(response.text)
然而,有时服务器返回的编码信息不准确,或者没有提供编码信息,这可能导致乱码问题。此时,可以手动设置response.encoding属性来指定编码方式。例如,如果已知响应内容是 UTF-8 编码,可以这样处理:
import requests
response = requests.get('https://www.example.com')
response.encoding = 'utf-8'
print(response.text)
import requests
url = 'https://example.com/image.jpg'
response = requests.get(url)
with open('image.jpg', 'wb') as f:
f.write(response.content)
在上述代码中:
import requests
response = requests.get('https://example.com/api/data')
try:
data = response.json()
print(data)
except ValueError as e:
print(f"解析JSON数据失败: {e}")
在这段代码中:
根据不同的状态码,我们可以进行相应的处理。例如:
import requests
response = requests.get('https://example.com')
if response.status_code == 200:
print("请求成功,获取到数据:")
print(response.text)
elif response.status_code == 404:
print("请求的资源未找到,请检查URL是否正确。")
else:
print(f"请求失败,状态码: {response.status_code}")
在上述代码中,通过判断response.status_code的值,进行不同的处理,从而提高程序的健壮性和用户体验。
在网络通信中,会话维持是指在一系列连续的请求中保持某些状态信息,使得后续请求能够利用之前请求所建立的状态。在 HTTP 协议中,由于其本身是无状态的,即每次请求之间相互独立,服务器无法直接知晓请求之间的关联。然而,在许多实际场景中,如用户登录、购物车操作等,我们需要在多个请求之间保持状态。这就是session发挥作用的地方。
session可以理解为一个会话对象,它能够在多个请求之间保存和传递一些重要的信息,其中最常用的就是cookies。cookies是服务器发送到用户浏览器并保存在本地的一小段数据,它包含了用户的相关信息,如登录状态、用户偏好等。通过session对象,我们可以自动处理这些cookies,使得下一次请求能够带上前一次请求中服务器设置的cookies,从而实现跨请求的状态保持。
以模拟登录为例,当我们使用用户名和密码登录到一个网站时,服务器会验证我们的身份,并返回一个包含登录状态信息的cookie。如果我们使用普通的请求方式,每次请求都需要重新提供用户名和密码进行验证,这显然是非常繁琐且不现实的。而使用session,我们只需在第一次登录时进行身份验证,之后session会自动保存服务器返回的cookie,并在后续的请求中带上这个cookie,服务器通过验证cookie就能识别我们的身份,从而实现登录状态的保持,让我们能够访问那些需要登录才能访问的页面。
2. 使用 session 发送请求
下面以模拟登录知乎为例,展示如何使用session发送请求实现登录后的页面访问。
首先,我们需要分析知乎的登录过程,获取登录所需的参数和 URL。在登录过程中,知乎会要求我们提供用户名、密码以及一个名为_xsrf的参数,这个参数可以从登录页面的 HTML 源代码中获取。
import requests
import re
def get_xsrf_token(session):
url = 'https://www.zhihu.com'
response = session.get(url)
match_obj = re.search('.*name="_xsrf" value="(.*?)"', response.text)
if match_obj:
return match_obj.group(1)
else:
return ""
def zhihu_login(account, password):
session = requests.Session()
agent = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:54.0) Gecko/20100101 Firefox/54.0"
headers = {
"Host": "www.zhihu.com",
"Referer": "https://www.zhihu.com/",
"Upgrade-Insecure-Requests": "1",
"User-Agent": agent
}
session.headers = headers
_xsrf = get_xsrf_token(session)
post_data = {}
post_url = ""
if re.match("^1\d{10}$", account):
print("phone login")
post_url = "https://www.zhihu.com/login/phone_num"
post_data = {
"_xsrf": _xsrf,
"phone_num": account,
"password": password
}
else:
if "@" in account:
print("email login")
post_url = "https://www.zhihu.com/login/email"
post_data = {
"_xsrf": _xsrf,
"email": account,
"password": password
}
response = session.post(post_url, data=post_data)
print(response.text)
# 登录成功后,访问需要登录才能访问的页面
profile_url = "https://www.zhihu.com/people/your_profile_name"
response = session.get(profile_url)
print(response.text)
if __name__ == "__main__":
account = "your_account"
password = "your_password"
zhihu_login(account, password)
在上述代码中:
通过以上示例,我们可以看到session在模拟登录和保持会话状态方面的强大功能,它极大地简化了我们与需要身份验证的网站进行交互的过程。
https协议是在http协议的基础上,通过添加 SSL/TLS 加密层来实现数据传输的安全性。在https通信中,证书扮演着至关重要的角色。证书是由受信任的数字证书颁发机构(CA,Certificate Authority)颁发的,它包含了服务器的公钥、证书所有者信息、证书有效期、颁发机构签名等内容。
当客户端(如浏览器或使用requests模块的程序)与服务器建立https连接时,会进行以下步骤的证书验证:
证书验证的目的是确保客户端与真正的目标服务器进行通信,防止中间人攻击。中间人攻击是指攻击者在客户端和服务器之间插入自己,截获、篡改或伪造通信数据。通过证书验证,客户端可以验证服务器的身份,保证数据传输的安全性和完整性。
在requests模块中,使用requests.get()等方法发送https请求时,默认会验证服务器的证书。通过verify参数可以控制证书验证的行为。
import requests
url = 'https://self_signed_server.example.com'
response = requests.get(url, verify=False)
print(response.text)
需要注意的是,跳过证书验证会降低通信的安全性,存在被中间人攻击的风险。因此,在生产环境中,应谨慎使用此设置,确保访问的服务器是可信任的。
import requests
url = 'https://custom_cert_server.example.com'
cert_path = 'ca_cert.pem'
response = requests.get(url, verify=cert_path)
print(response.text)
在上述代码中,verify参数被设置为证书文件的路径,requests模块会使用该证书来验证服务器的证书,确保通信的安全性。
代理服务器是位于客户端和目标服务器之间的一台服务器,它的作用是代理网络用户去获取网络信息。形象地说,它就像是网络信息的中转站。当我们设置了代理服务器后,本机不再直接向目标服务器发起请求,而是向代理服务器发出请求。代理服务器接收到请求后,会将请求转发给目标服务器,目标服务器处理请求后将响应返回给代理服务器,最后代理服务器再将响应转发给本机。
在爬虫等场景中,使用代理主要有以下几个原因:
在requests模块中,通过proxies参数来设置代理。以下是设置 HTTP 和 HTTPS 代理的示例:
import requests
url = 'https://www.example.com'
proxies = {
'http': 'http://proxy_ip:proxy_port',
'https': 'https://proxy_ip:proxy_port'
}
response = requests.get(url, proxies=proxies)
print(response.text)
在上述代码中,proxies是一个字典,其中http和https分别表示 HTTP 和 HTTPS 协议的代理地址,proxy_ip和proxy_port分别是代理服务器的 IP 地址和端口号。
如果代理服务器需要用户名和密码进行认证,可以这样设置:
import requests
url = 'https://www.example.com'
proxies = {
'http': 'http://username:password@proxy_ip:proxy_port',
'https': 'https://username:password@proxy_ip:proxy_port'
}
response = requests.get(url, proxies=proxies)
print(response.text)
在实际应用中,为了提高爬虫的稳定性和效率,我们还可以将多个代理 IP 地址放入一个列表中,并在每次请求时随机选择一个代理,以避免单个代理 IP 被频繁使用而导致被封禁。例如:
import requests
import random
url = 'https://www.example.com'
proxy_list = [
'http://proxy1_ip:proxy1_port',
'http://proxy2_ip:proxy2_port',
'http://proxy3_ip:proxy3_port'
]
proxy = {
'http': random.choice(proxy_list),
'https': random.choice(proxy_list)
}
response = requests.get(url, proxies=proxy)
print(response.text)
通过以上设置代理的方法,我们可以灵活地利用代理服务器来满足各种网络请求的需求,提高程序的可用性和安全性。
假设我们要爬取豆瓣电影 Top250 页面(https://movie.douban.com/top250)的电影信息,包括电影名称、评分、评价人数以及电影简介。该页面的结构较为规整,电影信息都包含在div标签且class为item的元素中。每个item元素里,电影名称在span标签且class为title的元素中,评分在span标签且class为rating_num的元素中,评价人数在span标签且class为pl的元素中,电影简介在span标签且class为inq的元素中。我们的目标就是从这个网页中提取出这些信息。
import requests
from bs4 import BeautifulSoup
def crawl_douban_movies():
url = 'https://movie.douban.com/top250'
headers = {
'User - Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
soup = BeautifulSoup(response.text, 'html.parser')
movie_items = soup.find_all('div', class_='item')
for item in movie_items:
movie_name = item.find('span', class_='title').text
rating = item.find('span', class_='rating_num').text
comment_num = item.find('span', class_='pl').text.strip('()')
quote = item.find('span', class_='inq')
quote = quote.text if quote else '无简介'
print(f'电影名称: {movie_name}')
print(f'评分: {rating}')
print(f'评价人数: {comment_num}')
print(f'简介: {quote}')
print('-' * 50)
else:
print(f'请求失败,状态码: {response.status_code}')
if __name__ == "__main__":
crawl_douban_movies()
在上述代码中:
以知乎为例,模拟登录的流程如下:
import requests
from bs4 import BeautifulSoup
import ddddocr
def zhihu_login(account, password):
session = requests.Session()
headers = {
'User - Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
session.headers = headers
# 获取登录页面
login_url = 'https://www.zhihu.com/signin'
response = session.get(login_url)
if response.status_code!= 200:
print(f'获取登录页面失败,状态码: {response.status_code}')
return
soup = BeautifulSoup(response.text, 'html.parser')
_xsrf = soup.find('input', attrs={'name': '_xsrf'})['value']
# 处理验证码
captcha_url = 'https://www.zhihu.com/api/v3/oauth/captcha?lang=cn'
response = session.get(captcha_url)
if response.json()['show_captcha']:
response = session.get(captcha_url, params={'type': 'login'})
with open('captcha.jpg', 'wb') as f:
f.write(response.content)
ocr = ddddocr.DdddOcr()
with open('captcha.jpg', 'rb') as f:
img_bytes = f.read()
captcha = ocr.classification(img_bytes)
else:
captcha = ''
# 发送登录请求
login_data = {
'client_id': 'c3cef7c66a1843f8b3a9e6a1e3160e20',
'grant_type': 'password',
'source': 'com.zhihu.web',
'username': account,
'password': password,
'_xsrf': _xsrf,
'captcha': captcha,
'lang': 'cn',
'ref_source': 'homepage'
}
response = session.post('https://www.zhihu.com/api/v3/oauth/sign_in', data=login_data)
if response.status_code == 200:
print('登录成功')
# 可以在此处进行登录后的操作,如访问需要登录才能访问的页面
profile_url = 'https://www.zhihu.com/people/your_profile_name'
response = session.get(profile_url)
print(response.text)
else:
print(f'登录失败,状态码: {response.status_code},原因: {response.text}')
if __name__ == "__main__":
account = 'your_account'
password = 'your_password'
zhihu_login(account, password)
在 Python 的网络编程领域中,requests模块无疑是一颗璀璨的明星。通过本文的学习,我们深入了解了requests模块的核心知识点和丰富的使用技巧。从最基础的安装与导入,到发送各种类型的 HTTP 请求,如 GET、POST,再到对响应内容的多样化处理,包括获取文本、二进制数据、JSON 数据以及响应状态码等,我们逐步掌握了requests模块的基本操作。
在高级应用方面,requests模块同样展现出了强大的功能。会话维持(session)功能使得我们能够轻松地在多个请求之间保持状态,实现如模拟登录后访问受限页面等操作;证书验证机制确保了在https通信中的安全性,让我们能够放心地与服务器进行数据交互;而设置代理功能则为我们突破网络限制、避免 IP 被封等提供了有力的支持。
通过简单网页爬虫和模拟登录网站这两个实战案例,我们将requests模块的知识应用到了实际项目中,进一步加深了对其的理解和掌握。在网页爬虫案例中,我们利用requests模块获取网页内容,并结合BeautifulSoup库进行数据解析,成功地提取出了所需的信息;在模拟登录网站案例中,我们详细分析了登录流程,通过处理动态参数、验证码等,实现了对知乎等网站的模拟登录,充分展示了requests模块在实际场景中的应用价值。
然而,requests模块的潜力远不止于此。在未来的学习和实践中,读者可以进一步探索其高级用法和优化策略。例如,在处理大量并发请求时,可以研究如何利用requests模块结合多线程、异步编程等技术来提高效率;在与复杂的 API 进行交互时,深入了解如何更好地处理请求头、请求体以及各种响应状态,以确保数据的准确传输和高效处理。同时,随着网络技术的不断发展,requests模块也在持续更新和完善,读者可以关注其官方文档和社区动态,及时掌握新的功能和特性,将其更好地应用到实际项目中。希望大家能够在实际项目中充分发挥requests模块的优势,创造出更多有价值的应用。