Anti-Bot 机制识别与绕过:如何检测浏览器指纹、行为分析、JS 环境检测和蜜罐,并设计规避策略?

各位老铁,晚上好!今天咱们聊点刺激的,说说怎么跟那些神烦的 Anti-Bot 机制斗智斗勇。记住,咱们的目标不是教唆大家干坏事,而是为了更好地理解这些机制,保护自己的爬虫,也保护自己的数据。

开场白:别把爬虫当小强,要当绅士!

很多网站都装了 Anti-Bot 机制,目的很简单:防止恶意爬虫薅羊毛,影响正常用户体验。咱们写爬虫,不能像个愣头青,横冲直撞,搞得人家服务器瘫痪。要像个绅士,礼貌地请求,合理地抓取。当然,必要的伪装也是必不可少的。

第一节:浏览器指纹识别——你是谁?从哪来?要到哪去?

想象一下,你走进一家酒吧,老板一眼就能看出你是新来的。为什么?因为你的穿着、谈吐、行为都跟老顾客不一样。浏览器指纹识别就是这个道理。网站通过各种信息,给你的浏览器打上一个独特的“指纹”,用来判断你是不是一个正常的浏览器。

  • 常见的指纹信息:

    信息 说明
    User-Agent 声明浏览器及操作系统信息,容易伪造,但很重要。
    Platform 操作系统平台,比如 Win32Linux x86_64
    Plugins 安装的浏览器插件列表,比如 Flash、Java。
    Fonts 系统安装的字体列表,不同的操作系统、浏览器,字体列表可能不一样。
    WebGL WebGL 渲染器信息,包括渲染器名称、厂商、版本等。
    AudioContext AudioContext 的指纹,通过 Web Audio API 生成,不同的硬件和软件环境,生成的指纹可能不一样。
    Canvas Canvas 指纹,通过 Canvas API 绘制文本或图形,然后获取图像数据的哈希值。不同的操作系统、浏览器、字体,绘制出来的图像可能不一样。
    Timezone 时区信息。
    Screen Size 屏幕分辨率。
  • 检测方式:

    网站通常会用 JavaScript 代码来收集这些信息,然后进行分析和判断。

  • 绕过策略:

    1. User-Agent 伪造: 这是最基本的,但也是最有效的。

      import requests
      import random
      
      user_agents = [
          'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
          'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Safari/605.1.15',
          'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0',
          'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:89.0) Gecko/20100101 Firefox/89.0',
      ]
      
      def get_random_user_agent():
          return random.choice(user_agents)
      
      headers = {
          'User-Agent': get_random_user_agent()
      }
      
      response = requests.get('https://www.example.com', headers=headers) # 替换成目标网址
      print(response.status_code)
    2. Headless Chrome 模拟: 使用 Puppeteer 或 Selenium 这样的工具,可以模拟真实的浏览器环境,包括各种指纹信息。

      const puppeteer = require('puppeteer');
      
      (async () => {
          const browser = await puppeteer.launch({
              headless: false, // 是否以无头模式运行
              args: [
                  '--disable-web-security', // 禁用 web 安全策略,避免跨域问题
                  '--disable-features=IsolateOrigins', // 禁用隔离源,避免一些指纹检测
                  '--lang=zh-CN,zh;q=0.9,en;q=0.8', // 设置语言
              ],
          });
          const page = await browser.newPage();
      
          // 设置 User-Agent
          await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36');
      
          // 模拟视窗大小
          await page.setViewport({ width: 1920, height: 1080 });
      
          await page.goto('https://www.example.com'); // 替换成目标网址
      
          // 模拟鼠标移动
          await page.mouse.move(100, 100);
      
          // 模拟点击
          await page.click('a');
      
          await page.waitForTimeout(5000); // 等待 5 秒
      
          await browser.close();
      })();
    3. 指纹随机化: 可以修改 Headless Chrome 的启动参数,或者使用一些第三方库,来随机化一些指纹信息,比如 WebGL、Canvas。

      // 使用 puppeteer-extra 和 puppeteer-extra-plugin-stealth 来隐藏指纹
      const puppeteer = require('puppeteer-extra');
      const StealthPlugin = require('puppeteer-extra-plugin-stealth');
      puppeteer.use(StealthPlugin());
      
      (async () => {
          const browser = await puppeteer.launch({ headless: false });
          const page = await browser.newPage();
          await page.goto('https://www.example.com'); // 替换成目标网址
          await page.waitForTimeout(5000);
          await browser.close();
      })();
    4. 使用真实浏览器: 这是最靠谱的方法,但成本也最高。可以使用一些云服务,比如 Browserless、HeadlessChrome.dev,它们提供了真实的浏览器环境,可以有效避免指纹识别。

