Script pour détecter le duplicate sur Google

WRInaute impliqué
Salut,

Bon, après mes post sur la façon de gérer le DC avec le droit, en voici un pour vous filer un script fait maison pour détecter du mieux possible le DC d'un texte dans l'index de GG.

Les critiques sont les plus que bienvenue.

... et s'il vous plait et que vous l'utilisez, un petit lien vers mon site ( http://www.an1000.org ) se sera cool, même si c'est loin d'être obligatoire. ;-)

Code:
<?php
//*****************************************************************
// La recherche exacte (entre guillemet) d'un texte sur google
// ne donnant pas les mêmes réponses qu'en passant par l'Ajax Google API,
// on utilise les deux.
//
//La recherche direct entre guillemet permet de récupérer les sites
// dont le duplicate content et complet. (limité à 10 résultats)
// L'utilisation de l'API permet de trouver le duplicate content partiel
// sans parser de pages de résultats.
//
//L'API ne permet que 100 requête par jour. Au dela il faut payer
//http://code.google.com/intl/fr/apis/customsearch/v1/overview.html#Pricing
//
//A vous de l'intégrer directement à vos site avec récupération des textes
// depuis vos bdd.
//
//Ca vous plait ? Bah faites moi un lien : http://www.an1000.org/
//*****************************************************************

header("Content-Type: text/html; charset=UTF-8");

if(isset($_POST['text_origin']))
	{
		$text_origin = stripslashes($_POST['text_origin']);

		// Détection en parse direct sur la requête exacte (entre guillemet)
		$url_parse = "https://www.google.fr/search?q=".urlencode('"'.$text_origin.'"')."&hl=fr&prmd=ivns&filter=0";

		if ($text_origin)// Récupération des données
			{
				$fp = fopen($url_parse,"r");// On parse la page
				if ($fp != FALSE)
					{
						while (!feof($fp))
							{
								$body .= fgets($fp, 4096);
							}
					}

				if(strpos($body, 'yellow_warning.gif') == '')// On vérifie si des résultats existent
					{
						if(strpos($body, '<h3 class="r"><a href="http://') != '')//On vérifie que les limiteurs existent
							{
								preg_match_all('#<h3 class="r"><a href="http://(.*)"#Uis', $body, $listing);// On extrait les url
								$nb_res = sizeof($listing[1]);// Comptage des tubes de $listing
								$url_DC = "<h2>Pages plagiant le texte</h2><table border=0>";
								for ($i=0; $i < $nb_res; $i++)
									{
										$url_DC.= "<tr><td style=\"width:50px;text-align:right;color:red;font-weight:bold;\">100,00%</td><td style=\"width:10px;\"></td><td><a href=\"http://".$listing[1][$i]."\">".$listing[1][$i]."</a></td></tr>";
									}
							}
						else
							{
								$nook_code = "Google a modifié son code source. L'expression réglière du preg_match_all doit être modifié !";
							}
					}

				if ($fp != FALSE){fclose($fp);}

				if (!isset($listing))
					{
						$listing[1][0] = "no-url";
						$url_DC = "<h2>Pages plagiant le texte</h2><table border=0>";
					}

				for ($boucle=0;$boucle<=10;$boucle++)
					{
						$start = $boucle*8;

						$url = "http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=".urlencode($text_origin)."&start=".$start."&rsz=large";
						$ch = curl_init();
						curl_setopt($ch, CURLOPT_URL, $url);
						curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
						//curl_setopt($ch, CURLOPT_REFERER, "http://www.castlemaniac.com/");
						$body = curl_exec($ch);
						curl_close($ch);

						$json = json_decode($body, true);// Tableau associatif.

						$nb_results_json = sizeof($json['responseData']['results']);// Nb de tube dans "results"
						for ($i=0; $i < $nb_results_json; $i++)// Extraction "content"
								{
									$content = $json['responseData']['results'][$i]['content'];
									$url_page_DC = str_replace("http://", "", $json['responseData']['results'][$i]['url']);
									
									if(!in_array($url_page_DC, $listing[1]))
										{
											//Traitement de "content"
											$content_origin = strip_tags($content);// Suppression des tags <b>
											$content_origin = preg_replace('#[.]#', '', $content_origin);// Suppression des .
											$content_origin = preg_replace('#[\s]+#', ' ', $content_origin);// Suppression des espaces multiples
											$content_origin = preg_replace('#^[\s]|[\s]$#','',$content_origin);// Suppression des espaces en début et fin de chaine
											$nb_word = explode(" ", $content_origin);// Mise des mots dans un tableau
											$nb_word_content_origin = sizeof($nb_word);// Comptage des mots
											
											// Traitement du texte en gras de "content"
											$text_bold = "";
											preg_match_all('#<b>(.*)</b>#Uis', $content, $bold);// Récupération du texte en gras
											$nb_result_bold = sizeof($bold[1]);// Nombre de tube dans $bold
												for ($j=0; $j < $nb_result_bold; $j++)// Mise en commun des tubes et nettoyage
													{
														$bold[1][$j] = preg_replace('#[.]#', '', $bold[1][$j]);// Suppression des .
														if (!empty($bold[1][$j]))$text_bold.= $bold[1][$j]." ";//Mise des résultat dans une seule variable
													}
											$text_bold = preg_replace('#[\s]+#', ' ', $text_bold);// Suppression des espaces multiples
											$text_bold = preg_replace('#^[\s]|[\s]$#','',$text_bold);// Suppression des espaces en début et fin de chaine
											$nb_word = explode(" ", $text_bold);// Mise des mots dans un tableau
											$nb_word_text_bold = sizeof($nb_word);// Comptage des mots

											$taux = round(($nb_word_text_bold*100)/$nb_word_content_origin,2);
											
											$tab_url_DC_partiel[$url_page_DC] = $taux;
										}
								}
						if ($nb_results_json < 8)break;// Limitation des requêtes si réponse vide.
					}
				arsort($tab_url_DC_partiel, SORT_NUMERIC);// Classement décroissant du taux
				foreach($tab_url_DC_partiel as $key=>$val)
					{
						if ($val == 100)$style = "color:red;font-weight:bold;";// Style du tableau
						elseif ($val < 100 && $val >= 50)$style = "color:red;";// Style du tableau
						else $style ="";// Style du tableau
						$val = number_format($val, 2, ',', ' ');// Mise ne forme du taux
						$url_DC.= "<tr><td style=\"width:50px;text-align:right;".$style."\">".$val."%</td><td style=\"width:10px;\"></td><td><a href=\"http://".$key."\">".$key."</a></td></tr>";
					}
				$url_DC.= "</table>";
			}
	}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<form action="" method="post">
	<label>Phrase test :</label><br />
	<input type="text" name="text_origin" />
	<input type="submit" name="submit" value="Ok" />
</form>
<?php
if(isset($_POST['text_origin']))
	{
	?>
		<h1 style="text-align:center;">Détection du DC dans l'index Google</h1>
		 <cite>Texte à identifier</cite><blockquote style="padding:5px;margin:10px;border:1px red dotted;background:aliceblue;font-weight:bold;"><?php echo $text_origin; ?></blockquote>
		 <?php if (!empty($nook_code))// Alerte
			{
			?>
				<div style="text-align:center;padding:5px;margin:10px;border:1px red solid;background:aliceblue;font-weight:bold;font-color:red;"><?php echo $nook_code; ?></div>
			<?php
			}
		?>
		 <?php echo $url_DC; // Affichage tableau  ?>
	<?php
	}
	?>
</body>
</html>
 
WRInaute accro
ça n'a rien à voir, mais je voulais te féliciter pour ton site, qui m'a beaucoup intéressé. (ça manque juste un peu de G. Duby..)
 
WRInaute impliqué
... y aurait tellement de chose à dire avec lui que j'aurais plus le temps de rien faire ... :)
 
WRInaute occasionnel
Salut Dolph.

Je pense tester ton appli dès demain et je ne manquerais de créer un lien vers ton site ;)

