Script PHP: chasse aux voleurs de contenus et au duplicate content

écrit par Aymeric

duplicate contentIl y a quelques jours, Sylvain alias @axenetwit nous faisait remarquer dans un tweet qu'une partie de son contenu avait été volée par une agence aux pratiques douteuses. Oui, le contenu dupliqué est une plaie. Qui n'a jamais eu peur de voir ses pages toutes belles et bien optimisées passer à la trappe dans l'index secondaire de Google? Autant on a les moyens de lutter contre le duplicate content interne, autant les sites qui copient/collent vos contenu sont plus difficiles à gérer. Petite recommandation tout de même, éviter de proposer les flux RSS complets de vos blogs par exemple (extrait/excerpt seulement), vous compliquerez la tâche des copieurs...

Halte au vol de contenu

Ayant déjà eu à faire à des addicts du plagiat et à cours d'idée pour un prochain script codé avec mes pieds, je me suis dit que le concept de mon prochain article était tout trouvé! Alors je me suis lancé dans un script qui récupère les URL des pages contenant une phrase spécifique (d'un de vos articles par exemple) dans les pages de résultats de Google.
Ensuite, il va lister d'une manière plus claire que les SERP toutes ces pages avec l'adresse IP de chaque domaine contenant le texte plagié pour déceler un éventuel plagiaire multi-domaines et un lien vers le Whois en espérant que le propriétaire n'ait pas masqué ses données Whois - Prénom, Nom, Email qui nous intéressent en l'occurence - pour lui taper sur les doigts.
Le but ultime de cette automatisation? Générer le texte des mails destinés à ces voleurs de manière automatisée.
Vade retro satanas !

Script PanPan féfesses voleur!

Créez un fichier vilain.php avec le code ci-dessous. Inutile d'envoyer un mail au propriétaire du domaines facebook.com ou free.fr si le plagiaire a copié votre texte sur une page Facebook ou un site perso de Free 😉
Prenez une partie de phrase d'un article de votre site (130 caractères maximum) et de préférence en coeur d'article pour éviter de faire remonter digg-like et autres sites lisant vos flux RSS.

<html>
<head>
<title>Script de recherche des voleurs de contenus</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
<script type="text/javascript">
/*http://www.sohtanaka.com/web-design/inline-modal-window-w-css-and-jquery/*/
$(document).ready(function(){
	$('a.poplight[href^=#]').click(function() {
		var popID = $(this).attr('rel');
		var popURL = $(this).attr('href');
		var query= popURL.split('?');
		var dim= query[1].split('&');
		var popWidth = dim[0].split('=')[1];
		$('#' + popID).fadeIn().css({ 'width': Number( popWidth ) }).prepend('<div style="float:right;"><a href="#" class="close">Fermer</a></div><br />');
		var popMargTop = ($('#' + popID).height() +80) / 2;
		var popMargLeft = ($('#' + popID).width() + 80) / 2;
		$('#' + popID).css({ 
			'margin-top' : -popMargTop,
			'margin-left' : -popMargLeft
		});
		$('body').append('<div id="fade"></div>');
		$('#fade').css({'filter' : 'alpha(opacity=80)'}).fadeIn(); 
		return false;
	});
	$('a.close, #fade').live('click', function() { 
	  	$('#fade , .popup_block').fadeOut(function() {
			$('#fade, a.close').remove();  
	});
		return false;
	});
});
</script>
<style type="text/css">
body{font-family:Arial,Helvetica;font-size:1.1em;}
table {
    border-spacing: 0px;
    background: #E9E9F3;
    border: 0.5em solid #E9E9F3;
}
table th {
    text-align: left;
    font-weight: normal;
    padding: 0.5em 0.5em;
    border: 0px;
    border-bottom: 1px solid #9999AA;
}
table td {
    text-align: left;
    border: 0px;
    border-bottom: 1px solid #9999AA;
    border-left: 1px solid #9999AA;
    padding: 0.5em 0.5em;
}
table thead th {
    text-align: center;
    font-weight: bold;
    color: #6C6C9A;
    border-left: 1px solid #9999AA;
}
table th.corner {
    text-align: center;
    border-left: 0px;
}
table tr.odd {
    background: #F6F4E4;
}
hr{
margin:24px;
}
#fade {
	display: none;
	background: #000;
	position: fixed; left: 0; top: 0;
	width: 100%; height: 100%;
	opacity: .80;
	z-index: 9999;
}
.popup_block{
	display: none;
	background: #fff;
	padding: 20px;
	border: 10px solid #ddd;
	float: left;
	font-size: 1em;
	position: fixed;
	top: 50%; left: 50%;
	z-index: 99999;
	-webkit-box-shadow: 0px 0px 20px #000;
	-moz-box-shadow: 0px 0px 20px #000;
	box-shadow: 0px 0px 20px #000;
	-webkit-border-radius: 10px;
	-moz-border-radius: 10px;
	border-radius: 10px;
}
img.btn_close {
	float: right;
	margin: -55px -55px 0 0;
}
*html #fade {
	position: absolute;
}
*html .popup_block {
	position: absolute;
}
</style>
</head>
<body>
<?php

