且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何检测假用户(爬虫)和 cURL

更新时间:2023-02-24 16:09:36

没有什么神奇的解决方案可以避免自动爬行.人类能做的每一件事,机器人也能做到.只有让工作更难的解决方案,难到只有技术娴熟的极客才能通过.

几年前我也遇到了麻烦,我的第一个建议是,如果你有时间,自己做一个爬虫(我认为爬虫"就是爬你的网站的人),这是该学科***的学校.通过抓取多个网站,我了解了不同类型的保护措施,并将它们关联起来,我一直很高效.

我给您提供了一些您可以尝试的保护示例.

每个 IP 的会话数

如果用户每分钟使用 50 个新会话,您可以认为该用户可能是一个不处理 cookie 的爬虫.当然,curl 可以完美地管理 cookie,但是如果您将它与每个会话的访问计数器结合起来(稍后解释),或者如果您的抓取工具是 cookie 问题的新手,它可能会很有效.

很难想象同一共享连接的 50 个人会同时访问您的网站(这当然取决于您的流量,这取决于您).如果发生这种情况,您可以锁定网站页面,直到验证码填满为止.

想法:

1) 您创建了 2 个表:1 个用于保存禁止的 ips,1 个用于保存 ip 和会话

如果不存在则创建表 session_per_ip (ip int 无符号,session_id varchar(32),创建时间戳默认 current_timestamp,主键(ip,session_id));如果不存在则创建表 banned_ips (ip int 无符号,创建时间戳默认 current_timestamp,主键(ip));

2) 在脚本的开头,您从两个表中删除了太旧的条目

3) 接下来检查您的用户的 ip 是否被禁止(您将标志设置为 true)

4) 如果没有,你计算他的 ip 会话数

5) 如果他有太多的会话,你把它插入你的禁止表并设置一个标志

6) 如果尚未插入,则将他的 ip 插入到每个 ip 表的会话中

我写了一个代码示例来更好地展示我的想法.

setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);//删除表中的旧条目$query = "delete from session_per_ip where timestampdiff(second, creation, now()) > {$check_duration}";$dbh->exec($query);$query = "delete from banned_ips where timestampdiff(second, creation, now()) > {$lock_duration}";$dbh->exec($query);//获取附加到我们用户的有用信息...session_start();$ip = ip2long($_SERVER['REMOTE_ADDR']);$session_id = session_id();//检查IP是否已经被禁止$banned = false;$count = $dbh->query("select count(*) from disabled_ips where ip = '{$ip}'")->fetchColumn();如果 ($count > 0){$banned = true;}别的{//为这个 ip 计算我们数据库中的条目$query = "select count(*) from sessions_per_ip where ip = '{$ip}'";$count = $dbh->query($query)->fetchColumn();如果 ($count >= $max_sessions){//锁定这个ip的网站$query = "将忽略插入到banned_ips ( ip ) 值( '{$ip}' )";$dbh->exec($query);$banned = true;}//如果用户的会话尚未记录,则在我们的数据库中插入一个新条目$query = "将忽略插入到 session_per_ip ( ip, session_id ) 值 ('{$ip}', '{$session_id}')";$dbh->exec($query);}//此时,如果您的用户被禁止,则您有一个 $banned.//下面的代码将允许我们测试它...//我们现在不显示任何内容,因为我们将使用会话://为了使演示更具可读性,我更喜欢逐步进行//这.ob_start();//显示您当前的会话echo "您当前的会话密钥是:<br/>";$query = "select session_id from sessions_per_ip where ip = '{$ip}'";foreach ($dbh->query($query) as $row) {echo "{$row['session_id']}<br/>";}//显示和处理创建新会话的方法echo str_repeat('<br/>', 2);echo '<a href="' . basename(__FILE__) . '?new=1">创建新会话/重新加载</a>';如果 (isset($_GET['new'])){session_regenerate_id();session_destroy();header("位置:" .basename(__FILE__));死();}//显示是否被禁止echo str_repeat('<br/>', 2);如果($禁止){echo '<span style="color:red;">您已被封禁:等待 60 秒才能解封...验证码当然必须更友好!</span>';回声'<br/>';echo '<img src="http://4.bp.blogspot.com/-PezlYVgEEvg/TadW2e4OyHI/AAAAAAAAAg/QHZPVQcBNeg/s1600/feu-rouge.png"/>';}别的{echo '<span style="color:blue;">你没有被禁止!</span>';回声'<br/>';echo '<img src="http://identityspecialist.files.wordpress.com/2010/06/traffic_light_green.png"/>';}ob_end_flush();}捕获 (PDOException $e){/*echo*/$e->getMessage();}?>

访问柜台

如果您的用户使用相同的 cookie 来抓取您的网页,您将能够使用他的会话来阻止它.这个想法很简单:你的用户有可能在 60 秒内访问 60 个页面吗?

想法:

  1. 在用户会话中创建一个数组,它将包含访问时间()s.
  2. 删除此数组中超过 X 秒的访问
  3. 为实际访问添加一个新条目
  4. 计算此数组中的条目
  5. 如果您的用户访问了 Y 个页面,则禁止他

示例代码:

 $time){如果 ((time() - $time) > $visit_counter_secs) {未设置($_SESSION['visit_counter'][$key]);}}//我们将当前访问添加到我们的数组中$_SESSION['visit_counter'][] = time();//检查用户是否已达到访问页面的限制$banned = false;如果(计数($_SESSION['visit_counter'])>$visit_counter_pages){//将我们用户的 ip 放在与之前相同的禁止表"上...$banned = true;}//此时,如果您的用户被禁止,则您有一个 $banned.//下面的代码将允许我们测试它...echo '<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>';//显示计数器$count = count($_SESSION['visit_counter']);echo "您访问了 {$count} 页.";echo str_repeat('<br/>', 2);回声<<<EOT<a id="reload" href="#">重新加载</a><script type="text/javascript">$('#reload').click(function(e) {e.preventDefault();window.location.reload();});EOT;echo str_repeat('<br/>', 2);//显示是否被禁止echo str_repeat('<br/>', 2);如果($禁止){echo '<span style="color:red;">你被禁止了!稍等片刻(在此演示中为 10 秒)...</span>';回声'<br/>';echo '<img src="http://4.bp.blogspot.com/-PezlYVgEEvg/TadW2e4OyHI/AAAAAAAAAg/QHZPVQcBNeg/s1600/feu-rouge.png"/>';}别的{echo '<span style="color:blue;">你没有被禁止!</span>';回声'<br/>';echo '<img src="http://identityspecialist.files.wordpress.com/2010/06/traffic_light_green.png"/>';}?>

要下载的图像

当一个爬虫需要做他的脏活时,那是为了大量的数据,而且是在尽可能短的时间内.这就是为什么他们不在页面上下载图像;占用太多带宽,使爬行速度变慢.

这个想法(我认为最优雅也最容易实现)使用了mod_rewrite 将代码隐藏在 .jpg/.png/... 图像文件中.此图片应在您要保护的每个页面上可用:它可以是您的徽标网站,但您将选择一个小尺寸的图片(因为此图片不得被缓存).

想法:

1/将这些行添加到您的 .htaccess

RewriteEngine OnRewriteBase/tests/anticrawl/重写规则 ^logo.jpg$ logo.php

2/使用安全性创建您的 logo.php

3/在您需要添加安全性的每个页面上增加 no_logo_count,并检查它是否达到您的限制.

示例代码:

EOT;echo str_repeat('<br/>', 2);//显示显示图片"链接:注意我们使用的是 .jpg 文件回声<<<EOT<div id="image_container"><a id="image_load" href="#">加载图片</a>