T'en que j'y suis : tu veux quoi comme ancre ? :)
 
WRInaute impliqué
Pour l'ancre, je te laisse regarder le site et mettre celle qui te semble la mieux.
Ca évite que je file tout le temps la même. ;-)
 
WRInaute occasionnel
vi sympa ton site. Juste une ptite remarque la première image sur ta page accueil le texte en dessous dépasse légerement de la photo sous firefox... mais autrement joli boulot...
en tout cas merci pour le script ça pourra aider certain.
 
WRInaute impliqué
Ah ?
Pas chez moi ni sur FF, ni sur IE, ni sur chrome.
Bon, je vais réduire un peu le texte.
 
WRInaute accro
merci pour ce partage :)

A préciser :
le probleme de cette api c'est que l'on ne peut pas préciser le pays et la langue, ce qui fausse les résultats
 
WRInaute accro
Merci pour cette contribution, Dolph.
Je vais la mettre au banc d'essai de mon backoffice V4, et si elle s'avère d'intérêt, on ne se contentera pas d'un backlink ;)

PS: bon retour sur WRI ;) :roll:
 
WRInaute impliqué
KOogar a dit:
merci pour ce partage :)

A préciser :
le probleme de cette api c'est que l'on ne peut pas préciser le pays et la langue, ce qui fausse les résultats
Ah savoir si on prend la version payante (non limité en nb de requête) a t-on droit à des option supplémentaire.