function scrapounet ($domaine,$phrase)
{
        $schema = '`<h3\s*class="r">\s*<a[^<>]*href="http://([^/]*)/([^<>]*)?"[^<>]*>(.*)</a>\s*</h3>`siU';
        $export='Domaine'."\t".'URL'."\t".'IP'."\n";$requete = '';$voleur = '';$deduplicate='';$k=0;
//	$phrase = '"'.str_replace(' ','+',$_POST["phrase"]).'"';
	$query = utf8_encode('http://www.google.fr/search?q=-site:'.$domaine.$requete.'+"'.str_replace(' ','+',$_POST["phrase"]).'"&hl=fr&ie=utf-8&oe=utf-8&aq=t&num=100');
        $useragent='Opera/9.63 (Windows NT 5.1; U; fr) Presto/2.1.1';
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
        curl_setopt($ch, CURLOPT_URL, $query);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
        $result = curl_exec ($ch);
        preg_match_all($schema, $result, $matches);
		for ($j=0; $j<count ($matches[1]); $j++) {
			$voleur = str_replace('https://','',$matches[1][$j]);
	                if (!stristr($deduplicate,';'.$voleur.';')) {
			$k++;
			$ip=gethostbyname($voleur);
			if ($k % 2) $odd=' class="odd"';else $odd='';
			$mailcontent = '<u>Sujet:</u> Respect du droit d\'auteur relatif au site '.$domaine.'<br /><br />';
			$mailcontent .= 'Monsieur,<br /><br />';
			$mailcontent .= 'Nous venons de d&eacute;couvrir votre site internet '.$voleur.'. Bien qu\'il ait retenu notre attention, nous avons eu la d&eacute;sagr&eacute;able surprise de constater que vous repreniez in extenso certains contenus r&eacute;dactionnels directement issus de notre siteweb '.$domaine.':<br /> Page concern&eacute;e: http://'.$voleur.'/'.$matches[2][$j].'<br /><br />';
			$mailcontent .= 'Vous comprenez bien que cette situation est pour nous intol&eacute;rable. Nous sommes contraints de vous rappeler que, selon le code de la propri&eacute;t&eacute; intellectuelle (http://www.legifrance.gouv.fr/affichCode.do?cidTexte=LEGITEXT000006069414&dateTexte=20080911), il est interdit de reproduire librement un texte, une image, un son, sans le consentement de son auteur (article L.122-4) et que les textes mis en ligne sur le site '.$domaine.', sauf mentions particuli&egrave;res, sont la propri&eacute;t&eacute; intellectuelle et l&eacute;gale de son auteur.<br /><br />';
			$mailcontent .= 'Nous vous prions donc de retirer de votre site '.$voleur.' les articles directement copi&eacute;s-coll&eacute;s de notre site '.$domaine.'. Nous comptons sur votre intervention dans les meilleurs d&eacute;lais.<br /><br />Dans cette attente, veuillez recevoir l\'expression de mes cordiales salutations<br /><br />';
	                $domaines .= '<tr'.$odd.'><th><a href="http://'.$voleur.'/'.$matches[2][$j].'" target="_blank">http://'.$voleur.'/'.substr($matches[2][$j],0,60).'</a></th><td><a href="http://whois.domaintools.com/'.$voleur.'" target="_blank">'.$voleur.'</a></td><td>'.$ip.'</td><td><a href="#?w=700" rel="mailcontent'.$k.'" class="poplight">Email</a></td></tr>';
	                $export .= $voleur."\t".'http://'.$voleur.'/'.$matches[2][$j]."\t".$ip."\n";
			$fulldiv .= '<div id="mailcontent'.$k.'" class="popup_block">'.$mailcontent.'</div>';
			$deduplicate .= ';'.$voleur.';';$mailcontent='';
			}
                }
        if ($k!=0 && $k<90){
	file_put_contents($domaine.'.txt',$export);
	$output = '<u>Requ&ecirc;te effectu&eacute;e:</u> <br />'.utf8_decode($query).'<br /><br />';
	$output .= 'T&eacute;l&eacutecharger l\'export (clic droit): <a href="'.$domaine.'.txt">'.$domaine.'.txt</a><br /><hr>';
        $output .= '<u>Liste des '.$k.' voleurs de contenus:</u><br /><br /><table><thead><tr><th class="corner">URL du contenu dupliqu&eacute;</th><th>Whois si NDD appartient au voleur</th><th>Adresse IP</th><th>Texte &agrave; envoyer</th></tr></thead>'.$domaines.'</table><hr>';
	$output .= 'Faire une nouvelle recherche de voleur de contenu: <a href="'.$_SERVER["REQUEST_URI"].'">'.$_SERVER["REQUEST_URI"].'</a>';}
	else {
	$output = '<u>Requ&ecirc;te effectu&eacute;e:</u> <br />'.utf8_decode($query).'<br /><br />';
	$output .= 'Ouf! Votre contenu n\'a pas &eacute;t&eacute; r&eacute;cup&eacuter&eacute;e par un m&eacute;chant... Pas de contenu dupliqu&eacutee, YOUPEE :-)<br /><br />';
	$output .= 'Faire une nouvelle recherche de voleur de contenu: <a href="'.$_SERVER["REQUEST_URI"].'">'.$_SERVER["REQUEST_URI"].'</a></td></tr></table>';
	}
        return '<table width="900" align="center"><tr><td>'.$output.$fulldiv.'<br /><br /></td></tr></table>';
}
if (isset($_POST["domaine"]) && $_POST["domaine"]!='' && isset($_POST["phrase"]) && $_POST["phrase"]!='')
{
$dom = $_POST["domaine"];
print $output =  scrapounet ($dom,$phrase);
}
else {
?>
<table width="800" align="center">
<form method="post" action="<?print $_SERVER["REQUEST_URI"];?>" >
<tr><th>Votre nom de domaine:&nbsp;</th><td><input type="text" name="domaine" value="axe-net.fr"><br /></td></tr>
<tr><th>Phrase &agrave; trouver chez un vilain copieur:&nbsp;</th><td><textarea name="phrase" cols="70" rows="3" maxlength="130">La r&eacute;ussite de cette entreprise repose avant tout, sur l'&eacute;coute attentive de vos besoins en mati&egrave;re de communication et l'&eacute;tude de votre secteur d'activit&eacute;.</textarea><br />Max: 130 caract&egrave;res / si le dernier mot est coup&eacute; (copier/coller), supprimez-le.</td></tr>
<tr><th colspan="2"><input type="submit" value="Allons attraper ces plagiaires !"></th></tr>
</table>
</form>
<? } ?>
</body>
</html>

