如何允许用户复制我的电子邮件地址而不是爬虫?

How to allow user to copy my email address but not crawlers?

我遇到一个问题,一些爬虫从我的网站抓取电子邮件地址并发送垃圾邮件。

有没有办法让普通用户复制邮件而不是爬虫(在html源代码中无法检测xxx@xxx.com格式)?

我尝试了以下解决方案,但其中 none 在复制电子邮件地址时有效:

解决方案 1

Try copying this will not copy @ and .com

.name::after {
  content: '@';
}

.mail::after {
  content: '.com';
}
<span class="name">foo</span><span class="mail">gmail</span>

解决方案 2

Try copying this makes foo and @gmail.com reversed.

.mail {
  display: inline-flex;
  flex-direction: row-reverse;
}
<div class="mail">
  <span>@gmail.com</span>
  <span>foo</span>
</div>

您可以尝试在电子邮件之间添加 HTML 评论。

<div class="mail">
  <span>foo<!--not an email-->@gmail.com</span>
</div>

但是,正如 OP 提到的,爬虫可以轻松过滤 HMTL 评论。如果你 运行 你的原始代码也通过 minifyers,评论可以被过滤掉。

您也可以尝试使用 Javascript 将您的电子邮件注入 DOM。

<div id="mail"></div>
<script>
  document.querySelector("#mail").innerText = ["foo", "gmail.com"].join("@")
</script>

这使得不 运行 Javascript 的抓取工具无法查看您的电子邮件。不过,为了让您的用户更有用,您还可以实施 copy-on-click.

<input type="text" readonly id="mail">
<script>
  let email = ["foo", "gmail.com"].join("@")
  let element = document.querySelector("#mail")
  element.value = email
  element.addEventListener('click', e => {
    element.select()
    element.setSelectionRange(0, 99999)
    document.execCommand("copy")
  })
</script>
<style>
   #mail{
     appearance: none; 
     border: 0; 
     outline: 0;
     font-family: inherit;
     font-size: inherit;
   }
</style>

可以将输入样式设置为像普通 inline-block 文本一样。您可以添加在复制后立即显示的工具提示。

您可以强制用户单击按钮让 JavaScript 为他们复制电子邮件。

document.querySelector('button').onclick = () => {

  const span = document.querySelector('span');
  const before = window.getComputedStyle(span, ':before').getPropertyValue('content').replace(/"/g, '');
  const after = window.getComputedStyle(span, ':after').getPropertyValue('content').replace(/"/g, '');

  const input = document.createElement('input');
  document.body.append(input);
  input.value = before + after;
  input.select();
  input.setSelectionRange(0, 99999);
  document.execCommand('copy');
  input.remove();
}
span:before {
  content: 'foo';
}

span:after {
  content: '@bar.com';
}
<span></span><button>Copy!</button>