1.说明
浏览器会发送请求,服务器也会响应请求,这个过程是可以被playwright介入的,类似于开发框架里的中间件(钩子),比如说我们可以在发送请求前修改请求体活请求头,或者我们不让请求图片以提升速度
2.route
Page对象有有个route()函数,我们可以指定要监控的路由URL规则,然后再指定对应的处理函数就行
例如,我们让每个请求的头部都加上一些值
def handle(route, request):
# override headers
headers = {
**request.headers,
"foo": "foo-value",
"bar": None
}
route.continue_(headers=headers)
page.route("**/*", handle)
再比如说我们要禁用图片发起请求,达到无图模式的目的
page.route("**/*.{png,jpg,jpeg}", lambda route: route.abort())
page.route("**/*", lambda route: route.abort() if route.request.resource_type == "image" else route.continue_())
3.举例
有一个网站,点击一个按钮之后会弹出一个窗口去展示PDF文件,这个过程是由JS源码控制的,但我希望点击下载按钮之后它直接触发下载事件而不是弹出预览窗口。那我就可以监听响应的JS源码并且把它的触发函数给修改了,然后再监听PDF文件的响应头,把“content-disposition”从“inline”改为“attachment”这样它就会直接下载了
changed_download_function = """
function popupPdf()
{
args = popupPdf.arguments;
...
f.submit();
return;
}
"""
def modify_js_function(route: Route) -> None:
print(f"handle_route() url:{
route.request.url}")
response = route.fetch()
headers = response.headers
body = response.body().decode()
body = re.sub("function\s+popupPdf\s*\([^)]*\)\s*\{(?:[^{}]|\{[^{}]*\})*?return;\s*\}", changed_download_function, body)
route.fulfill(
response=response,
body=body,
headers=headers,
)
def modify_response_header(route: Route):
print(f"modify_response_header() url:{
route.request.url}")
response = route.fetch()
headers = response.headers
content_disposition = headers.get("content-disposition", "")
if content_disposition:{
content_disposition}")
headers.update({
"content-disposition": content_disposition.replace("inline", "attachment")})
route.fulfill(
response=response,
body=response.body(),
headers=headers,
)
context.route("**/*eav.enquiry_Search.do", modify_js_function)
context.route("**/*eav.enquiryPopupFor*.do", modify_response_header)