web-dev-qa-db-ger.com

Facebook Crawler schlägt hart auf meinen Server und ignoriert Anweisungen. Mehrfacher Zugriff auf richtige Ressourcen

Der Facebook-Crawler schlägt mehrere Male pro Sekunde auf meine Server und scheint sowohl den Expires-Header als auch die og: ttl -Eigenschaft zu ignorieren.

In einigen Fällen greift es mehrmals innerhalb von 1 bis 5 Minuten auf dieselbe og: image-Ressource zu. In einem Beispiel: Der Crawler hat innerhalb von 3 Minuten mit 12 verschiedenen IP-Adressen 12 Mal auf dasselbe Image zugegriffen. 

Ich musste nur 10 Minuten lang Anfragen protokollieren, bevor ich folgendes Beispiel sah:

Liste der Zeiten und Crawler-IP-Adressen für ein Image:

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

Was ist das og: image gemäß der Dokumentation von Facebook

Die URL des Bildes, die angezeigt wird, wenn jemand den Inhalt an Facebook weitergibt. Weiter unten finden Sie weitere Informationen und unsere Best Practices . Hier erfahren Sie, wie Sie ein Vorschaubild mit hoher Qualität angeben.

Für die Bilder, die ich im og: image verwende, ist der Expires-Header auf +7 Tage in der Zukunft festgelegt. In letzter Zeit habe ich das in +1 Jahre in der Zukunft geändert. Keine der Einstellungen scheint einen Unterschied zu machen. Die Header, die der Crawler zu ignorieren scheint:

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

Laut der Object Properties-Dokumentation von Facebook ist die Eigenschaft og: ttl: 

Sekunden, bis diese Seite erneut gescrapet werden soll. Verwenden Sie diese Option, um das Limit Der Facebook-Crawler für Inhalte zu bewerten. Der minimal zulässige Wert beträgt 345600 Sekunden (4 Tage); Wenn Sie einen niedrigeren Wert festlegen, wird der Mindestwert verwendet. Wenn Sie dieses Tag nicht angeben, wird das TTL aus dem "Expires" -Header berechnet, der von Ihrem Webserver zurückgegeben wird, andernfalls wird standardmäßig auf 7 Tage gesetzt.

Ich habe diese og: ttl-Eigenschaft auf 2419200 gesetzt, was 28 Tage in der Zukunft liegt.

Ich war versucht, so etwas zu verwenden:

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

Ich befürchte jedoch, dass der Crawler von Facebook die Kopfzeile ignorieren und das Bild als beschädigt markieren würde, wodurch die Bildvorschau aus der gemeinsamen Story entfernt würde.

Ein Video mit der Rate , mit der diese Anfragen vom Crawler eingehen.

Gibt es eine Möglichkeit, den Crawler daran zu hindern, diese Ressourcen so schnell wieder zu treffen?

Beispielcode, der zeigt, wie meine geöffneten Diagramm- und Meta-Eigenschaften aussehen:

<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" />
12
Wayne Whitty

Nachdem ich fast alles andere mit Caching, Headern und was auch immer versucht hatte, rettete das einzige, was unsere Server vor "übermäßig enthusiastischen" Facebook-Crawlern(User-Agent facebookexternalhit)war einfach den Zugriff verweigern und HTTP/1.1 429 Too Many Requests HTTP-Antwort zurücksenden , als der Crawler "zu viel gecrawlt" hat.

Zugegeben, wir hatten Tausende von Bildern, die der Crawler crawlen sollte, aber der Facebook-Crawler warpraktisch DDOS auf unserem Servermit Zehntausenden von Anfragen(ja, dieselben URLs immer und immer wieder), pro Stunde. Ich erinnere mich, dass es sich um 40 000 Anfragen pro Stunde von verschiedenen Facebook-IP-Adressen unter Verwendung des User Agents facebookexternalhit an einem Punkt handelte.

