session_page

SessionPage 详解

SessionPage 是 DrissionPage 中的三大页面对象之一,主要基于 requests 库实现,专注于数据包收发、表单提交和数据解析功能。与浏览器模式相比,SessionPage 具有启动快、资源占用少的优势,适合批量数据采集、接口测试等场景。

SessionPage 概述

特点与优势

  • 轻量级:无需启动浏览器,资源消耗小
  • 高效:收发数据包速度快,适合大规模数据获取
  • 低调:不易被网站检测为爬虫(相比浏览器)
  • 简洁:API 设计与 ChromiumPage 保持一致,易于使用

适用场景

  • 数据爬取和采集
  • API 接口测试
  • 简单表单提交
  • 无需渲染 JavaScript 的网页操作

创建 SessionPage 对象

基本创建方式

from DrissionPage import SessionPage

# 创建默认 SessionPage 对象
page = SessionPage()

使用配置文件创建

# 使用指定配置文件创建
page = SessionPage(crx_or_path='config.ini')

# 或者从默认位置读取配置
page = SessionPage(read_file=True)

自定义会话参数

# 自定义创建,可设置代理等参数
page = SessionPage(proxy='http://127.0.0.1:7890', timeout=10)

# 使用更多自定义参数
page = SessionPage(
    proxy='http://127.0.0.1:7890', 
    timeout=10,
    headers={'User-Agent': 'Custom User Agent'},
    cookies={'session_id': '123456'}
)

页面请求与导航

打开网页

# 使用 get 方法打开网页
page.get('https://www.example.com')

# 设置超时时间
page.get('https://www.example.com', timeout=10)

# 添加查询参数
page.get('https://www.example.com/search', params={'q': 'python'})

发送 POST 请求

# 基本 POST 请求
page.post('https://api.example.com/submit', data={'key': 'value'})

# 发送 JSON 数据
page.post('https://api.example.com/submit', json={'key': 'value'})

# 上传文件
page.post('https://api.example.com/upload', 
          files={'file': open('example.txt', 'rb')})

其他 HTTP 方法

# PUT 请求
page.put('https://api.example.com/update', data={'key': 'new_value'})

# DELETE 请求
page.delete('https://api.example.com/remove/123')

# 自定义请求
page.request('PATCH', 'https://api.example.com/patch', 
             json={'field': 'value'})

处理响应数据

获取页面内容

# 获取 HTML 文本
html = page.html

# 获取 JSON 响应
json_data = page.json

# 获取二进制内容
binary_data = page.content

获取响应信息

# 获取响应状态码
status_code = page.status_code
print(f'状态码: {status_code}')

# 获取响应头信息
headers = page.response_headers
print(f'Content-Type: {headers.get("Content-Type")}')

# 获取请求 URL
url = page.url
print(f'当前 URL: {url}')

会话管理

Cookies 操作

# 获取当前所有 cookies
cookies = page.cookies
print(cookies)

# 获取特定 cookie
session_id = page.get_cookie('session_id')
print(f'Session ID: {session_id}')

# 设置 cookie
page.set_cookies({'user_id': '12345'})

# 保存 cookies 到文件
page.save_cookies('cookies.json')

# 从文件加载 cookies
page.load_cookies('cookies.json')

请求头管理

# 获取当前请求头
headers = page.headers
print(headers)

# 设置新的请求头
page.set_headers({'User-Agent': 'Mozilla/5.0 ...'})

# 添加单个请求头
page.add_headers({'Referer': 'https://www.example.com'})

元素查找与操作

SessionPage 也支持类似于浏览器模式的元素查找和操作功能,但基于静态 HTML 解析。

元素查找

# 通过 CSS 选择器查找元素
element = page.ele('#main-content')

# 通过 XPath 查找元素
element = page.ele('xpath://div[@class="article"]')

# 通过文本查找元素
element = page.ele('@text=登录')

# 查找所有匹配元素
elements = page.eles('.item')

元素信息获取

# 获取元素文本
text = element.text
print(f'元素文本: {text}')

# 获取属性值
href = element.attr('href')
print(f'链接地址: {href}')