Bon, je suis en train de l'adapté à mon site.
J'ai pas de cron, donc, appel depuis a page d'accueil.
Vérif via une table de temp si le script a déjà été utilisé dans les x dernières heures (pour limité les requêtes par 24h)
Récup du texte de l'article à tester.
Suppression de tout ce qui est inutile, citation, titre, balises...
On prélève au hasard 1 phrase d'au moins 10 mots dans chaque tiers de texte.

On envoie la moulinette.

On récupère url origin, url DC, taux DC, phrase testée et on met tout ça dans une table.
On vérifie si l'hébergeur correspond à un mail de notre table domaine/mailreport (engros, une liste de mail des plateformes de blog pourris :)).
Si oui, on envoi direct à l'hébergeur le mail de demande de suppression.

Dans la partie admin, on gère au cas par cas.

Dés que c'est fini (demain, surement) je poste le nouveau code.
 
WRInaute occasionnel
Bon, je t'avais dis que je testerais.

Par manque de temps, je n'ai pas encore eu les moyens de le faire mais comme je n'ai qu'une parole, promis je le fais incessamment sous peu ! ;)

GG 4 ur first ! :D
 
WRInaute accro
Dolph a dit:
KOogar a dit:
le probleme de cette api c'est que l'on ne peut pas préciser le pays et la langue, ce qui fausse les résultats
Ah savoir si on prend la version payante (non limité en nb de requête) a t-on droit à des option supplémentaire.

avec l'api adsense et map oui mais pas sur la search, on a seulement droit a plus de queries si l'on paye
 
WRInaute occasionnel
Salut Dolph !

Comme promis, je viens de prendre en main ton appli et voici déjà mes retours :
- En dé-zippant l'appli depuis phpsources, j'ai un problème d'encodage car le jeu de caractères FR (accents, cédille, etc...) est mal encodé, est-ce normal d'après toi ?
- cela n'engage que moi, mais j'aurais préféré que tu mettes une partie "paramétrage" avec les variables globales tel que l'url du site à modifier.
- Ensuite, un petit fichier ".sql" reprenant toutes les requêtes d'un seul coup fournit avec le fichier php n'aurait pas été de refus.
- Et enfin, pourquoi pas un fichier "install" à part récapitulant l'installation étape par étape, voir aussi un fichier "changelog" au cas où tu génères plusieurs versions suivant les débugs.

Allez je passe à l'installation et reviendrait vers toi pour te faire mon retour d'expérience quand j'aurais tester l'appli ! ;)

A tout !
 
WRInaute impliqué
Un script pret à l'emploi, en quelque sorte.
Pourquoi pas.

Sinon, moi, j'ai pas de soucis d'encodage...
Mes table sont en utf8 et le script tourne en utf8. Si les texte que tu y met n'y sont pas, c'est peut-être la raison.
 
WRInaute occasionnel
Dolph a dit:
Sinon, moi, j'ai pas de soucis d'encodage...
Mes table sont en utf8 et le script tourne en utf8. Si les texte que tu y met n'y sont pas, c'est peut-être la raison.
Attention, je ne te parle pas de la bdd mais directement des commentaires du fichier php ;)
 