Wir wollten den Crawler nicht vollständig blockieren und das Blockieren nach IP-Adresse war auch keine Option. Wir brauchten nur die FB Crawler (ziemlich) ein bisschen zurück.

Dies ist ein Teil des PHP Codes, mit dem wir es gemacht haben:

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

Sie müssen auch das Neuschreiben konfigurieren, um alle an Ihre Bilder gerichteten Anforderungen an dieses PHP Skript weiterzuleiten:

.../images/.htaccess (wenn Sie Apache verwenden)

RewriteEngine On
RewriteRule .* index.php [L] 

Es scheint, als hätte der Crawler diesen Ansatz "verstanden" unddie Versuchsrateeffektiv von Zehntausenden Anforderungen pro Stunde auf Hunderte/reduziert. Tausende Anfragen pro Stunde.

10
Smuuf

Blindes Senden 304 Not Modified-Header ist nicht sinnvoll und kann den Crawler von Facebook noch mehr verwirren. Wenn Sie sich wirklich dazu entschließen, einige Anfragen zu blockieren, sollten Sie 429 Too Many Requests header in Betracht ziehen - es wird zumindest klar angezeigt, um welches Problem es sich handelt.

Als sanftere Lösung können Sie versuchen:

  • Fügen Sie Last-Modified-Header mit einem statischen Wert hinzu. Der Crawler von Facebook könnte klug genug sein, um zu erkennen, dass er für ständig wechselnde Inhalte Expires-Header ignorieren sollte, aber nicht klug genug ist, um fehlende Header richtig zu behandeln.
  • Fügen Sie ETag-Header mit der richtigen 304 Not Modified-Unterstützung hinzu.
  • Ändern Sie den Cache-Control-Header in max-age=315360000, public, immutable, wenn das Bild statisch ist.

Sie können auch ein zwischengespeichertes Bild speichern und über den Webserver bereitstellen, ohne PHP zu involvieren. Wenn Sie URLs in etwas wie http://fb.example.com/img/image/123790824792439jikfio09248384790283940829044 ändern, können Sie durch Umschreiben von Regeln einen Fallback für nicht vorhandene Dateien erstellen:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^img/image/([0-9a-z]+)$ img/image.php?id=$1 [L]

Nur die erste Anforderung sollte von PHP verarbeitet werden, wodurch der Cache für die angeforderte URL gespeichert wird (beispielsweise in /img/image/123790824792439jikfio09248384790283940829044). Für alle weiteren Anfragen sollte der Webserver darauf achten, den Inhalt aus der zwischengespeicherten Datei bereitzustellen, die richtigen Header zu senden und 304 Not Modified zu verarbeiten. Sie können nginx auch für rate limit - konfigurieren. Es sollte effizienter sein, als die Bereitstellung von Servern an PHP zu delegieren.

3
rob006

Es scheint, dass die Crawler von Facebook nicht immer so respektvoll sind. In der Vergangenheit haben wir den Vorschlag hier implementiert: übermäßiger Traffic von facebookexternalhit bot

Es ist nicht die beste Lösung, da es für Nizza schön wäre, die Antragsquote zu begrenzen, aber offensichtlich tun sie das nicht. 

3
Simon R

Ich habe Word vom Facebook-Team selbst zurückbekommen. Hoffentlich bringt es etwas Klarheit darüber, wie der Crawler Bild-URLs behandelt. 

Hier kommt's:

Der Crawler behandelt Bild-URLs anders als andere URLs.

Wir kratzen Bilder mehrmals, weil wir unterschiedliche physische Regionen haben, von denen jede das Bild abrufen muss. Da wir etwa 20 verschiedene Regionen haben, sollte der Entwickler ~ 20 Aufrufe für jedes Bild erwarten. Nachdem wir diese Anfragen gestellt haben, bleiben sie etwa einen Monat lang in unserem Cache. Wir müssen diese Bilder regelmäßig neu scannen, um Missbrauch Auf der Plattform zu verhindern Bild und ersetzen Sie es durch ein beleidigendes).