# 获取 HTML
html = element.html
print(f'元素 HTML: {html}')

表单操作

虽然 SessionPage 不能像浏览器一样实时交互,但可以通过解析和构建表单数据实现表单提交。

# 找到表单元素
form = page.ele('form#login')

# 获取表单字段
form_data = {}
for input_ele in form.eles('input'):
    name = input_ele.attr('name')
    if name:
        form_data[name] = input_ele.attr('value') or ''

# 更新表单数据
form_data['username'] = 'user123'
form_data['password'] = 'pass123'

# 获取表单提交地址
action = form.attr('action') or page.url
method = form.attr('method') or 'post'

# 提交表单
if method.lower() == 'post':
    page.post(action, data=form_data)
else:
    page.get(action, params=form_data)

高级功能

会话克隆与共享

# 克隆当前会话创建新页面
new_page = page.clone()

# 使用相同会话创建新页面(共享cookies等状态)
same_session_page = SessionPage(session=page.session)

设置代理

# 设置 HTTP 代理
page.set.proxy('http://127.0.0.1:7890')

# 设置 SOCKS 代理
page.set.proxy('socks5://127.0.0.1:1080')

# 移除代理
page.set.proxy(None)

处理重定向

# 允许自动重定向(默认)
page.get('https://example.com/redirect', allow_redirects=True)

# 禁止自动重定向
page.get('https://example.com/redirect', allow_redirects=False)

# 获取重定向历史
history = page.history
for resp in history:
    print(f'重定向: {resp.url} -> {resp.status_code}')

会话重连

# 重新创建会话(保留cookies等信息)
page.reconnect()

# 完全重置会话(包括cookies)
page.reset()

SessionPage vs. ChromiumPage

两种模式有各自的优缺点,下面是简单对比:

特性 SessionPage ChromiumPage
启动速度
资源占用
JavaScript执行 不支持 支持
元素交互 基础支持 完全支持
反爬能力 较弱 较强
数据处理速度
适用场景 数据抓取、接口测试 复杂网页交互、自动化测试

实用技巧

处理 AJAX 数据

对于需要 JavaScript 加载的数据,可以直接请求接口:

# 先访问页面
page.get('https://example.com/products')

# 分析后找到 AJAX 接口地址
api_url = 'https://example.com/api/products'

# 构建请求参数
params = {
    'page': 1,
    'size': 20,
    'sort': 'popular'
}

# 提取必要的认证信息(如果有)
token = page.ele('meta[name="csrf-token"]').attr('content')

# 设置必要的头信息
page.add_headers({
    'X-Requested-With': 'XMLHttpRequest',
    'Referer': page.url,
    'X-CSRF-Token': token
})

# 发送 API 请求获取数据
page.get(api_url, params=params)
data = page.json
print(f'获取到{len(data["items"])}个产品')

处理防盗链

处理图片等资源的防盗链保护:

# 访问页面
page.get('https://example.com/gallery')

# 设置 Referer 头以通过防盗链检查
img_url = 'https://example.com/images/protected.jpg'
page.add_headers({'Referer': 'https://example.com/gallery'})

# 下载图片
page.get(img_url)
with open('image.jpg', 'wb') as f:
    f.write(page.content)

批量并行请求

使用多个 SessionPage 实例可以实现并行请求:

import concurrent.futures

urls = [f'https://api.example.com/items/{i}' for i in range(1, 101)]
results = []

def fetch_url(url):
    page = SessionPage()
    page.get(url)
    return page.json

# 使用线程池并行请求
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
    results = list(executor.map(fetch_url, urls))

print(f'获取了 {len(results)} 条数据')

小结

SessionPage 提供了高效、轻量级的网页操作方式,特别适合批量数据采集和接口测试场景。它与 ChromiumPage 共享相似的 API 设计,使得在两种模式之间切换变得简单。通过合理利用 SessionPage 的特性,可以显著提升自动化脚本的性能和效率。

在下一章中,我们将详细介绍 ChromiumPage 的高级功能,展示如何在需要完整浏览器环境的场景下进行自动化操作。

使用 Hugo 构建
主题 StackJimmy 设计