WRInaute occasionnel
Dolph a dit:
bah ça, faut voir chez phpsource alors. ;-)
C'est eux qui créé le zip.
D'ac !

Bon, j'ai encore un souci car ce script a été créé pour ton environnement de bdd et il y a des tables que tu n'as pas définit comme "ma_table_article", est-ce volontaire ? :)
 
WRInaute occasionnel
Bon, je ne peux plus éditer mon post ci-dessus ...

Autre chose :
Code:
CREATE TABLE IF NOT EXISTS ma_table_mail_hebergeur (
Id int(11) unsigned NOT NULL auto_increment,
Domaine varchar(255) NOT NULL,
Mail varchar(255) NOT NULL,
PRIMARY KEY  (Plagiat_Mail_Id)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

#1072 - Key column 'Plagiat_Mail_Id' doesn't exist in table
Problème de clé primaire : le champs Plagiat_Mail_Id n'existe pas dans la bdd.
 
WRInaute impliqué
exact, je corrige ça.
PRIMARY KEY (Id)

Et en effet, c'est fait pour ma ndd donc, faut mettre à sa sauce.
 
WRInaute impliqué
Là, il est en place sur un site et je regarde le fonctionnement et les améliorations possibles.

Au final, il devra être portable pour une installe sur la totalité des sites que je gère, donc, il y se devra d'être totalement dépendant de tables d'origine du site.

D'aileurs, sur phpsources, il est inscrit en "bout de code", c'est pas pour rien. ;-)
 
WRInaute occasionnel
Dolph a dit:
D'aileurs, sur phpsources, il est inscrit en "bout de code", c'est pas pour rien. ;-)
Wé je me doute bien :) même si je n'avais pas remarqué le "bout de code". :D

Sinon ya tjs la version light disponible dans ton 1er message de ce topic ...

Quoi qu'il en soit, je vais le remanier pour gérer ma fonction d'appel à la connexion, le CRON et liée la table de contenu de la bdd de mon cms ! 8)
 
WRInaute occasionnel
Salut Dolph !

Sauf erreur de ma part, je pense qu'il y a une petite coquille au niveau des champs de ma_table_article : "texte_article url_article" au lieu "texte_article, url_article". Manque juste la petite virgule qui va bien :)

Sur ce, je continue à interfacer ton appli ;)

EDIT :
Autre question -
En fin de code tu as "UPDATE ma_table_article SET plagiat = '1'" : est-ce que ce champs est en fait "Verif_plagiat" ?
 
WRInaute occasionnel
lunicrea a dit:
EDIT :
Autre question -
En fin de code tu as "UPDATE ma_table_article SET plagiat = '1'" : est-ce que ce champs est en fait "Verif_plagiat" ?
Bon, j'ai eu réponse à ma question en me concentrant sur le code :) C'est bien le champs Verif_plagiat qui est appelé.

Autre question même si je pense que j'ai déjà la réponse :
Est-ce normal d'obtenir des warnings comme ci-dessous ?
Code:
Warning: fopen() [function.fopen]: HTTP request failed! HTTP/1.0 503 Service Unavailable

Je pense que Google doit avoir blacklisté le mutu d'OVH et donc il ne répond pas ... Tu confirmes Dolph ? :roll:
 
WRInaute impliqué
Ca doit être ça...

GG n'aime pas l'automatisation, donc, faut exécuter la page pas trop souvent. ;-)
Moi, je la lance 2x par jour.
 
WRInaute occasionnel
Dolph a dit:
Ca doit être ça...

GG n'aime pas l'automatisation, donc, faut exécuter la page pas trop souvent. ;-)
Moi, je la lance 2x par jour.
Ok ! Bonne nouvelle cela dit, car c'était le dernier point que j'avais à régler ;)

Du coup, je vais mettre ton lien sur notre site comme convenu ! 8)
Je te MP le lien dès qqu c'est fait, tu me diras si ça te conviens.

Et ne manquerais pas de te tenir au courant des évolutions, bizarreries en tout genre...

Bonne fin de journée ! :mrgreen:
 
Discussions similaires
Haut