Python入门第11课:Python网络请求入门,使用requests库轻松获取网页数据

Python入门第11课:Python网络请求入门,使用requests库轻松获取网页数据

作者: 蛋皮
标签: Python, requests, 网络请求, HTTP, Web Scraping, API, 数据获取

欢迎回到Python入门系列!在前两节课中,我们学习了面向对象编程 的精髓,并掌握了操作Excel文件 的强大技巧。今天,我们将开启Python在互联网世界的大门------网络请求

想象一下,你的Python程序不仅能处理本地文件,还能主动与全球数以亿计的网站和服务器对话,获取最新的新闻、天气、股票信息,或是调用各种强大的在线服务(API)。这不再是科幻,而是通过Python的requests库可以轻松实现的现实。

requests库被誉为"Python的HTTP库",它以其简洁、优雅的API设计,让发送HTTP请求变得像说话一样简单。无论你是想抓取网页内容、与Web API交互,还是自动化测试,requests都是你的首选工具。


为什么选择 requests

requests出现之前,Python标准库中的urllib也能发送网络请求,但其API相对复杂繁琐。requests库的出现彻底改变了这一局面,它提供了:

  • 简洁的API: 一行代码即可发送GET/POST请求。
  • 人性化的会话 (Sessions): 轻松管理Cookie和持久连接。
  • 自动处理编码: 自动解码响应内容。
  • 强大的功能: 支持文件上传、SSL验证、代理、超时设置、身份验证等。
  • 社区支持: 拥有庞大的用户群和丰富的文档。

一句话:requests让你用最少的代码,做最多的网络交互。


准备工作:安装 requests

在开始之前,请确保已安装requests库。打开命令行(终端),执行:

bash 复制代码
pip install requests

安装完成后,就可以在Python脚本中导入使用了:

python 复制代码
import requests

核心:HTTP请求与响应

在深入requests之前,我们需要了解最基本的网络通信协议------HTTP (HyperText Transfer Protocol)

  • 客户端 (Client): 你的Python程序就是客户端,它向服务器发出请求 (Request)
  • 服务器 (Server): 网站或API的计算机,它接收请求并返回响应 (Response)
  • 请求方法 (HTTP Methods): 最常见的两种:
    • GET: 用于获取资源(如网页内容、API数据)。这是最常用的。
    • POST: 用于向服务器提交数据(如表单提交、上传文件)。
  • 状态码 (Status Code): 服务器在响应中返回一个三位数的状态码,表示请求的结果:
    • 200 OK: 请求成功!
    • 404 Not Found: 请求的资源不存在。
    • 500 Internal Server Error: 服务器内部错误。
    • 403 Forbidden: 禁止访问。
    • 401 Unauthorized: 未授权。

requests库的核心就是发送这些HTTP请求,并处理返回的响应。


发送GET请求:获取网页或API数据

GET请求是最基础、最常用的请求类型。

1. 最简单的GET请求

python 复制代码
import requests

# 发送一个GET请求到指定URL
response = requests.get('https://httpbin.org/get')

# 检查请求是否成功
if response.status_code == 200:
    print("请求成功!")
    # 获取响应的文本内容
    print(response.text)
else:
    print(f"请求失败,状态码: {response.status_code}")

代码解析:

  • requests.get(url): 发送一个GET请求到url,返回一个Response对象。
  • response.status_code: 获取HTTP状态码。
  • response.text: 获取响应的文本内容(字符串形式)。

2. 处理JSON响应 (API常用)

许多API返回的数据格式是JSON。requests可以轻松处理它。

python 复制代码
import requests

# 一个返回JSON的公共测试API
response = requests.get('https://jsonplaceholder.typicode.com/posts/1')

if response.status_code == 200:
    # 直接将响应的JSON内容解析为Python字典
    data = response.json()
    print("获取到的JSON数据:")
    print(data)
    # 现在可以像操作普通字典一样操作data
    print(f"文章标题: {data['title']}")
    print(f"用户ID: {data['userId']}")
else:
    print(f"请求失败: {response.status_code}")

关键点: response.json() 方法会自动将JSON字符串解析成Python的dictlist

3. 添加查询参数 (Query Parameters)

URL中的?后面的部分就是查询参数,常用于搜索、分页等。

python 复制代码
import requests

# 方法1: 手动拼接URL (不推荐,容易出错)
# response = requests.get('https://httpbin.org/get?name=张三&age=25')

# 方法2: 使用 params 参数 (推荐!)
params = {
    'name': '张三',
    'age': 25,
    'city': '北京'
}
response = requests.get('https://httpbin.org/get', params=params)

