18

Script anti duplicate content avec les sous-domaines

Contenu dupliquéLes sous-domaines peuvent dans certains cas être des générateurs de contenu dupliqué. Si votre homepage a des prédispositions pour ressortir sur une requête, avoir la même homepage présente dans l'index de Google avec une autre URL ne va pas aider l'ami Algo à trier correctement ces pages dans les SERP, vous n'allez pas ranker comme il faut.
Je ne vais pas vous refaire un laïus sur le Duplicate content mais plutôt vous présenter un script qui va vous permettre de lister tous les sous-domaines indexés sur Google pour un nom de domaine donné, afin de détecter d'éventuelles erreurs et/ou sous-domaines inattendus.

Pourquoi?

L'idée m'est venu entre autre quand j'ai constaté que j'avais un sous-domaine dupliqué à cause d'un site en version beta/dev qui avait été indexé (oui, Google la fouine lit les liens texte hors href, utilise les données de la Toolbar Google, et crawl le tout). Si vous êtes consultant/Chef de projet SEO (ce n'est pas encore mon cas, mais j'y aspire fortement, alors pensez à moi 😉 ), ce script pourrait être un passage obligatoire lors d'un audit si vous n'avez pas accès au zonefile de votre client.
Avec ce script SEO, j'ai ainsi pu trouver par exemple un sous-domaine étrange de webrankinfo.com http://forum.webrankinfo.comforum.webrankinfo.com/ qui générait 4 pages dupliquées (dont la homepage) de Webrankinfo: Olivier Duffez, si tu passes par là;)

Comment?

Le script va parcourir 1000 résultats (ce qui semble suffisant pour la plupart des sites) pour ensuite extraire les sous-domaine présents grâce à une petite expression régulière. Je ne peux pas finir cet article sans remercier @percub qui m'a bien aidé puisque j'étais parti dans une boucle un peu étrange et complexe dans laquelle je bouclais sur la requête modifiée au fur et à mesure (genre site:domaine.com -site:sd1.domain.com -site:sd2.domain.com -site:sd3.domain.com etc...) jusqu'à arriver au message "error 414, request is too long" (et oui, j'avais testé sur yahoo.com avec plus de 230 sous-domaines...). Il a su me remettre dans le droit chemin et me conseiller après pas mal d'échanges mails. Merci à lui. Du coup ce script est un doux mélange de différents bouts de code.

Script anti-duplicate avec des sous-domaines

Enjoy!

<?php
function scrapounet ($domaine)
{
$schema = '`<cite>(.*?)\.'.$domaine.'\/(.*?)<\/cite>`i';
$requete = '';$subs = '';$subdomaines = '';$output = '';$i=0;$j=0;
$useragent='Opera/9.63 (Windows NT 5.1; U; fr) Presto/2.1.1';
for ($i=0; $i<901; $i+=100) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
curl_setopt($ch, CURLOPT_URL,'http://www.google.fr/search?q=site:*.'.$domaine.'&hl=fr&ie=utf-8&oe=utf-8&aq=t&num=100&start='.$i);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
$result .= curl_exec ($ch);
curl_close ($ch);
sleep(5);
}
preg_match_all($schema, $result, $matches);
$matches = array_unique($matches[1]);
sort($matches);
foreach (($matches) as $key => $subs) {
$j++;
$subs = str_replace('https://','',$subs);
$requete .= '-site:'.$subs.'.'.$domaine;
$subdomaines .= '<tr><td>'.$subs.'</td><td>'.gethostbyname($subs.'.'.$domaine).'</td></tr>';
$export .= $subs."\n";
}
file_put_contents($domaine.'.txt',$export);
$output = 'Télécharger l\'export (clic droit): <a href="'.$domaine.'.txt">'.$domaine.'.txt</a><br /><hr>';
$output .= 'Liste des '.$j.' sous-domaines indexées:<br /><br /><table border="1"><tr><td><b>Sous-domaine</b></td><td><b>Adresse IP</b></td></tr>'.$subdomaines.'</table><hr>';
$output .= '<u>Equivalent de la requête Google effectuée avec la version précédente du script:</u> site:'.$domaine.$requete.'<br /><hr>';
return $output;
}

if (isset($_GET["domaine"]) && $_GET["domaine"]!='')
{
$dom = $_GET["domaine"];
print $output =  scrapounet ($_GET["domaine"]);
}
?>

Appelez ensuite le script de cette manière: http://www.votresite.com/sousdomaines.php?domaine=abondance.com

Voici un screenshot d'une sortie:

Edité le 04/11:

Je vous mets malgré tout l'ancien script car dans certains cas et après de nombreux tests, les 1000 premiers résultats ne suffisent pas forcément pour faire apparaître tous les sous-domaines. Tant que la requête n'est pas trop longue (et que l'erreur 414 n'arrive pas), ce script extrait plus de sous-domaines. Essayez les deux!

