1. 程式人生 > >反爬蟲中chrome無頭瀏覽器的幾種檢測與繞過方式

反爬蟲中chrome無頭瀏覽器的幾種檢測與繞過方式

chrome無頭瀏覽器的幾種檢測方式

本文測試使用的chrome版本為 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3514.2 Safari/537.36

1.UserAgent檢測

無頭模式下的UA會帶有HeadlessChrome關鍵字

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/70.0.3521
.2 Safari/537.36

因此可以檢查UA中的關鍵字

if (/HeadlessChrome/.test(navigator.userAgent)) {
  // headless...
}

2.Webdriver檢測

無頭模式下navigator.webdriver為true,因此可以進行如下檢測。

// Webdriver Test
if (navigator.webdriver) {
  // headless...
}

為了繞過這個檢測,重新設定該屬性即可。

Object.defineProperty(navigator, 'webdriver', {
    get
: () => false, });

3.chrome屬性檢測

在無頭模式下window.chrome屬性是undefined,而在正常有介面模式下,定義如下。

csi: ƒ ()
embeddedSearch: {searchBox: {…}, newTabPage: {…}}
loadTimes: ƒ ()
app: (...)
runtime: (...)
webstore: (...)
get app: ƒ nativeGetter()
set app: ƒ nativeSetter()
get runtime: ƒ nativeGetter()
set runtime: ƒ nativeSetter()
get webstore: ƒ nativeGetter()
set webstore: ƒ nativeSetter(

因此可以進行如下形式檢測

if (!window.chrome || !window.chrome.runtime) {
  // headless...
}

繞過檢測修改屬性即可

 window.navigator.chrome = {
    runtime: {},
    // etc.
  };

4.Permissions檢測

(async () => {
  const permissionStatus = await navigator.permissions.query({ name: 'notifications' });
  if(Notification.permission === 'denied' && permissionStatus.state === 'prompt') {
    // headless
  }
})();

無頭模式下Notification.permission與navigator.permissions.query會返回相反的值。
因此繞過的方式如下。

// Pass the Permissions Test.
await page.evaluateOnNewDocument(() => {
  const originalQuery = window.navigator.permissions.query;
  return window.navigator.permissions.query = (parameters) => (
    parameters.name === 'notifications' ?
      Promise.resolve({ state: Notification.permission }) :
      originalQuery(parameters)
  );
});

5. Plugins長度檢測

無頭模式下navigator.plugins.length返回0

if (navigator.plugins.length === 0) {
  // headless
}

繞過方式如下

Object.defineProperty(navigator, 'plugins', {
    get: () => [1, 2, 3, 4, 5],
  });

6.The Languages檢測

navigator.languages檢測方法

if (!navigator.languages || navigator.languages.length === 0) {
  // headless
}

繞過方法

  Object.defineProperty(navigator, 'languages', {
    get: () => ['en-US', 'en'],
  });

7.原文地址