Edit du 23/11: Voici une deuxième version. Le script a été modifié par @Beunwa qui a fiabilisé le code et l'a rendu plus facilement maintenable : les regexp ont été remplacées par Xpath par exemple car la regexp ci-dessus ne fonctionne plus. J'ai laissé ses commentaires, autant que ses astuces vous servent! Un grand merci à lui 🙂

<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Script de recherche des voleurs de contenus</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
<script type="text/javascript">
/*http://www.sohtanaka.com/web-design/inline-modal-window-w-css-and-jquery/*/
$(document).ready(function(){
	$('a.poplight').click(function() {
		var popID = $(this).attr('rel');
		var popURL = $(this).attr('href');
		var query= popURL.split('?');
		var dim= query[1].split('&');
		var popWidth = dim[0].split('=')[1];
		$('#' + popID).fadeIn().css({ 'width': Number( popWidth ) }).prepend('<div style="float:right;"><a href="#" class="close">Fermer</a></div><br />');
		var popMargTop = ($('#' + popID).height() +80) / 2;
		var popMargLeft = ($('#' + popID).width() + 80) / 2;
		$('#' + popID).css({
			'margin-top' : -popMargTop,
			'margin-left' : -popMargLeft
		});
		$('body').append('<div id="fade"></div>');
		$('#fade').css({'filter' : 'alpha(opacity=80)'}).fadeIn();
		return false;
	});
	$('a.close, #fade').live('click', function() {
	  	$('#fade , .popup_block').fadeOut(function() {
			$('#fade, a.close').remove();
	});
		return false;
	});
});
</script>
<style type="text/css">
body{font-family:Arial,Helvetica;font-size:1.1em;}
table {
    border-spacing: 0px;
    background: #E9E9F3;
    border: 0.5em solid #E9E9F3;
}
table th {
    text-align: left;
    font-weight: normal;
    padding: 0.5em 0.5em;
    border: 0px;
    border-bottom: 1px solid #9999AA;
}
table td {
    text-align: left;
    border: 0px;
    border-bottom: 1px solid #9999AA;
    border-left: 1px solid #9999AA;
    padding: 0.5em 0.5em;
}
table thead th {
    text-align: center;
    font-weight: bold;
    color: #6C6C9A;
    border-left: 1px solid #9999AA;
}
table th.corner {
    text-align: center;
    border-left: 0px;
}
table tr.odd {
    background: #F6F4E4;
}
hr{
margin:24px;
}
#fade {
	display: none;
	background: #000;
	position: fixed; left: 0; top: 0;
	width: 100%; height: 100%;
	opacity: .80;
	z-index: 9999;
}
.popup_block{
	display: none;
	background: #fff;
	padding: 20px;
	border: 10px solid #ddd;
	float: left;
	font-size: 1em;
	position: fixed;
	top: 50%; left: 50%;
	z-index: 99999;
	-webkit-box-shadow: 0px 0px 20px #000;
	-moz-box-shadow: 0px 0px 20px #000;
	box-shadow: 0px 0px 20px #000;
	-webkit-border-radius: 10px;
	-moz-border-radius: 10px;
	border-radius: 10px;
}
img.btn_close {
	float: right;
	margin: -55px -55px 0 0;
}
*html #fade {
	position: absolute;
}
*html .popup_block {
	position: absolute;
}
</style>
</head>
<body>
<?php
//necessite php5
function getDomValue($html, $path){
	$dom = new DOMDocument();
	@$dom->loadHTML($html);
	$xp = new DOMXPath($dom);
	$nodeList = $xp->query($path);
	$tab = array();
	foreach($nodeList as $domElement){
		$tab[] = $domElement->nodeValue;
	}
	return $tab;
}