第二节:行为分析——你的小动作,我都知道!

光有好的皮囊还不够,还要有像人一样的行为。网站可以通过分析你的鼠标移动、点击、键盘输入等行为,来判断你是不是一个机器人。

  • 常见的行为分析:

    行为 说明
    鼠标移动轨迹 真实的用户的鼠标移动轨迹通常是不规则的,而机器人的鼠标移动轨迹往往是直线或者规则的曲线。
    点击行为 真实的用户的点击行为通常是有目的性的,而机器人的点击行为可能是随机的或者有规律的。
    键盘输入 真实的用户的键盘输入通常是有意义的,而机器人的键盘输入可能是随机的或者无意义的。
    页面停留时间 真实的用户的页面停留时间通常是根据内容决定的,而机器人的页面停留时间可能是固定的。
    页面滚动 真实的用户的页面滚动通常是根据内容决定的,而机器人的页面滚动可能是固定的或者无规律的。
  • 检测方式:

    网站通常会用 JavaScript 代码来监听用户的行为,然后进行分析和判断。

  • 绕过策略:

    1. 模拟鼠标移动: 使用 Puppeteer 或 Selenium,可以模拟真实的鼠标移动轨迹。

      const puppeteer = require('puppeteer');
      
      // 模拟鼠标移动轨迹
      async function simulateMouseMove(page, startX, startY, endX, endY, steps = 20) {
          const deltaX = (endX - startX) / steps;
          const deltaY = (endY - startY) / steps;
      
          for (let i = 0; i < steps; i++) {
              const currentX = startX + deltaX * i;
              const currentY = startY + deltaY * i;
              await page.mouse.move(currentX, currentY);
              await page.waitForTimeout(Math.random() * 20 + 10); // 增加随机延迟
          }
          await page.mouse.move(endX, endY);
      }
      
      (async () => {
          const browser = await puppeteer.launch({ headless: false });
          const page = await browser.newPage();
          await page.setViewport({ width: 1920, height: 1080 });
          await page.goto('https://www.example.com'); // 替换成目标网址
      
          // 获取元素的位置
          const element = await page.$('a'); // 替换成目标元素的选择器
          const boundingBox = await element.boundingBox();
          const centerX = boundingBox.x + boundingBox.width / 2;
          const centerY = boundingBox.y + boundingBox.height / 2;
      
          // 模拟鼠标移动到元素中心
          await simulateMouseMove(page, 100, 100, centerX, centerY);
      
          // 模拟点击
          await page.click('a');
      
          await page.waitForTimeout(5000);
          await browser.close();
      })();
    2. 模拟点击行为: 模拟点击不同的元素,增加随机延迟。

      // 模拟随机点击
      async function simulateRandomClicks(page, clicks = 5) {
          for (let i = 0; i < clicks; i++) {
              // 随机选择一个元素
              const elements = await page.$$('body *');
              const randomIndex = Math.floor(Math.random() * elements.length);
              const element = elements[randomIndex];
      
              // 获取元素的位置
              const boundingBox = await element.boundingBox();
              if (boundingBox) {
                  const centerX = boundingBox.x + boundingBox.width / 2;
                  const centerY = boundingBox.y + boundingBox.height / 2;
      
                  // 模拟鼠标移动到元素中心
                  await page.mouse.move(centerX, centerY);
      
                  // 模拟点击
                  await page.click('body'); // 点击body,可以触发更多事件
      
                  await page.waitForTimeout(Math.random() * 500 + 200); // 增加随机延迟
              }
          }
      }
    3. 模拟键盘输入: 模拟键盘输入,增加随机延迟。

      // 模拟键盘输入
      async function simulateKeyboardInput(page, text) {
          for (let i = 0; i < text.length; i++) {
              await page.keyboard.type(text[i]);
              await page.waitForTimeout(Math.random() * 100 + 50); // 增加随机延迟
          }
      }
    4. 随机页面停留时间: 每次访问页面后,随机停留一段时间。

      import time
      import random
      
      def random_sleep(min_seconds=1, max_seconds=5):
          sleep_time = random.uniform(min_seconds, max_seconds)
          time.sleep(sleep_time)
      
      # 使用示例
      random_sleep()
    5. 模拟页面滚动: 模拟页面滚动,增加随机延迟。

      // 模拟随机滚动
      async function simulateRandomScroll(page, scrollHeight = 500) {
           await page.evaluate((scrollHeight) => {
              window.scrollBy(0, Math.random() * scrollHeight);
          }, scrollHeight);
      
          await page.waitForTimeout(Math.random() * 500 + 200); // 增加随机延迟
      }

