Facebook爬虫正在重击我的服务器并忽略指令。多次访问相同的资源

Facebook爬虫每秒多次访问我的服务器,它似乎忽略了 Expires 标头和 og:ttl 属性。

在某些情况下,它会在 1-5 分钟内多次访问相同的 og:image 资源。在一个示例中 - 爬虫在3分钟内使用12个不同的IP地址访问了同一图像12次。

在我捕获以下示例之前,我只需要记录请求10分钟:

一个映像的时间和爬网程序 IP 地址列表:

2018-03-30 15:12:58 - 66.220.156.145
2018-03-30 15:13:13 - 66.220.152.7
2018-03-30 15:12:59 - 66.220.152.100
2018-03-30 15:12:18 - 66.220.155.248
2018-03-30 15:12:59 - 173.252.124.29
2018-03-30 15:12:15 - 173.252.114.118
2018-03-30 15:12:42 - 173.252.85.205
2018-03-30 15:13:01 - 173.252.84.117
2018-03-30 15:12:40 - 66.220.148.100
2018-03-30 15:13:10 - 66.220.148.169
2018-03-30 15:15:16 - 173.252.99.50
2018-03-30 15:14:50 - 69.171.225.134

根据Facebook的文档,og:image是什么:

当有人将内容分享到 Facebook 时显示的图片的网址。有关详细信息,请参阅下文,并查看我们的最佳做法指南,了解如何指定高质量的预览图像。

我在 og:image 中使用的图像将 Expires 标头设置为 +7 天。最近,我将其更改为+1年。这两种设置似乎都没有任何区别。爬网程序似乎忽略的标头:

Cache-Control: max-age=604800
Content-Length: 31048
Content-Type: image/jpeg
Date: Fri, 30 Mar 2018 15:56:47 GMT
Expires: Sat, 30 Mar 2019 15:56:47 GMT
Pragma: public
Server: nginx/1.4.6 (Ubuntu)
Transfer-Encoding: chunked
X-Powered-By: PHP/5.5.9-1ubuntu4.23

根据 Facebook 的 Object Properties 文档,og:ttl 属性是:

几秒钟,直到这个页面应该被重新抓取。使用此选项可对 Facebook 内容抓取工具进行速率限制。允许的最小值为 345600 秒(4 天);如果设置较低的值,将使用最小值。如果未包含此标记,则将从 Web 服务器返回的“Expires”标头计算 ttl,否则它将默认为 7 天。

我已将此 og:ttl 属性设置为 2419200,即未来的 28 天。

我一直想使用这样的东西:

header("HTTP/1.1 304 Not Modified"); 
exit;

但我担心的是,Facebook的抓取工具会忽略标题并将图像标记为已损坏 - 从而从共享故事中删除图像预览。

显示来自爬网程序的这些请求传入的速率的视频

有没有办法防止爬虫这么快就回来攻击这些资源?

示例代码显示了我的开放图形和元属性的外观:

<meta property="fb:app_id" content="MyAppId" />
<meta property="og:locale" content="en_GB" />
<meta property="og:type" content="website" />
<meta property="og:title" content="My title" />
<meta property="og:description" content="My description" />
<meta property="og:url" content="http://example.com/index.php?id=1234" />
<link rel="canonical" href="http://example.com/index.php?id=1234" />
<meta property="og:site_name" content="My Site Name" />
<meta property="og:image" content="http://fb.example.com/img/image.php?id=123790824792439jikfio09248384790283940829044" />
<meta property="og:image:width" content="940"/>
<meta property="og:image:height" content="491"/>
<meta property="og:ttl" content="2419200" />

答案 1

在我尝试了几乎所有其他缓存,标头和其他所有功能之后,唯一将我们的服务器从“过于热情”的Facebook爬虫(用户代理facebookexternalhit中拯救出来的就是简单地拒绝访问并发回HTTP / 1.1 429太多的请求HTTP响应,当爬虫“抓取太多”。

不可否认,我们有成千上万张我们希望爬虫抓取的图像,但Facebook爬虫实际上每小时都会用数以万计的请求(是的,一遍又一遍地使用相同的URL)来DDOSing我们的服务器。我记得每小时有40 000个请求来自不同的Facebook的IP地址使用te用户代理。facebookexternalhit

我们不想完全阻止爬虫,并且按IP地址阻止也不是一种选择。我们只需要FB爬行器来退缩(相当)一点。

这是我们用来做的一段PHP代码:

.../图像/索引.php

<?php

// Number of requests permitted for facebook crawler per second.
const FACEBOOK_REQUEST_THROTTLE = 5;
const FACEBOOK_REQUESTS_JAR = __DIR__ . '/.fb_requests';
const FACEBOOK_REQUESTS_LOCK = __DIR__ . '/.fb_requests.lock';

function handle_lock($lockfile) {
    flock(fopen($lockfile, 'w'), LOCK_EX);
}

$ua = $_SERVER['HTTP_USER_AGENT'] ?? false;
if ($ua && strpos($ua, 'facebookexternalhit') !== false) {

    handle_lock(FACEBOOK_REQUESTS_LOCK);

    $jar = @file(FACEBOOK_REQUESTS_JAR);
    $currentTime = time();
    $timestamp = $jar[0] ?? time();
    $count = $jar[1] ?? 0;

    if ($timestamp == $currentTime) {
        $count++;
    } else {
        $count = 0;
    }

    file_put_contents(FACEBOOK_REQUESTS_JAR, "$currentTime\n$count");

    if ($count >= FACEBOOK_REQUEST_THROTTLE) {
        header("HTTP/1.1 429 Too Many Requests", true, 429);
        header("Retry-After: 60");
        die;
    }

}

// Everything under this comment happens only if the request is "legit". 

$filePath = $_SERVER['DOCUMENT_ROOT'] . $_SERVER['REQUEST_URI'];
if (is_readable($filePath)) {
    header("Content-Type: image/png");
    readfile($filePath);
}

您还需要配置重写,以将定向到映像的所有请求传递到此 PHP 脚本:

.../images/.htaccess(如果您使用的是 Apache)

RewriteEngine On
RewriteRule .* index.php [L] 

爬虫似乎“理解了这一点”的方法,并有效地将尝试率从每小时数万个请求降低到每小时数百/数千个请求。


答案 2

我收到了Facebook团队自己的消息。希望它能为爬网程序如何处理图像 URL 带来一些澄清。

它在这里:

爬网程序处理图像 URL 的方式与其他 URL 不同。

我们多次抓取图像,因为我们有不同的物理区域,每个区域都需要获取图像。由于我们有大约 20 个不同的区域,因此开发人员应该期望每个映像有大约 20 个调用。一旦我们提出这些请求,它们就会在我们的缓存中保留大约一个月 - 我们需要经常重新压缩这些图像以防止平台上的滥用(恶意行为者可能会让我们抓取良性图像,然后用令人反感的图像替换它)。

因此,基本上,您应该期望og:image中指定的图像在共享后将被点击20次。然后,一个月后,它将再次被刮掉。


推荐