function scrapounet ($domaine,$phrase)
{
        $export='Domaine'."\t".'URL'."\t".'IP'."\n";$requete = '';$voleur = '';$deduplicate='';$k=0;
        
        /*
         * J'ai utilisé urlencode pour construire la requete, 
         * cette fonction est faite pour ca et marche mieux que 
         * simplement remplacer les espaces par des accents.
         * J'ai supprimé l'utf8_encode qui provoque de mauvais résultats
         * (J'ai ajouté l'encodage utf8 dans le header du document 
         * et j'ai sauvé ce fichier en utf8)         
         */
          
		$query = 'http://www.google.fr/search?q=-site:'.$domaine.$requete.'+"'.urlencode($_POST["phrase"]).'"&hl=fr&ie=utf-8&oe=utf-8&aq=t&num=100';
        $useragent='Opera/9.63 (Windows NT 5.1; U; fr) Presto/2.1.1';
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
        curl_setopt($ch, CURLOPT_URL, $query);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
        $result = curl_exec ($ch);
        
        /*
         * on utilise xpath a la place des regex car il est bien plus 
         * fiable, adapté et plus facilement maintenable que les regexs.
         * 
         * Si google met a jour son format de serp il suffira juste 
         * d'ouvrir firefox avec l'extension firepath (par exemple)
         * de récuperer le nouveau xpath de l'url des sites
         * et de mettre a jour la variable $path ci dessous en conséquence.
         */ 
         
         $path = '//h3[@class="r"]/a/@href';
        $matches[1] = getDomValue($result, $path);
        //echo $result;
        //print_r($matches[1]);
		for ($j=0; $j<count ($matches[1]); $j++) {
			
			/*
			 * On utilise la fonction parse_url qui permet d'eclater une url
			 * en host / path / query
			 */ 
			 
			 $urlvoleur =  $matches[1][$j];
			 $tmp = parse_url($urlvoleur);
			 $voleur = $tmp['host'];
			
	                if (!stristr($deduplicate, ';'.$voleur.';')) {						
			$k++;
			$ip=gethostbyname($voleur);
			if ($k % 2) $odd=' class="odd"';else $odd='';
			$mailcontent = '<u>Sujet:</u> Respect du droit d\'auteur relatif au site '.$domaine.'<br /><br />';
			$mailcontent .= 'Monsieur,<br /><br />';
			$mailcontent .= 'Nous venons de d&eacute;couvrir votre site internet '.$voleur.'. Bien qu\'il ait retenu notre attention, nous avons eu la d&eacute;sagr&eacute;able surprise de constater que vous repreniez in extenso certains contenus r&eacute;dactionnels directement issus de notre siteweb '.$domaine.':<br /> Page concern&eacute;e: http://'.$urlvoleur.'<br /><br />';
			$mailcontent .= 'Vous comprenez bien que cette situation est pour nous intol&eacute;rable. Nous sommes contraints de vous rappeler que, selon le code de la propri&eacute;t&eacute; intellectuelle (http://www.legifrance.gouv.fr/affichCode.do?cidTexte=LEGITEXT000006069414&dateTexte=20080911), il est interdit de reproduire librement un texte, une image, un son, sans le consentement de son auteur (article L.122-4) et que les textes mis en ligne sur le site '.$domaine.', sauf mentions particuli&egrave;res, sont la propri&eacute;t&eacute; intellectuelle et l&eacute;gale de son auteur.<br /><br />';
			$mailcontent .= 'Nous vous prions donc de retirer de votre site '.$voleur.' les articles directement copi&eacute;s-coll&eacute;s de notre site '.$domaine.'. Nous comptons sur votre intervention dans les meilleurs d&eacute;lais.<br /><br />Dans cette attente, veuillez recevoir l\'expression de mes cordiales salutations<br /><br />';
	                $domaines .= '<tr'.$odd.'><th><a href="'.$urlvoleur.'" target="_blank">'.$urlvoleur.'</a></th><td><a href="http://whois.domaintools.com/'.$voleur.'" target="_blank">'.$voleur.'</a></td><td>'.$ip.'</td><td><a href="#?w=700" rel="mailcontent'.$k.'" class="poplight">Email</a></td></tr>';
	                $export .= $voleur."\t".'http://'.$voleur.'/'.$matches[2][$j]."\t".$ip."\n";
			$fulldiv .= '<div id="mailcontent'.$k.'" class="popup_block">'.$mailcontent.'</div>';
			$deduplicate .= ';'.$voleur.';';$mailcontent='';
			}
                }
        if ($k!=0 && $k<90){
			file_put_contents($domaine.'.txt',$export);			
	$output = '<u>Requ&ecirc;te effectu&eacute;e:</u> <br />'.str_replace('+',' ',utf8_decode($query)).'<br /><br />';
	$output .= '<u>Extrait de texte recherch&eacute;e:</u> <br />"'.stripslashes($_POST["phrase"]).'"<br /><br />';
	$output .= 'T&eacute;l&eacutecharger l\'export (clic droit): <a href="'.$domaine.'.txt">'.$domaine.'.txt</a><br /><hr>';
    $output .= '<u>Liste des '.$k.' voleurs de contenus:</u><br /><br /><table><thead><tr><th class="corner">URL du contenu dupliqu&eacute;</th><th>Whois si NDD appartient au voleur</th><th>Adresse IP</th><th>Texte &agrave; envoyer</th></tr></thead>'.$domaines.'</table><hr>';
	$output .= 'Faire une nouvelle recherche de voleur de contenu: <a href="'.$_SERVER["REQUEST_URI"].'">'.$_SERVER["REQUEST_URI"].'</a>';}
	else {
	$output = '<u>Requ&ecirc;te effectu&eacute;e:</u> <br />'.str_replace('+',' ',utf8_decode($query)).'<br /><br />';
	$output .= '<u>Extrait de texte recherch&eacute;e:</u> <br />"'.stripslashes($_POST["phrase"]).'"<br /><br />';
	$output .= 'Ouf! Votre contenu n\'a pas &eacute;t&eacute; r&eacute;cup&eacuter&eacute;e par un m&eacute;chant... Pas de contenu dupliqu&eacutee, YOUPEE <img src="http://www.yapasdequoi.com/wp-includes/images/smilies/icon_smile.gif.pagespeed.ce.nuZG_6txEH.gif" alt=":-)" class="wp-smiley"> <br /><br />';
	$output .= 'Faire une nouvelle recherche de voleur de contenu: <a href="'.$_SERVER["REQUEST_URI"].'">'.$_SERVER["REQUEST_URI"].'</a></td></tr></table>';
	}
        return '<table width="900" align="center"><tr><td>'.$output.$fulldiv.'<br /><br /></td></tr></table>';
}
if (isset($_POST["domaine"]) && $_POST["domaine"]!='' && isset($_POST["phrase"]) && $_POST["phrase"]!='')
{
$dom = $_POST["domaine"];
print $output =  scrapounet ($dom,$phrase);
}
else {
?>
<table width="800" align="center">
<form method="post" action="<?print $_SERVER["REQUEST_URI"];?>" >
<tr><th>Votre nom de domaine:&nbsp;</th><td><input type="text" name="domaine" value="axe-net.fr"><br /></td></tr>
<tr><th>Phrase &agrave; trouver chez un vilain copieur:&nbsp;</th><td><textarea name="phrase" cols="70" rows="3" maxlength="130">La r&eacute;ussite de cette entreprise repose avant tout, sur l'&eacute;coute attentive de vos besoins en mati&egrave;re de communication et l'&eacute;tude de votre secteur d'activit&eacute;.</textarea><br />Max: 130 caract&egrave;res / si le dernier mot est coup&eacute; (copier/coller), supprimez-le.</td></tr>
<tr><th colspan="2"><input type="submit" value="Allons attraper ces plagiaires !"></th></tr>
</table>
</form>
<? } ?>
</body>
</html>

Si les plagiaires sont encore là...

Si jamais après ces échanges de mails, le plagiaire ne veut toujours pas coopérer, vous pouvez toujours faire appel à l'agence tous risques qui se fera un plaisir de lui régler son compte, ou utiliser le formulaire Google de Spam Report. A vous la domination des SERP!

Comment? j'ai utilisé une image sans l'autorisation de son auteur? euh, c'est juste le screenshot d'un film qui a déjà gagné assez d'argent 🙂

Articles relatifs au vol de contenu suceptibles de vous intéresser: , Plagiat, liste des voleurs de contenu chez Axe-net, Vol de contenu et duplicate content chez Axe-Net, Duplicate-Leaks, les nouveaux-zorros?

Tenez-vous informés des mises à jour en vous abonnant aux commentaires de cet article ou en suivant le topic dédié sur le forum Veille SEO. Toute proposition d'amélioration est la bienvenue, n'hésitez pas à retweeter si ça vous plait:-)

écrit dans Scripts SEO par Aymeric | 53 commentaires

53 commentaires "Script PHP: chasse aux voleurs de contenus et au duplicate content"