如何在Selenium中禁用window.location赋值以阻止客户端随机重定向?
如何在Selenium中禁用window.location赋值以阻止客户端随机重定向?
我之前爬取网站时也碰到过这个非常头疼的随机跳转问题!你说的没错,直接重定义window.location确实行不通,因为它的configurable属性是false,没法直接修改它的属性描述符。不过有几个实战验证有效的办法,能帮你拦截这些跳转:
方法一:重写location的核心跳转方法(最简便)
当页面执行window.location = "跳转地址"时,浏览器内部其实会调用location.assign("跳转地址")。所以我们只需要在页面脚本加载前,重写location.assign和location.replace这两个方法,就能拦截绝大多数客户端跳转。
步骤:
- 在Selenium中通过Chrome DevTools Protocol(CDP)的
Page.addScriptToEvaluateOnNewDocument注入拦截脚本,这个方法能保证脚本在页面所有JS之前执行。 - 重写跳转方法,可选保留调试日志或添加白名单逻辑。
以Python为例,代码如下:
from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager # 初始化Chrome浏览器 options = webdriver.ChromeOptions() driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options) # 通过CDP注入前置脚本 driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', { 'source': ''' // 可选:保存原始方法,方便后续调试或放行特定跳转 const originalAssign = window.location.assign; const originalReplace = window.location.replace; // 拦截assign跳转 window.location.assign = function(url) { console.log('拦截到assign跳转请求:', url); // 示例:放行指定域名的跳转 // if (url.startsWith('https://your-allowed-domain.com')) { // originalAssign.call(this, url); // } }; // 拦截replace跳转 window.location.replace = function(url) { console.log('拦截到replace跳转请求:', url); }; ''' }) # 访问目标页面 driver.get('https://target-website.com')
这个方法的优点是简单可靠,不会触发任何属性重定义的异常,因为我们只是重写了location对象上的可写方法。
方法二:用Proxy代理拦截所有location操作(更彻底)
如果网站还会通过直接修改location.href、location.pathname等属性触发跳转,上面的方法可能不够用。这时候可以用Proxy代理location对象,拦截所有属性的读写和方法调用:
注入的脚本如下(同样通过Page.addScriptToEvaluateOnNewDocument注入):
// 创建location的代理对象,拦截所有操作 const proxiedLocation = new Proxy(window.location, { set(loc, propName, value) { // 拦截所有可能触发跳转的属性赋值 const blockedProps = ['href', 'pathname', 'search', 'hash', 'host', 'hostname', 'port', 'protocol']; if (blockedProps.includes(propName)) { console.log(`拦截修改location.${propName}的请求,目标值:`, value); return true; // 返回true避免页面脚本抛出赋值失败的异常 } // 允许修改其他无关属性 return Reflect.set(loc, propName, value); }, get(loc, propName) { // 拦截跳转相关方法 if (typeof loc[propName] === 'function' && ['assign', 'replace', 'reload'].includes(propName)) { return function(...args) { console.log(`拦截调用location.${propName}的请求,参数:`, args); }; } // 返回原始属性/方法 return Reflect.get(loc, propName); } }); // 拦截对window.location的直接赋值和访问 Object.defineProperty(window, 'location', { get() { return proxiedLocation; }, set(value) { console.log(`拦截直接赋值window.location的请求,目标值:`, value); }, configurable: true });
注意:部分浏览器环境下,修改
window.location的属性描述符可能依然报错,这时候可以退而求其次,只代理location的关键方法和属性,或者结合方法一使用。
额外提示
- 如果你需要调试跳转拦截情况,可以通过
driver.get_log('browser')获取浏览器控制台的日志,方便排查问题。 - 如果网站使用了更隐蔽的跳转方式(比如
history.pushState),你还需要重写history对象的相关方法,思路和上面一致。
内容来源于stack exchange
相关产品推荐
相关产品推荐