第三节:JS 环境检测——你是不是在装模作样?

网站可以通过检测 JavaScript 的运行环境,来判断你是不是一个真实的浏览器。比如,检测是否存在 window 对象、navigator 对象,或者检测一些特定的 JavaScript 函数。

  • 常见的 JS 环境检测:

    检测项 说明
    window 对象 window 对象是浏览器环境的全局对象,如果不存在,说明不是浏览器环境。
    navigator 对象 navigator 对象包含了浏览器的信息,比如 User-Agent、Platform 等,如果不存在,说明不是浏览器环境。
    document 对象 document 对象代表了 HTML 文档,如果不存在,说明不是浏览器环境。
    特定函数 网站可能会检测一些特定的 JavaScript 函数,比如 evalFunction,如果不存在或者被修改,说明可能是一个模拟环境。
  • 检测方式:

    网站通常会用 JavaScript 代码来检测这些信息,然后进行分析和判断。

  • 绕过策略:

    1. 使用 Headless Chrome: Headless Chrome 提供了完整的 JavaScript 运行环境,可以有效避免 JS 环境检测。

    2. 修改 JavaScript 环境: 可以修改 JavaScript 的运行环境,模拟真实的浏览器环境。

      // 修改 navigator 对象
      Object.defineProperty(navigator, 'webdriver', {
          get: () => false,
      });
      
      // 修改 window 对象
      window.navigator.chrome = {
          runtime: {},
      };
      
      // 删除一些属性
      delete navigator.plugins;
      delete navigator.mimeTypes;
    3. 使用 Proxy: 使用 Proxy 可以拦截 JavaScript 代码的执行,修改返回值,从而绕过 JS 环境检测。

      // 使用 Proxy 拦截 navigator 对象
      const originalNavigator = navigator;
      const proxyNavigator = new Proxy(originalNavigator, {
          get: function(target, prop) {
              if (prop === 'webdriver') {
                  return false;
              }
              return target[prop];
          },
      });
      
      // 将 navigator 对象替换为 Proxy 对象
      window.navigator = proxyNavigator;

第四节:蜜罐——小心有诈!

蜜罐是一种诱饵技术,网站会在页面上放置一些隐藏的链接或表单,只有机器人才能发现并点击。一旦机器人点击了这些链接或表单,就会被识别出来。

  • 常见的蜜罐:

    类型 说明
    隐藏链接 在页面上放置一些隐藏的链接,比如用 CSS 将链接隐藏起来,或者将链接的颜色设置为和背景色一样。
    隐藏表单 在页面上放置一些隐藏的表单,比如用 CSS 将表单隐藏起来,或者将表单的 name 属性设置为一些奇怪的值。
    JavaScript 生成的链接 通过JavaScript动态生成链接,正常用户不会这么快就抓取到这些链接,而爬虫可能会抓取到。
  • 检测方式:

    网站通常会用 CSS 或 JavaScript 代码来隐藏这些链接或表单。

  • 绕过策略:

    1. 不要抓取隐藏的链接或表单: 在抓取页面时,忽略那些用 CSS 隐藏起来的链接或表单。

      from bs4 import BeautifulSoup
      import requests
      
      response = requests.get('https://www.example.com') # 替换成目标网址
      soup = BeautifulSoup(response.content, 'html.parser')
      
      # 找到所有可见的链接
      visible_links = [a['href'] for a in soup.find_all('a') if a.get('href') and a.get('style') != 'display: none;']
      
      print(visible_links)
    2. 不要填写隐藏的表单: 在填写表单时,检查表单的 name 属性,避免填写那些 name 属性奇怪的表单。

    3. 使用真实用户行为: 模拟真实用户的行为,不要盲目地抓取所有的链接或填写所有的表单。

总结:道高一尺,魔高一丈!

Anti-Bot 机制和绕过策略是一个永恒的猫鼠游戏。网站会不断地更新 Anti-Bot 机制,我们也要不断地学习和改进绕过策略。记住,咱们的目标不是战胜所有的 Anti-Bot 机制,而是要找到一个平衡点,既能抓取到我们需要的数据,又能避免被网站封禁。

最后,送给大家一句至理名言:

爬虫有风险,入行需谨慎! (手动狗头)

希望今天的分享对大家有所帮助! 谢谢大家!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注