puppeteer - 操做支付寶報「操做頻繁」錯誤的思考

我這裏想要實現的是經過轉帳到支付寶的方式判斷一個手機號是否註冊過支付寶。但查詢收款人的網絡請求很複雜分析不出來,使用 puppteer 也是沒有解決 「操做頻繁」 的問題(應該還有不少其餘的判斷我沒有考慮到),這裏只是整理記錄一下。html

問題分析

轉帳時查詢用戶是否存在會報 「操做頻繁」web

alipay-operating-frequency

感受可能檢查了無頭瀏覽器,但在 JS 裏沒有搜索到webdrive。而後經過內存快照找找發現真有webdrive。。(雖然不能百分百肯定無頭瀏覽器,但以後進行了一些欺騙確實有點做用)chrome

alipay-find-webdrive-in-memory

嘗試解決

用根據 It is not possible to detect and block Chrome headless 進行欺騙:(加了一條頁面是否隱藏,感受這個也可能會檢測)瀏覽器

// We'll use Puppeteer is our browser automation framework.
const puppeteer = require('puppeteer');

// This is where we'll put the code to get around the tests.
const preparePageForTests = async (page) => {
  // Pass the User-Agent Test.
  const userAgent = 'Mozilla/5.0 (X11; Linux x86_64)' +
    'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.39 Safari/537.36';
  await page.setUserAgent(userAgent);

  // Pass the Webdriver Test.
  await page.evaluateOnNewDocument(() => {
    Object.defineProperty(navigator, 'webdriver', {
      get: () => false,
    });
  });

  // Pass the Chrome Test.
  await page.evaluateOnNewDocument(() => {
    // We can mock this in as much depth as we need for the test.
    window.navigator.chrome = {
      runtime: {},
      // etc.
    };
  });

  // 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)
    );
  });

  // Pass the Plugins Length Test.
  await page.evaluateOnNewDocument(() => {
    // Overwrite the `plugins` property to use a custom getter.
    Object.defineProperty(navigator, 'plugins', {
      // This just needs to have `length > 0` for the current test,
      // but we could mock the plugins too if necessary.
      get: () => [1, 2, 3, 4, 5],
    });
  });

  // Pass the Languages Test.
  await page.evaluateOnNewDocument(() => {
    // Overwrite the `plugins` property to use a custom getter.
    Object.defineProperty(navigator, 'languages', {
      get: () => ['zh-CN', 'zh', 'en'],
    });
  });
    
  // 可能會檢測頁面是否隱藏,處理一下
  await page.evaluateOnNewDocument(() => {
    // Overwrite the `hidden` property
    Object.defineProperty(document, "hidden", {
      get: () => false
    });
    Object.defineProperty(document, "webkitHidden", {
      get: () => false
    });
  });
}

(async () => {
  // Launch the browser in headless mode and set up a page.
  const browser = await puppeteer.launch({
    args: ['--no-sandbox'],
    headless: true,
  });
  const page = await browser.newPage();

  // Prepare for the tests (not yet implemented).
  await preparePageForTests(page);

  // Navigate to the page that will perform the tests.
  const testUrl = 'https://intoli.com/blog/' +
    'not-possible-to-block-chrome-headless/chrome-headless-test.html';
  await page.goto(testUrl);

  // Save a screenshot of the results.
  await page.screenshot({path: 'headless-test-result.png'});

  // Clean up.
  await browser.close()
})();

其餘博客有說用下面這種方式去掉webdriver,但我測試很差使:網絡

const browser = await puppeteer.launch({ignoreDefaultArgs: ["--enable-automation"]});

PS:到這裏問題沒有徹底解決,查詢一兩次就頻繁了。最後使用 appium 操做支付寶的 APP 實現的(這種方式也有問題,由於用戶能夠設置不讓經過手機號查找)。。app

拓展

有興趣的能夠看看 Chrome 添加該屬性的原因:https://groups.google.com/a/chromium.org/forum/#!msg/blink-dev/6GysDZCWwB8/rXbGoRohBgAJless

能夠根據ChromeStatus得知該屬性添加的版本爲 63,但這屬性須要到在 puppeteer v0.12.0(對應 chromium 版本爲 64.0.3240.0 (r508693))中才開始有效,在 v0.11.0(63.0.3205.0 (r499413)) 中還未生效。async

參見:puppeteer 的 PDD 反爬經歷 - xzysaber - 博客園測試

經過內存快照能夠找到任何混淆過的字符串麼?

並不能,必須待查找的內存沒有釋放(還有指向這個字符串的引用)才能找到。例如:ui

檢測不到:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <script>
      (function test() {
        var fun_a = "\167\145\142\144\162\151\166\145\162";
      })();

      ("\167\145\142\144\162\151\166\145\162");

      var a = navigator["\167\145\142\144\162\151\166\145\162"];
      console.log(a);

      var window.b = "\167\145\142\144\162\151\166\145\162";
      delete window.b;
    </script>
  </body>
</html>

能夠檢測到:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <script>
      var a = "\167\145\142\144\162\151\166\145\162";

      function test() {
        var fun_a = "\167\145\142\144\162\151\166\145\162";
        return navigator[fun_a];
      }
      var b = test();

      //> [...'webdriver'].map((d, i)=>String.fromCharCode(d.charCodeAt(0) + 1)).join('')
      //'xfcesjwfs'
      var other_1 = [..."xfcesjwfs"]
        .map((d, i) => String.fromCharCode(d.charCodeAt(0) - 1))
        .join("");
    </script>
  </body>
</html>
相關文章
相關標籤/搜索