Grundsätzlich sollten Sie damit rechnen, dass das in og: angegebene Bild 20 Mal nach der Freigabe getroffen wird. Dann, einen Monat später, wird es erneut abgekratzt.

2
Wayne Whitty

Wenn die FB-Crawler Ihre Cache-Header ignorieren, könnte in diesem Fall das Hinzufügen des ETag-Headers verwendet werden, um korrekte Antworten zurückzugeben und die Last Ihres Servers zu reduzieren.

Wenn Sie das erste Mal ein Bild generieren, berechnen Sie den Hashwert dieses Bildes (z. B. mit md5) als Antwortkopf "ETag". Wenn Ihr Server eine Anforderung mit dem Header "If-None-Match" empfängt, überprüfen Sie, ob Sie diesen Hash bereits zurückgegeben haben. Wenn die Antwort ja ist, eine Antwort 304 zurückgeben. Wenn nicht, generieren Sie das Bild.

Wenn Sie überprüfen, ob Sie bereits einen bestimmten Hash zurückgegeben haben (ohne dabei das Bild erneut zu generieren), müssen Sie den Hash irgendwo speichern ... Vielleicht speichern Sie die Bilder in einem tmp-Ordner und verwenden den Hash als Dateinamen?

Weitere Informationen zu den Kopfzeilen "ETag" + "If-None-Match" .

0
Rober MH

Facebook-Dokumentation speziell states "Bilder werden basierend auf der URL zwischengespeichert und werden nur dann aktualisiert, wenn sich die URL ändert.". Dies bedeutet, dass es keine Rolle spielt, welche Header oder Metatags Sie zu Ihrem hinzufügen Seite soll der Bot das Bild trotzdem zwischenspeichern.

Das brachte mich zum Nachdenken:

  1. Teilt jeder Nutzer eine etwas andere URL Ihrer Seite? Dadurch wird das freigegebene Bild jedes Mal neu zwischengespeichert.
  2. Wird auf Ihr freigegebenes Bild mit einer etwas anderen URL zugegriffen?
  3. Vielleicht wird das Bild irgendwo anders verlinkt?

Ich würde die Seitenprotokolle überwachen und genau sehen, was passiert. Wenn die Seiten-URL oder die Bild-URL sogar etwas anders ist, funktioniert der Caching-Mechanismus nicht. Glücklicherweise scheint dies nicht wie eine Kopfzeile/Tags Art des Problems.

0
Walter White

Laut Facebook Dokumentation respektiert nur der Facebot-Crawler die Crawler-Richtlinien. Sie deuten jedoch auch darauf hin

Sie können einem dieser Benutzeragenten als Ziel dienen, dem Crawler eine Nicht öffentliche Version Ihrer Seite bereitzustellen, die nur Metadaten und keinen tatsächlichen Inhalt enthält. Dies trägt zur Optimierung der Leistung bei und ist hilfreich, um Paywall-Inhalte sicher zu halten.

Einige Leute schlagen vor, den Zugriff auf facebookexternalhit zu beschränken. Ich bezweifle jedoch, dass dies eine gute Idee ist, da der Crawler möglicherweise daran gehindert wird, den Inhalt zu aktualisieren.

Je nach Architektur können mehrere Treffer von verschiedenen IPs, aber demselben Bot angezeigt werden. Sie sollten überprüfen, wie oft dieselbe Ressource durchsucht wird. og: ttl ist was die Dokumentation empfiehlt und helfen sollte.

0
Emil

@Nico schlägt vor

Wir hatten die gleichen Probleme auf unserer Website/Server. Das Problem war der og:url-Metatag. Nach dem Entfernen wurde das Problem für die meisten Aufrufe von facebookexternalhit behoben.

Sie können also versuchen, das Problem zu beheben

0
serv-inc