“会话登录”的核心思想是:在第一次登录成功后,服务器会给你一个“身份凭证”(通常是 Cookie),后续的请求你都需要带上这个凭证,服务器才能认出你是谁,从而保持登录状态。
在 Python 中,我们最常用的工具是 requests 库,因为它能非常方便地处理会话(Session)和 Cookie。
核心概念:Session 对象
requests.Session 对象就像一个浏览器,当你创建一个 Session 对象后,它会在你发起的所有请求之间保持某些参数,
- Cookies:登录后获取的 Cookie 会被自动保存,并在后续的请求中自动发送。
- Headers:你可以为
Session对象设置默认的请求头(如User-Agent),所有通过该Session发起的请求都会带上这些头。
使用 Session 是处理需要登录状态的网站的最佳实践。
简单的表单登录(用户名/密码)
这是最常见的登录方式,我们以一个虚构的网站 http://example.com/login 为例。
步骤:
- 分析登录页面:你需要用浏览器打开登录页面,按
F12打开开发者工具,切换到 "Network"(网络)标签。 - 填写并提交表单:输入用户名和密码,点击登录,你会看到浏览器向服务器发送了一个请求。
- 关键信息:
- Request URL:登录请求的 URL(
http://example.com/login)。 - Request Method:通常是
POST。 - Payload / Form Data:你提交的表单数据,通常包括
username,password等字段。 - Headers:特别是
Content-Type,它告诉服务器你发送的是什么格式的数据(application/x-www-form-urlencoded或application/json)。 - Response:登录成功后,服务器响应中通常会包含 Set-Cookie 头,
Session对象会自动捕获它。
- Request URL:登录请求的 URL(
Python 代码实现:
import requests
# 1. 创建一个 Session 对象
session = requests.Session()
# 2. 准备登录所需的数据(从浏览器开发者工具中获取)
login_url = 'http://example.com/login' # 替换为实际的登录URL
login_data = {
'username': 'your_username', # 替换为你的用户名
'password': 'your_password', # 替换为你的密码
'csrf_token': 'some_csrf_token' # 如果网站有CSRF保护,需要先获取这个token
}
# 3. 设置请求头(模拟浏览器,防止被识别为爬虫)
# User-Agent 可以从浏览器的 Network 请求中复制
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',
'Referer': 'http://example.com/login' # 有些网站需要这个来验证请求来源
}
# 4. 发送登录请求
# Session 对象会自动处理后续的 Cookie
print("正在尝试登录...")
try:
# 使用 session.post() 发送 POST 请求
response = session.post(login_url, data=login_data, headers=headers, timeout=10)
# 检查登录是否成功
# 通常登录成功后,页面会跳转或返回特定的状态码/内容
# 检查响应中是否包含 "欢迎" 或 "login failed" 等关键词
if '登录成功' in response.text or response.status_code == 200:
print("登录成功!")
# 5. 访问需要登录才能看到的页面
# session 对象会自动带上之前获取的 Cookie
protected_page_url = 'http://example.com/profile'
profile_response = session.get(protected_page_url, headers=headers)
print("\n--- 个人主页内容 ---")
# print(profile_response.text) # 打印个人主页的HTML内容
# 你可以从 profile_response.text 中提取你需要的信息
else:
print("登录失败,请检查用户名、密码或请求参数。")
print(f"响应内容: {response.text}")
except requests.exceptions.RequestException as e:
print(f"请求发生错误: {e}")
处理 CSRF 令牌
为了防止跨站请求伪造攻击,很多网站会在登录表单中添加一个 CSRF 令牌,你需要先访问登录页面,获取这个令牌,然后在登录请求中把它一起发回去。
修改后的代码(在场景一的基础上增加获取 CSRF 令牌的步骤):
import requests
import re # 用于正则表达式提取token
session = requests.Session()
login_url = 'http://example.com/login'
profile_url = 'http://example.com/profile'
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'
}
# 1. 先访问登录页面,获取 CSRF token
print("正在访问登录页面以获取 CSRF Token...")
login_page_response = session.get(login_url, headers=headers)
login_page_html = login_page_response.text
# 2. 从页面 HTML 中提取 CSRF token
# 假设 token 在 <input name="csrf_token" value="..."> 中
# 使用正则表达式提取
csrf_token_match = re.search(r'name="csrf_token"\s*value="([^"]+)"', login_page_html)
if csrf_token_match:
csrf_token = csrf_token_match.group(1)
print(f"成功获取 CSRF Token: {csrf_token}")
else:
print("未能找到 CSRF Token,可能网站结构已改变或没有使用CSRF。")
csrf_token = "" # 如果没有token,留空
# 3. 准备登录数据,并加入 CSRF token
login_data = {
'username': 'your_username',
'password': 'your_password',
'csrf_token': csrf_token # 将获取到的token加入数据
}
# 4. 发送登录请求
print("正在尝试登录...")
response = session.post(login_url, data=login_data, headers=headers)
if '登录成功' in response.text:
print("登录成功!")
# 5. 访问受保护页面
profile_response = session.get(profile_url, headers=headers)
print("\n--- 个人主页内容 ---")
# print(profile_response.text)
else:
print("登录失败。")
print(f"响应内容: {response.text}")
处理 JavaScript 渲染的页面(动态加载)
有些网站(尤其是现代单页应用 SPA)的登录表单和内容是通过 JavaScript 动态加载的,requests 无法直接获取这些内容,这种情况下,你需要使用 Selenium 或 Playwright 等自动化测试工具,它们可以模拟真实浏览器行为,执行 JavaScript,并获取最终的页面内容。
使用 Selenium 的基本思路:
- 安装 Selenium 和对应浏览器的 WebDriver(如 ChromeDriver)。
- 启动一个浏览器实例。
- 使用 Selenium 的 API 打开登录页面。
- 找到用户名、密码输入框和登录按钮(通过
id,name,class,xpath等定位)。 - 向输入框中输入用户名密码,并点击登录按钮。
- 等待页面加载完成。
- 获取登录后页面的源代码或数据。
- 关闭浏览器。
Selenium 代码示例(需要先安装 selenium 和 webdriver-manager):
pip install selenium webdriver-manager
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import time
# 1. 设置 WebDriver
# 使用 webdriver-manager 自动管理 driver
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
# 2. 打开登录页面
login_url = 'http://example.com/login' # 替换为使用JS渲染的登录页面
driver.get(login_url)
# 3. 定位元素并输入信息
# 假设输入框的 id 是 'username_field' 和 'password_field'
# 登录按钮的 id 是 'login_button'
try:
username_input = driver.find_element(By.ID, 'username_field')
password_input = driver.find_element(By.ID, 'password_field')
login_button = driver.find_element(By.ID, 'login_button')
username_input.send_keys('your_username')
password_input.send_keys('your_password')
# 4. 点击登录按钮
login_button.click()
# 5. 等待登录完成和页面加载
# 可以加一个显式等待,等待某个元素出现
# time.sleep(5) # 简单的等待,不推荐在生产环境使用
# driver.implicitly_wait(10) # 隐式等待
print("登录成功,正在跳转...")
# 6. 访问需要登录的页面
profile_url = 'http://example.com/profile'
driver.get(profile_url)
# 7. 获取页面源代码或特定数据
page_source = driver.page_source
print("\n--- 个人主页内容 (通过 Selenium 获取) ---")
# print(page_source)
# 提取某个特定元素
# welcome_message = driver.find_element(By.CLASS_NAME, 'welcome-message').text
# print(f"欢迎信息: {welcome_message}")
except Exception as e:
print(f"操作失败: {e}")
finally:
# 8. 关闭浏览器
print("关闭浏览器。")
driver.quit()
总结与最佳实践
| 特性 | requests.Session |
Selenium |
|---|---|---|
| 原理 | 直接发送 HTTP 请求 | 模拟真实浏览器,可执行 JS |
| 速度 | 非常快 | 慢(需要启动浏览器) |
| 适用场景 | 传统网站、API、表单提交 | SPA(单页应用)、需要 JS 渲染的页面、处理复杂验证码 |
| 会话管理 | 自动处理 Cookie | 自动管理 Cookie 和本地存储 |
| 依赖 | requests 库 |
selenium + WebDriver |
| 首选 | 优先使用 | 当 requests 无法解决问题时使用 |
工作流程建议:
- 首先尝试使用
requests.Session,这是最简单、最高效的方式。 - 用浏览器开发者工具(F12)分析登录过程,确定请求 URL、方法、数据格式和必要的头信息。
- 如果遇到 CSRF 令牌,先获取令牌再登录。
- 如果发现
requests获取到的内容不完整或错误(登录后页面内容还是未登录状态),很可能是网站使用了 JavaScript 动态加载,这时,再切换到 Selenium 方案。 - 注意网站的反爬机制:设置合理的
User-Agent、请求间隔 (time.sleep()),使用代理 IP 等,避免被封禁。
