在实际工作里我们可以在Playwright 的无头模式中通过过滤网页响应的资源类型(例如:过滤图片)来阻止图片资源的加载进而提升测试执行效率。通过Playwright 的page.route()
API可以拦截和修改网络请求和响应。它允许你在浏览器页面发送请求时进行干预,从而实现模拟数据、屏蔽资源、修改请求头等功能。
1. 核心概念
-
作用:通过 URL 匹配规则拦截请求,然后对请求或响应进行修改。
-
适用场景:
-
模拟 API 响应(如返回假数据)
-
屏蔽广告或跟踪脚本
-
修改请求头(如添加认证信息)
-
记录网络请求日志
-
加速测试(如阻止加载图片、CSS 等非必要资源)
-
2. 基本语法(Python)
await page.route(url_pattern, handler)
-
参数说明:
-
url_pattern
:匹配请求 URL 的规则,可以是字符串、正则表达式或函数。 -
handler
:处理函数,需接收route
和request
两个参数,并决定如何处理请求。
-
3. 处理函数的关键操作
在 handler
中,必须调用以下方法之一:
a. 继续请求(可修改请求)
await route.continue_( url="https://new-url.com", method="POST", headers={"User-Agent": "Mozilla/5.0"}, post_data=b"binary_data" )
-
continue_
方法(注意下划线,因为continue
是 Python 关键字)
b. 返回自定义响应
await route.fulfill( status=200, content_type="text/html", body="<h1>Mock Response</h1>", headers={"Cache-Control": "no-cache"} )
-
直接返回模拟数据,不发送实际请求。
c. 中止请求
await route.abort() # 默认中止类型为 "failed" # 或指定原因 await route.abort("blockedbyclient")
-
中止类型包括
"aborted"
,"accessdenied"
,"blockedbyclient"
等。
4. Python 示例
示例 1:模拟 API 响应
async def handle_route(route, request): if "/api/user" in request.url: await route.fulfill( status=200, content_type="application/json", body=json.dumps({"id": 1, "name": "Mock User"}) ) else: await route.continue_() await page.route("**/api/**", handle_route)
示例 2:屏蔽图片和 CSS
async def block_resources(route, request):
if request.resource_type in ["image", "stylesheet"]:
await route.abort()
else:
await route.continue_()
await page.route("**/*", block_resources)
示例 3:修改请求头
async def add_auth_header(route, request): headers = request.headers.copy() headers["Authorization"] = "Bearer fake-token" await route.continue_(headers=headers) await page.route("**/api/**", add_auth_header)
5. 高级用法
动态 URL 匹配
使用函数判断复杂条件:
def url_matcher(request): return "tracking" in request.url and request.resource_type == "script" async def block_tracking(route, request): await route.abort() await page.route(url_matcher, block_tracking)
修改响应内容
async def modify_response(route, request): # 先获取原始响应 response = await route.fetch() body = await response.text() modified_body = body.replace("Original Text", "Replaced Text") await route.fulfill(response=response, body=modified_body) await page.route("https://example.com/data.json", modify_response)
取消路由注册
# 注册路由 await page.route("**/ads/**", lambda route, _: route.abort()) # 取消路由 await page.unroute("**/ads/**")
6. 注意事项
-
必须处理请求:每个
handler
必须调用continue_()
,fulfill()
或abort()
,否则请求会被挂起。 -
异步函数:处理函数需定义为
async def
。 -
作用域:路由仅对当前页面生效,页面跳转后需重新注册。
-
性能影响:频繁拦截可能影响测试速度,建议按需使用。
-
匹配顺序:多个路由按注册顺序匹配,第一个匹配的路由会处理请求。
7. 总结
-
核心功能:通过
page.route()
,你可以完全控制网络请求,这在测试和爬虫中非常有用。 -
典型场景:
-
测试前端在不同 API 响应下的行为
-
加速测试(屏蔽非必要资源)
-
调试网络问题(记录请求日志)
-
-
Python 特有细节:
-
使用
continue_()
(带下划线) -
处理函数必须是异步的(
async def
) -
字符串匹配语法与 Python 正则表达式兼容
-
通过灵活使用 page.route()
,你可以创建高度可控的浏览器自动化脚本。