<?php

function scrapounet ($domaine)
{
$schema = '`<cite>(.*?)\.'.$domaine.'\/(.*?)<\/cite>`i';
$requete = '';$subs = '';$i=0;$j=0;
$useragent='Opera/9.63 (Windows NT 5.1; U; fr) Presto/2.1.1';
do {
$ch = curl_init();
curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
curl_setopt($ch, CURLOPT_URL,'http://www.google.fr/search?q=site:'.$domaine.$requete.'&hl=fr&ie=utf-8&oe=utf-8&aq=t&num=100');
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
$result = curl_exec ($ch);
preg_match_all($schema, $result, $matches);
$matches = array_unique($matches[1]);
foreach (($matches) as $key => $subs) {
$subs = str_replace('https://','',$subs);
if (!eregi('\+\-site:'.$subs.'.'.$domaine,$requete)) {
$j++;
$requete .= '+-site:'.$subs.'.'.$domaine;
$subdomaines .= '<tr><td>'.$subs.'</td><td>'.gethostbyname($subs.'.'.$domaine).'</td></tr>';
$export .= $subs."\n";}
}
sleep(5);
$i++;
}
while ($i<10) ;
file_put_contents($domaine.'.txt',$export);
$output = 'Télécharger l\'export (clic droit): <a href="'.$domaine.'.txt">'.$domaine.'.txt</a><br /><hr>';
$output .= 'Liste des '.$j.' sous-domaines indexées:<br /><br /><table border="1"><tr><td><b>Sous-domaine</b></td><td><b>Adresse IP</b></td></tr>'.$subdomaines.'</table><hr>';
$output .= '<u>Rêquete Google effectuée:</u> site:'.$domaine.$requete.'<br /><hr>';
return $output;
}

if (isset($_GET["domaine"]) && $_GET["domaine"]!='')
{
$dom = $_GET["domaine"];
print $output =  scrapounet ($_GET["domaine"]);
}
?>

Crédit photo : Girafes dupliquées lors de mon voyage en Tanzanie.

18 commentaires

  1. Merci pour la citation 😉

    Dernière modif: Google arrête d’afficher les résultats à 1000 donc tu peux modifier la condition de ta boucle for –> $i<901

  2. Effectivement, j’avais pas vu l’erreur en faisant un print de $result. C’est corrigé. Merci encore à toi 😉

  3. Pas mal ça ! Même si faut être sacrément nouille pour pas mettre de restriction d’ip ou de htpassword sur un site de dev et se le faire indexer après :p

    • 😀 je pensais pas qu’il allait le trouver surtout… Nouille de la part d’ un jambon, je suis flatté !

    • Les développeurs qui bossent dans ma boite sont des nouilles … je ne compte plus le nombre de fois ou j’ai du me cogner des campagnes de redirections 301 pour virer un de nos sous domaine qui concurrencait un des sites qu’on avait fait … Depuis il me semble quand meme qu’un bon Noindex nofollow + quelques trucs dans le HTaccess sont suffisant pour ce probleme.

      Apres c’est un bon petit script mettre en place – ce serait possible d’avoir le mem en ASP??? qqn?

  4. Heu oui pour commencer, pourquoi des girafes ?

    Sinon, (j’ai peut être mal compris mais) c’est pas courant d’avoir plus de mille sous domaine… 🙂

    C’est fou tout de même, qu’est-ce qu’il ne faut pas faire, comme truc pour que google nous laisse tranquile…

    J’avais aussi sur un site un sous domaine dev. afin que je fasse des test avant mise en mise definitive, j’ai du desactiver et 301 car DC, …, remarque j’ai eu un petit coup de boost peu apres, une sorte de reponse sinusoïdale à un échelon …

    J’imagine la tête du moteur, quand il a reçu d’un coup une centaine de redirection …

    • Des anciens sous-domaines, un mauvais paramétrage DNS (wildcard par exemple), un CMS mal configuré peuvent générer beaucoup de domaines dupliqués. Mais ce script peu avoir d’autres utilités, être adapté, libre recours à votre imagination!

  5. Salut,

    avec un sleep de 5 secondes à chaque requête tu n’as pas de soucis de blacklistage à la longue ?

    Merci en tout cas. ce script pourra servir de bonne base 😉

    • Avec 10 passages non, ça passait nickel quand je faisais mes tests avec des print de $result.

  6. Je pensais naïvement que la requête :
    site:*.example.com -inurl:www.example.com
    sur Google pouvait être suffisante

  7. Je ne me suis pas rendu compte de l’erreur en faisant un print de $result. Le tir est rectifié. Une fois encore, recevez mes remerciements.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *