4

有没有办法阻止网站知道它们是否可见?

也许是命令行标志?我在这里检查过,但找不到任何合适的https://peter.sh/experiments/chromium-command-line-switches/

我认为他们使用页面可见性 API:https ://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API

4

2 回答 2

4

页面可见性 API

根据文档Page Visibility API在尝试节省资源和提高性能时会派上用场,方法是让页面在文档不可见时避免执行不必要的任务。

根据页面可见性级别 2 W3C 编辑草案

Page Visibility API 定义了一种以编程方式确定顶级浏览上下文的可见性状态的方法,并在可见性状态发生变化时得到通知。在不知道页面可见性状态的情况下,Web 开发人员一直在设计网页,就好像它们始终可见一样。这不仅会导致更高的机器资源利用率,而且还会阻止 Web 开发人员根据网页是否对用户可见来做出运行时决策。在了解页面可见性状态的情况下设计网页可以改善用户体验和提高网站的能效。

使用此 API,Web 应用程序可以根据用户是否可见来选择更改其行为。例如,当页面不再可见时,此 API 可用于缩减工作。


可见性状态

顶级浏览上下文的 Document 可以处于以下任一可见性状态:

  • hidden:文档在任何屏幕上都不可见。
  • 可见:文档在至少一个屏幕上至少部分可见。

可见性状态通过VisibilityState枚举反映在 API 中,如下所示:

enum VisibilityState {
  "hidden", "visible"
};

扩展

该规范扩展了 Document 接口,如下所示:

partial interface Document {
  readonly attribute boolean hidden;
  readonly attribute VisibilityState visibilityState;
  attribute EventHandler onvisibilitychange;
};

使用示例

为了改善用户体验并优化 CPU 和电源效率,应用程序可以在应用程序可见时自动播放视频,并在应用程序隐藏时自动暂停播放:

const videoElement = document.getElementById("videoElement");

// Autoplay the video if application is visible
if (document.visibilityState === "visible") {
  videoElement.play();
}

// Handle page visibility change events
function handleVisibilityChange() {
  if (document.visibilityState === "hidden") {
    videoElement.pause();
  } else {
    videoElement.play();
  }
}

document.addEventListener('visibilitychange', handleVisibilityChange);

此外,此博客中的@MichaelMahemoff进一步指出,多标签浏览现在是当前的常态,您不能仅仅因为它正在运行而假设用户正在观看您的应用程序,并且新的Page Visibility API可以让您的应用程序发现它是否可见或不是。您可以使用 API 来减少不必要的网络活动和计算。如果您使用的是任何当前的ChromeChromium版本,如果当前页面被隐藏,您可以在控制台中尝试document.webkitHidden。但是,document.webkitVisibilityState将返回一个指示当前状态的字符串,它是visiblehidden和之一prerenderedwebkitvisibilitychange当这些更改中的任何一个发生时,例如当用户打开您的应用程序的选项卡或离开它时,将触发一个新事件。


解决方案

所有这些交互都可以使用visibility.js来观察,它是Page Visibility API的包装器,允许您确定您的网页是对用户可见还是隐藏在后台选项卡或预呈现中。它还允许您在 JavaScript 逻辑中使用页面可见性状态,并通过禁用不必要的计时器和 AJAX 请求来提高浏览器性能,或改善用户界面体验(例如,通过在用户切换到另一个浏览器选项卡时停止视频播放或幻灯片放映)。

Firefox 特定解决方案:另一种 Firefox 特定解决方案是使用 Firefox 的禁用页面可见性 API扩展,该扩展禁用所有页面的 API。

在这里您可以找到有关如何在 geckodriver 中永久安装扩展的详细讨论

Chrome 特定解决方案:另一种特定于 Chrome 的解决方案是使用 Chrome Web Store 中的Don't Make Me Watch扩展程序。

在这里您可以找到有关如何使用 python 在 selenium 的 chrome 驱动程序中加载扩展的详细讨论

于 2019-12-24T11:44:56.907 回答
4

如果您的目标是欺骗可见性 API,则将这段脚本注入相关页面或框架中:

await page.evaluate(`
    Object.defineProperty(window.document,'hidden',{get:function(){return false;},configurable:true});
    Object.defineProperty(window.document,'visibilityState',{get:function(){return 'visible';},configurable:true});
    window.document.dispatchEvent(new Event('visibilitychange'));
`);

它首先覆盖window.hidden以使其返回false。然后,visibilitychange如果页面已经隐藏,它会触发事件以通知文档。

或者在创建文档后立即覆盖 API:

await page.evaluateOnNewDocument(`
    Object.defineProperty(window.document,'hidden',{get:function(){return false;},configurable:true});
    Object.defineProperty(window.document,'visibilityState',{get:function(){return 'visible';},configurable:true});
`);
于 2019-12-24T19:16:28.363 回答