playwright中的请求或响应拦截
通过路由功能可以实现请求或响应拦截
设置路由
页面路由:page.route(url,handler)
浏览器上下文路由:browser_context.route(url,handler)
页面路由优先级高于浏览器上下文路由
当有多个路由匹配同一个请求时,将按照与注册相反的顺序运行,即后注册的路由优先级更高
正常情况下,一次请求只会匹配一个路由,如果某个路由处理了请求,则不会再匹配其他路由,除非该路由调用了 route.fallback()方法
参数 url表示需要拦截的请求完整url
可以为字符串,验证请求的URL是为指定字符串,区分大小写 page.route("https://www.qingheluo.com/", handler) 可以包含星号(*)通配符,匹配任意数量的非斜杠(/)字符 page.route("*//*/", handler) 星号不能包含斜杠,否则无法匹配 可以为一个正则表达式,验证请求URL是否符合正则表达式规则 page.route(re.compile(r".*/images/.*\.png$"), handler)
参数 handler表示拦截请求的处理函数
函数接受两个参数:Route,Request Route表示当前被拦截的路由对象。通过这个对象,可以继续请求、中止请求、修改请求参数等,或者创建并返回一个新的响应 Request表示当前被拦截的请求对象。通过这个对象,可以获取请求的URL、方法、头部信息、查询参数、请求体等信息 参数可以从右向左省略 当处理函数未执行中止、继续、回退或返回响应操作时,网络访问流程会一直处于暂停状态
Request 请求对象为一个只读对象,不能修改请求参数,如果需要修改请求参数,需要通过 Route.request 来修改
Route 路由对象可以控制请求的中止、继续、修改请求参数、修改相应内容等
中止请求:route.abort(error_code='aborted')
调用该方法后,将返回一个响应 响应内容为**关键字参数error_code**指定的错误码 请求将被中止,不会再执行后续的路由处理 error_code默认为'aborted',可选值 'aborted' 操作中止(由于用户操作) 'accessdenied' 访问网络以外的资源的权限被拒绝 'addressunreachable'无法到达目标IP地址 'blockedbyclient' 客户端选择阻止请求 'blockedbyresponse' 请求失败,因为响应与未满足的要求一起提供 'connectionaborted' 由于未收到已发送数据的ACK而导致连接超时 'connectionclosed' 连接已关闭(对应于TCP FIN) 'connectionfailed' 连接尝试失败 'connectionrefused' 连接尝试被拒绝 'connectionreset' 连接已重置(对应于TCP连接) 'internetdisconnected' Internet连接已丢失 'namenotresolved' 无法解析主机名 'timedout' 操作超时 'failed' 未知错误
继续请求:route.continue\_(**kwargs)
调用该方法后,将按照正常流程继续执行后续的请求处理,而不是直接返回响应 关键字参数用于修改后续请求参数 可用关键字参数: method:str,修改请求的方法 headers:dict,修改请求的头信息 post_data:str|dict,修改请求的请求体 str格式为:key1=val1&key2=val2,并且需要设置Content-Type为application/x-www-form-urlencoded 如果为dict会被序列化为json字符串 url: str,修改请求的URL 返回新url请求的响应,但是浏览器地址栏不会更新,仍然是原始url 新URL必须与原始URL具有相同的协议 当修改headers时,当我们仅需修改某个头部或增加某些头部时,可以 headers = { **request.headers, # 保留原有头部信息 "foo": "foo-value", # 重新设置foo的值,如果有则覆盖,没有则新增 "bar": None # 删除bar的值 } route.continue_(headers=headers)
路由回退:route.fallback(**kwargs)
调用该方法后,会将请求交给下一个路由处理 可用的关键字参数和 continue_ 相同,有一点需要注意,当修改了请求的 URL 时,下一个路由会使用修改后的URL进行匹配 后面处理的修改会覆盖前面相同项目的修改
route.continue_() 和 route.fallback()的区别
正常情况下,当某个路由处理了请求,则不会再匹配其他路由 fallback()会将请求处理权传递给下一个匹配的路由处理器,如果没有匹配的路由,则会按照其正常的网络流程进行 continue_()是让请求继续按照其正常的网络流程进行,但并不会将请求处理权交给下一个路由处理器
执行请求:route.fetch(**kwargs)
按照关键字参数指定的请求参数,发送请求并返回响应对象Response
headers :dict max_redirects : int,最大重定向次数,默认20,超过将引发错误 method : str post_data:str|dict timeout:float,请求超时时间,默认30000(30秒) url :str
返回响应:route.fulfill(**kwargs)
使用指定的参数创建一个新的响应对象并返回,不再执行后续的处理
response :使用Response对象作为响应返回给客户端 一般由route.fetch()方法获取 其他参数会覆盖Response对象中的相关对应属性 status :int,响应状态码,默认200 headers :dict,响应头部信息 body :str|bytes,响应内容 json :dict,响应内容解析为json对象,如果没有设置Content-Type,会自动设置值为application/json path :str,本地文件路径,用于返回本地文件内容,Content-Type将从文件扩展名推断
修改返回内容示例
修改响应头部信息 res = route.fetch() route.fulfill(response=res, headers={**res.headers,"foo": "bar"}) 修改正文内容 res = route.fetch() route.fulfill(response=res, body=res.text().replace('old', 'new'))
删除路由
page.unroute(url,handler):未指定 handler 则删除 url 的所有路由
browser_context.unroute(url,handler):未指定 handler 则删除 url 的所有路由
page.unroute_all(behavior='default')
browser_context.unroute_all(behavior='default')
behavior可选值 'default' 不等待当前处理程序调用(如果有)完成,正常抛出未处理的错误 'wait' 等待当前处理程序调用(如果有)完成 'ignoreErrors' 不等待当前的处理程序调用(如果有)完成,静默捕获未处理的错误