<?php
//CODE TEST :
//ENLEVEZ/COMMENTEZ LE CODE QUI SUIT EN MODE PRODUCTION
//pour tester, augmentez $TEMPS_ENTRE_REELS_CRAWL à 30 secondes, le temps que vous puissiez voir les message d'erreurs/succès
//mettre d'abord true pour un vrai crawl FB (il se loguera) puis false pour un faux crawl
$vrai_crawl = true;
if($vrai_crawl){
$_SERVER = [
'HTTP_USER_AGENT' => 'facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)',
'HTTP_ACCEPT_ENCODING' => 'deflate, gzip',
'HTTP_RANGE' => 'oui',//'oui' juste pour indiquer que HTTP_RANGE existe
'REQUEST_URI' => 'page.html',
];
}else{
$_SERVER = [
'HTTP_USER_AGENT' => 'facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)',
'REQUEST_URI' => 'page.html',
];
}
//FIN CODE TEST.
class Block_fake_fb_hits {
//429 (Too Many Requests) indique à l'utilisateur qu'il a envoyé trop de requêtes en un temps donné
protected $CODE_ENTETE_HTTP = 429;
protected $DOSSIER_LOGS = 'logs_fb_hits/verifications';
protected $SAUVER_LOGS = true;
protected $DOSSIER_LOGS_GLOBAUX = 'logs_fb_hits/logs_globaux';
//[date] sera remplacé par la date du jour pour ne pas avoir un fichier trop volumineux, chaque jour un nouveau fichier est créé
protected $FICHIER_LOGS_GLOBAUX = '[date].log';
//création des fichiers logs globaux chaque heure, si false, crée un seul fichier par jour
//mettre true si ya beaucoup de faux crawl pour dispatcher les logs en plusieurs fichiers
protected $INCLURE_HEURE_DANS_NOM_LOG = false;
//séparateur des infos logs dans les fichiers globaux, l'utilisation '"[espace][tiret]"' est nécessaire pour ne pas rentrer en conflit avec REQUEST_URI, une URL n'aura jamais un espace et un guillemet n'ont plus "
protected $SEPARATEUR = '" -"';
//secondes entre le bon hit et les suivants que FB peut envoyer sans les entêtes
protected $TEMPS_ENTRE_REELS_CRAWL = 5;
//init
protected $FICHIER_VERIFICATION;
protected $REQUEST_URI;
protected $HTTP_HOST;
protected $HTTP_USER_AGENT;
protected $REMOTE_ADDR;
//suivant là où est inclut Block_fake_fb_hits.php (à configurer dans le constructeur)
protected $_DIRNAME;
public function __construct(){
$this->REQUEST_URI = $_SERVER['REQUEST_URI'] ?? '';
$this->HTTP_HOST = $_SERVER['HTTP_HOST'] ?? '';
$this->HTTP_USER_AGENT = $_SERVER['HTTP_USER_AGENT'] ?? '';
$this->REMOTE_ADDR = $_SERVER['REMOTE_ADDR'] ?? '';
//crée un fichier de vérification uniquement pour la page parcourue
$this->FICHIER_VERIFICATION = 'fb-' . preg_replace("#[^a-z0-9-_]+#i", '-', $this->REQUEST_URI) . '.hit';
//"__DIR__, 1" pour remonter d'un dossier, "__DIR__, 2" de deux, etc
// $this->_DIRNAME = dirname(__DIR__, 2);
$this->_DIRNAME = __DIR__;
}
public function verifier(){
//un vrai crawl FB contient les entêtes HTTP_ACCEPT_ENCODING et HTTP_RANGE (https://developers.facebook.com/docs/sharing/webmasters/crawler/)
$est_fb_hit =
strstr($this->HTTP_USER_AGENT, 'facebookexternalhit') !== false
||
strstr($this->HTTP_USER_AGENT, 'facebookcatalog') !== false;
if(!$est_fb_hit)
return true;
$bon_hit = isset($_SERVER['HTTP_ACCEPT_ENCODING'], $_SERVER['HTTP_RANGE'])
&& $_SERVER['HTTP_ACCEPT_ENCODING'] == 'deflate, gzip';
$chemin = $this->_DIRNAME . '/' . $this->DOSSIER_LOGS . '/' . $this->FICHIER_VERIFICATION;
if($bon_hit){
//on met à jour son dernier passage
file_put_contents($chemin, time(), LOCK_EX);
//sauvegarde le log si on veut voir
$this->sauver_log(true);
return true;
}else{
if(!file_exists($chemin)){
$this->bloquer();
return false;
}
$access_line = file_get_contents($chemin);
//vérifie si ya eu un réel crawl ya moins de 5 secondes
if((int) $access_line >= time() - $this->TEMPS_ENTRE_REELS_CRAWL)
return true;
$this->bloquer();
return false;
}
}
private function bloquer(){
//sauvegarde le log si on veut voir
$this->sauver_log(false);
http_response_code($this->CODE_ENTETE_HTTP);
}
private function sauver_log($vrai_hit){
if(!$this->SAUVER_LOGS)
return;
$new_log = [];
$new_log[] = date('Y-m-d H:i:s');
$new_log[] = $this->REQUEST_URI;
$new_log[] = $this->HTTP_HOST;
$new_log[] = $this->REMOTE_ADDR;
$new_log[] = $this->HTTP_USER_AGENT;
$new_log = implode($this->SEPARATEUR, $new_log);
$date_fichier_log = $this->INCLURE_HEURE_DANS_NOM_LOG ? date('Y-m-d-H') : date('Y-m-d');
$fichier_log = str_replace('[date]', $date_fichier_log, $this->FICHIER_LOGS_GLOBAUX);
$fichier_log = ($vrai_hit ? 'vrais' : 'faux') . '/' . $fichier_log;
$chemin_logs = $this->_DIRNAME . '/' . $this->DOSSIER_LOGS_GLOBAUX . '/' . $fichier_log;
file_put_contents($chemin_logs, $new_log . "\n", FILE_APPEND | LOCK_EX);
}
}
if((new Block_fake_fb_hits())->verifier() === false){
//message d'erreur ici
echo "<h1 style='color:red'>FAUX CRAWL FACEBOOK</h1>";
exit;
}
//contenu de la page ici
echo "<h1 style='color:green'>REEL CRAWL FACEBOOK / HUMAIN</h1>";
🚀 Simple, rapide et efficace pour suivre le trafic de votre site web : C2stats pour savoir qui vient sur votre site, où sont partagées les pages de votre site, le nombre de visiteurs sur mobiles...
_ /logs_fb_hits
|_ /verifications
|_ /logs_globaux
|_ /faux
|_ /vrais
J'espère que ce script gratuit vous est utile.Pour soutenir mon travail, un simple don ou mettre une note est grandement apprécié.
Vous cherchez à pousser encore plus loin vos idées ou à les concrétiser avec un site internet sur mesure ? Je suis là pour vous aider ! Mon expérience en développement web est à votre disposition.
Que ce soit la création de votre site web pro ou l'apport de fonctionnalités avancées à votre projet, contactez-moi pour en discuter et avoir un devis gratuit personnalisé.
Mon objectif est de vous offrir des solutions sur mesure qui répondent à vos besoins, et votre vision associée à mon expertise donnera vie à votre projet web parfait. Contactez-moi aujourd'hui, je réponds en général en moins d'une heure :
Demander un devis