Si vous utilisez Screamingfrog vous savez déjà qu’il vous offre de nombreuses options pour personnaliser un crawl. Parmi les options vous pouvez utiliser l’interdiction ou l’inclusion de certains dossiers, mais il est impossible de le paramétrer pour suivre (ou ne pas suivre) uniquement certains liens en fonction de leur emplacement dans le code source.
Si vous souhaitez que screamingfrog ignore les liens internes présents dans la barre de navigation principale, de base c’est impossible, et pourtant…
Il existe un hack pour forcer screamingfrog à ne pas suivre ces liens internes présents dans le menu.
Ce cas d’utilisation étant vraiment intéressant, voici l’astuce pour personnaliser à souhaits l’exploration d’un site avec screaming frog. Est livré avec l’article le code PHP qui accompagne ce hack SEO.
Pour remettre un peu de contexte voici le tweet qui a inspiré ce hack screamingfrog.
Dites, les SEO, afin de valider un maillage, je cherche à crawler un site en ignorant les liens de menu et de footer (simuler leur disparition avant de le faire vraiment).
Vous feriez comment vous ?— Mathieu JANIN (@Matt_Refeo) June 15, 2020
Pourquoi forcer screamingfrog à ignorer les menus ?
Si j’ai bien compris, la finalité est d’éliminer du site un ou plusieurs menus, mais avant de faire ce changement radical, il faut mesurer l’impact. L’impact en matière de distribution du PageRank interne.
Quelqu’un d’autre pourrait parfaitement avoir besoin d’ignorer les liens des menus, pour effecturer une analyse du maillage interne focalisée sur les liens présents dans les contenus. Cela pourrait avoir du sens si on considère que Google donne plus d’importance au liens situés dans le contenu principal.
On pourrait identifier les pages qui bénéficient de trop peu de liens internes éditoriaux, ou d’aucun lien éditorial (une nouvelle race de pages orphelines).
Mais comment explorer un site en empêchant le crawler de suivre les liens de la navigation principale et du footer ?
Screamingfrog nous permet d’inclure et d’exclure des URLs en fonction de patterns présents dans l’URL mais ne permet pas (à l’heure où j’écris ces lignes) d’inclure ou d’exclure des URLs en fonction de leur emplacement dans le code. Comment remédier à ce problème ?
Il y a bien cette proposition, intéressante techniquement, mais franchement, un poil compliquée à mettre en place sur une version en production.
sinon une idée : tu demandes à ajouter un paramètres aux liens concernés le temps du crawl, comme ça le tri est hautement facilité ensuite depuis la liste créée par SF, et tu refais l’arborescence avec Gephi ou autre.
— Frédéric Laudet (@SeoFred34) June 15, 2020
On ne peut pas modifier le site en production, mais a-t-on forcément besoin de crawler le site sujet de l’analyse ? Non, on peut utiliser un proxy.
Il suffit de crawler “un script” qui fera office de miroir du site (généré à la volée). Sur ce miroir ou proxy on doit simplement éliminer du code HTML les éléments qui ne nous intéressent pas (ici les menus).
Par exemple on élimine toutes les balises <nav>…</nav> et la section <footer>…</footer>. Selon les cas d’utilisation on peut aussi tout faire sauter et ne garder que ce qui se trouve dans <main>…</main> ou encore dans <div id=”main-content”>…</div>.
Cette solution s’inspire de celle proposée pour forcer ScreamingFrog à suivre les liens externes et continuer le crawl indéfiniment. Il y a cependant deux choses majeures qui changent dans le présent cas de figure :
- Modification du code HTML à la volée pour éliminer les zones du code qui nous posent problème (ou garder uniquement celles qui nous intéressent)
- Plus besoin de réécrire les URLs externes pour forcer l’exploration infinie. Ici, on reste sur le même site.
Fonctionnement de ce Hack Screamingfrog concrètement
Supposez que nous devions travailler sur le site leptidigital.fr de @VincentBrossas. Le site en production se présente comme suit et nous voulons nous débarrasser de ce qui est encadré en rouge ici.
En passant par un simple script PHP qui nous servira de proxy et en manipulant légèrement le HTML, on obtient le résultat dont Mathieu a besoin, à savoir un site dépourvu de menu de navigation, et de footer. Nous aurions pu aussi faire disparaître la sidebar, mais c’est un détail.
Maintenant place au code. Dans le dossier /www/ de notre serveur (local ici), on crée un dossier appelé /custom-crawl/. Dans ce dossier on place 3 fichiers php.
- simple_html_dom.php que vous trouverez en ligne ici
- index.php (copiez y le code ci-dessous)
- mirror.php (copiez y le code ci-après)
Code à coller dans index.php
<?php /* How it Works ? Easy. You just need to change the custom parameters section of this file to tell the script : 1- The URL of website do you want to crawl 2- The tags you want to exclude from the HTML or include in the HTML. 3- The behaviour you want to work with: Exclusion behaviour ? or Inclusion behaviour ? Example 1 Let's says you want to INCLUDE in the HTML only what is inside the &amp;amp;amp;lt;article&amp;amp;amp;gt; tag, just use : $website = "https://www.www.example.com"; $selectors = array("article"); $behaviour("include"); Example 2 Let's says you want to EXCLUDE from the HTML all what is inside the &amp;amp;amp;lt;nav&amp;amp;amp;gt; and &amp;amp;amp;lt;footer&amp;amp;amp;gt; tags but also you want to exclude a &amp;amp;amp;lt;div&amp;amp;amp;gt; tag by its ID, just use $website = "https://www.www.example.com"; $selectors = array("nav,footer","div[id=secondary-nav]"); $behaviour("exclude"); */ // Custom Parameters $website = "https://www.example.com"; $behaviour = "exclude"; //remember if you need an inclusion behaviour use $behaviour = "include"; $selectors = array("nav","footer","aside"); // End of Custom Parameters // Do not change the following! include ('mirror.php'); include ('simple_html_dom.php'); $crawl = new mirror(); if(isset($_GET["uxx"])){ echo $crawl-&amp;amp;amp;gt;getCont($_GET["uxx"],$selectors,$behaviour,$_SERVER['HTTP_USER_AGENT']); } else { echo $crawl-&amp;amp;amp;gt;getCont($website,$selectors,$behaviour,$_SERVER['HTTP_USER_AGENT']); } ?>
Code à coller dans mirror.php
<?php class mirror { function __construct(){ } private function getIt($url,$ua){ $ch = curl_init(); curl_setopt($ch,CURLOPT_USERAGENT,$ua); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_REFERER, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); $response = array(); $response["html"] = curl_exec($ch); $response["info"] = curl_getinfo($ch); curl_close($ch); return $response; } public function getCont($url,$selectors='',$behaviour,$ua){ $parts = parse_url($url); $response = $this-&amp;amp;amp;gt;getIt($url,$ua); if($response["info"]["http_code"]!==0){ $html = str_get_html($response["html"]); if($selectors!=""){ $html = $this-&amp;amp;amp;gt;customHTML($html,$selectors,$behaviour); } $html = $this-&amp;amp;amp;gt;updateHref($html,$parts["scheme"],$parts["host"]); $html-&amp;amp;amp;gt;save(); return $html; } return $response["html"]; } private function customHTML($html,$selectors,$behaviour){ if($behaviour=="exclude"){ foreach($selectors as $tag){ foreach($html-&amp;amp;amp;gt;find($tag) as $tag){ $tag-&amp;amp;amp;gt;outertext = ""; } } } else if($behaviour=="include"){ $output = ""; array_push($selectors,"script"); foreach($selectors as $tag){ foreach($html-&amp;amp;amp;gt;find($tag) as $tag){ $output.= $tag-&amp;amp;amp;gt;outertext; } } $head = $html-&amp;amp;amp;gt;find("head",0)-&amp;amp;amp;gt;outertext; $output = "&amp;amp;amp;lt;html&amp;amp;amp;gt;".$head."&amp;amp;amp;lt;body&amp;amp;amp;gt;".$output."&amp;amp;amp;lt;/body&amp;amp;amp;gt;&amp;amp;amp;lt;/html&amp;amp;amp;gt;"; $html = str_get_html($output); } return $html; } private function updateHref($html,$scheme,$host){ foreach ($html-&amp;amp;amp;gt;find('a') as $link){ $link-&amp;amp;amp;gt;href = preg_replace("#^/.*#",$scheme."://".$host."/",$link-&amp;amp;amp;gt;href); $link-&amp;amp;amp;gt;href = preg_replace("#^".$scheme."://".$host."/.*#","?uxx=".$link-&amp;amp;amp;gt;href,$link-&amp;amp;amp;gt;href); } return $html; } } ?>
Une fois les fichiers installés dans le dossier custom-crawl il ne reste plus qu’à ouvrir ScreamingFrog et à crawler le site http://localhost/custom-crawl.
C’est tout pour cette petite astuce SEO, en espérant qu’elle vous soit utile.
Salut Walid, oui je reconnais les rouages de ta précédente solution (rediriger le jus de screaming frog via un routing localhost).
J’ai beaucoup de chantiers R&D en SEO (sémantique, maillage, crawling, etc), et le crawling raisonnable en fait partie. Je cherche à créer une solution qui permette de s’adapter à tous les sites sans avoir à hacker manuellement des composants par un ciblage du DOM comme tu le proposes ici.
Comme Frederic Laudet, j’avais imaginé un angle statistique avec un pré-audit des backlinks pour simplement kicker les backlinks sitewise, c-a-d ceux présents à plus de 90% dans les pages du site.
Au final, je pense que je vais m’orienter sur un dev polymorphe qui va choisir la meilleure solution de filtrage en fonction du cas de figure (si le site est html5 c’est facile car normé w3c), si le site n’y est pas on fonctionne à la déduction.
Hello Sébastien,
Franchement quand tu crawles un site pour un audit t’es obligé de custom un peu en fonction du site. Par exemple pour extraire de la data et segmenter le site durant le crawl, je trouve pas cela irraisonnable.
Je ne peux pas en dire plus par contre j’espère que cela te mettra la puce à l’oreille, attends avant de partir sur ton dev polymorphe car quelque chose arrive très bientôt.
Merci! Je teste ça car c’est exactement ce que je recherchais!
Super Kad, alors tu peux me faire un lien vers mon blog, c’est cool 🙂
Top merci walid pour l information et le code qui va avec
Je t’en prie Nicolas ça me fait plaisir ! Sinon dis moi Nico j’aime bien ton site, tu me fais un lien ?
Je viens de voir ton commentaire en checkant mes visiteurs en “referral” dans GA 😉
On peut s’arranger si tu veux si mon lien NF devient DF … (ici ou ailleurs )
Un grand merci pour ce “hack” et pour ces scripts !
Très pratique.
Pour les autres, attention il se peut que cela ne fonctionne pas sur certaines pages trop grosses. Ca vous donnera une erreur PHP à l’écran.
Il faut juste jouer avec la variable define(‘MAX_FILE_SIZE’, 600000) du fichier simple_html_dom.php et mettre beaucoup plus de “size”.