# 打印最终的URL,看看params是如何被拼接的
print(f"请求的URL: {response.url}")
# 输出: https://httpbin.org/get?name=%E5%BC%A0%E4%B8%89&age=25&city=%E5%8C%97%E4%BA%AC
# (中文被URL编码了)

if response.status_code == 200:
    data = response.json()
    # httpbin.org会把收到的参数回显在响应中
    print("服务器收到的参数:", data['args'])

4. 设置请求头 (Headers)

请求头 (Headers) 包含了关于客户端的额外信息,如浏览器类型、接受的内容类型、身份令牌等。有些网站会检查User-Agent来判断是否是爬虫。

python 复制代码
import requests

url = 'https://httpbin.org/headers'

# 定义自定义请求头
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',
    'Accept': 'application/json',  # 告诉服务器我们希望接收JSON
    'Authorization': 'Bearer your-token-here'  # 如果API需要身份验证
}

response = requests.get(url, headers=headers)

if response.status_code == 200:
    data = response.json()
    print("服务器看到的请求头:")
    print(data['headers'])
    # 会看到我们设置的User-Agent, Accept等
else:
    print(f"请求失败: {response.status_code}")

发送POST请求:提交数据

POST请求用于向服务器发送数据。

1. 提交表单数据 (Form Data)

python 复制代码
import requests

url = 'https://httpbin.org/post'
data = {
    'username': 'alice',
    'password': 'secret123'
}

# 使用 data 参数发送表单数据 (application/x-www-form-urlencoded)
response = requests.post(url, data=data)

if response.status_code == 200:
    result = response.json()
    print("服务器收到的表单数据:")
    print(result['form'])  # httpbin.org会把收到的表单数据放在form字段
else:
    print(f"POST请求失败: {response.status_code}")

2. 发送JSON数据

python 复制代码
import requests

url = 'https://httpbin.org/post'
json_data = {
    'name': 'Bob',
    'email': 'bob@example.com',
    'active': True
}

# 使用 json 参数发送JSON数据 (会自动设置Content-Type为application/json)
response = requests.post(url, json=json_data)  # 注意是 json=json_data

if response.status_code == 200:
    result = response.json()
    print("服务器收到的JSON数据:")
    print(result['json'])  # httpbin.org会把收到的JSON数据放在json字段
else:
    print(f"POST请求失败: {response.status_code}")

3. 上传文件

python 复制代码
import requests

url = 'https://httpbin.org/post'

# 准备要上传的文件
files = {'file': open('example.txt', 'rb')}  # rb: 二进制读取模式

try:
    response = requests.post(url, files=files)
    if response.status_code == 200:
        result = response.json()
        print("文件上传成功!服务器收到的文件信息:")
        print(result['files'])
    else:
        print(f"文件上传失败: {response.status_code}")
finally:
    # 记得关闭文件
    files['file'].close()

实用技巧与高级功能

1. 设置超时 (Timeout)

防止请求因网络问题无限期挂起。

python 复制代码
import requests
from requests.exceptions import Timeout

try:
    # 设置连接超时5秒,读取超时10秒
    response = requests.get('https://httpbin.org/delay/2', timeout=(5, 10))
    print("请求成功:", response.status_code)
except Timeout:
    print("请求超时了!")

2. 使用会话 (Session) 管理状态

当你需要与同一个服务器进行多次交互(如登录后访问其他页面),使用Session对象可以自动管理Cookie,非常方便。

python 复制代码
import requests

# 创建一个会话对象
session = requests.Session()

# 设置会话级别的默认头
session.headers.update({'User-Agent': 'MyApp/1.0'})

# 模拟登录 (假设这个POST请求会返回一个包含登录状态的Cookie)
login_data = {'username': 'user', 'password': 'pass'}
login_response = session.post('https://httpbin.org/post', data=login_data)

# 现在,后续的所有请求都会自动带上登录请求返回的Cookie
# 即使没有显式传递,session也会维护这个会话状态
profile_response = session.get('https://httpbin.org/cookies')
# profile_response会包含之前登录设置的Cookie

# 使用完记得关闭会话
session.close()

3. 处理异常

网络请求可能因各种原因失败(网络断开、DNS错误、超时、服务器错误等)。使用try-except块捕获异常是良好实践。

python 复制代码
import requests
from requests.exceptions import RequestException, ConnectionError, HTTPError

url = 'https://httpbin.org/status/418'  # 这个URL会返回418状态码 (I'm a teapot)

try:
    response = requests.get(url, timeout=5)
    # 检查HTTP错误状态码
    response.raise_for_status()  # 如果状态码>=400,会抛出HTTPError异常
    print("请求成功:", response.text)
except ConnectionError:
    print("连接错误:无法连接到服务器。")
except Timeout:
    print("请求超时。")
except HTTPError as e:
    print(f"HTTP错误: {e}")
except RequestException as e:
    print(f"请求发生未知错误: {e}")

4. 代理 (Proxy)

在某些网络环境下,可能需要通过代理服务器访问外部网络。

python 复制代码
import requests

proxies = {
    'http': 'http://10.10.1.10:3128',
    'https': 'http://10.10.1.10:1080'
}

response = requests.get('https://httpbin.org/get', proxies=proxies)

一个实用的例子:获取天气信息

让我们结合所学,写一个简单的脚本,从一个公共天气API获取城市天气。

python 复制代码
import requests

def get_weather(city):
    """
    从OpenWeatherMap API获取指定城市的天气信息。
    注意:你需要注册获取自己的API密钥 (APPID)。
    这里使用的是一个公共测试密钥,可能有限制。
    """
    # 公共测试密钥 (请勿在生产环境使用,注册获取自己的)
    API_KEY = "45a724b567e3415e93e151307241808"  # 这是一个示例,请替换为有效密钥
    BASE_URL = "http://api.weatherapi.com/v1/current.json"

    params = {
        'key': API_KEY,
        'q': city,
        'lang': 'zh'  # 中文
    }

    try:
        response = requests.get(BASE_URL, params=params, timeout=10)
        response.raise_for_status()  # 检查HTTP错误

        data = response.json()
        current = data['current']
        location = data['location']

        print(f"\n📍 城市: {location['name']}, {location['country']}")
        print(f"🌤 天气: {current['condition']['text']}")
        print(f"🌡 温度: {current['temp_c']}°C (体感 {current['feelslike_c']}°C)")
        print(f"💧 湿度: {current['humidity']}%")
        print(f"🌬 风速: {current['wind_kph']} km/h")

    except requests.exceptions.HTTPError as e:
        if response.status_code == 400:
            print(f"错误:城市 '{city}' 未找到或查询参数无效。")
        else:
            print(f"HTTP错误: {e}")
    except requests.exceptions.RequestException as e:
        print(f"网络请求错误: {e}")
    except KeyError as e:
        print(f"解析数据时出错,缺少关键字段: {e}")
    except Exception as e:
        print(f"发生未知错误: {e}")

# 使用函数
get_weather("Beijing")
get_weather("Shanghai")
get_weather("New York")

注意: 上面的API密钥是示例,实际使用时需要去 WeatherAPI 注册并获取自己的免费密钥。


最佳实践与总结

  1. 总是检查状态码: 在使用响应内容前,务必检查 response.status_code 或使用 response.raise_for_status()
  2. 设置超时: 避免程序因网络问题卡死。
  3. 处理异常: 使用 try-except 捕获网络请求中可能发生的各种异常。
  4. 尊重网站规则: 如果进行网页抓取(Web Scraping),请检查网站的 robots.txt 文件(如 https://example.com/robots.txt)和使用条款,避免过于频繁的请求(设置延迟),不要给服务器造成过大负担。
  5. 使用会话: 对于需要保持登录状态的多步操作,使用 requests.Session()
  6. 安全处理敏感信息: API密钥、密码等敏感信息不要硬编码在代码中,可以使用环境变量或配置文件。
  7. 选择合适的库: requests 适用于同步请求。如果你需要处理成千上万的并发请求,可以考虑 aiohttp (异步) 或 httpx (支持同步和异步)。

总结

通过本课的学习,你已经掌握了使用requests库进行网络请求的核心技能。你学会了:

  • 发送 GETPOST 请求。
  • 处理 JSON 响应和表单数据
  • 设置 请求头查询参数超时
  • 使用 Session 管理会话状态。
  • 正确处理 异常

requests库打开了Python与互联网世界沟通的大门。无论是获取公开数据、调用第三方API,还是进行自动化测试,它都是你不可或缺的工具。

练习建议:

  1. 使用 requests 获取一个你喜欢的新闻网站的首页HTML,尝试用 print(response.text) 查看内容。
  2. 找一个公共API(如GitHub API, JSONPlaceholder),练习发送GET和POST请求。
  3. 修改上面的天气脚本,让它能接受用户输入的城市名。
  4. 尝试使用 Session 模拟一个简单的登录流程(可以使用 httpbin.org 的相关接口测试)。