[PHP] Spamerkennung: %-Anteil und Dichte von Links im Text

jeko

Lounge-Member
Hallo zusammen,

Ich habe hier unten einen kleinen Algorithmus, der den prozentualen Anteil von URLs an einem gesamten Text und die Dichte der URLs errechnet.
Damit kann ermittelt werden, welcher Anteil vom Text an URLs geht und wieviel noch normaler Text ist. Weiter kann auch mit der durschnittlichen Dichte ermittelt werden, wie eng die Links zusammenstehen.

Brauch kann man das vielleicht als Teil eines Spamschutzes. Auf die Idee gekommen bin ich dadurch, dass in meinen Gästebüchern von diversen Spambots immer häufiger Einträge mit Linkanhäufungen zu Pillenverkäufern entstanden. Ist ziemlich mühsam die immer von Hand zu entfernen. Richtig genervt hats, als sie begannen mein nopaste zuzuspammen (nopaste.ch). Vielleicht hilfts dem einen oder anderen, ich find er funktioniert ganz gut (auf nopaste.ch noch nicht eingebaut :)).

PHP:
// Zeitmessung
function microtime_float()
{
   list($usec, $sec) = explode(" ", microtime());
   return ((float)$usec + (float)$sec);
}
$__time_start = microtime_float();

// Hier beginnt's
// Der Text
$text = 'SPAMAMSPSAM';

$urlregexp = "((ht|f)tp(s?)\:\/\/|~/|/)?([\w]+:\w+@)?([a-zA-Z]{1}([\w\-]+\.)+([\w]{2,5}))(:[\d]{1,5})?((/?\w+/)+|/?)(\w+\.[\w]{3,4})?((\?\w+=\w+)?(&\w+=\w+)*)?";
// regex by http://geekswithblogs.net/casualjim/archive/2005/12/01/61722.aspx

preg_match_all("%$urlregexp%i",$text,$links,PREG_OFFSET_CAPTURE);
$totalChars = strlen($text);
$totalLinks = count($links[0]);
$linkChars = 0;
$linkDensity = 0;
$lastLinkEnd = 0;

// echo $text."\n\n\n"; // Debug

if ($totalLinks == 0) die("Text contains no links.\n\n");

foreach($links[0] as $link) {
	$length = strlen($link[0]);
	$linkChars += $length;
	$linkDensity += $link[1] - $lastLinkEnd;
	$lastLinkEnd = $link[1] + $length;
}

$linkDensity += $totalChars - $lastLinkEnd;

$LinkPercentage = round($linkChars/$totalChars*100);
$LinkDensity = round($linkDensity/$totalLinks);

$time_end = microtime_float();

echo 'Percentage links: '.$LinkPercentage."%\n";
echo 'Average Link length: '.ceil($linkChars/$totalLinks)." Characters\n";
echo 'Average Link density: '.$LinkDensity." Characters\n";
echo 'Time needed: '.number_format($time_end - $__time_start,4)."s \n\n";

Der Algo muss natürlich an die eigenen Bedürfnisse angepasst werden. Dabei könnte man zum Beispiel Grenzwerte festlegen für den Prozentanteil an Links (z.B. maximal 30%, wenn höher -> Spam) und die Linkdichte (z.B. Mindestabstand der Links muss durchschnittlich 100 Zeichen betragen). Dann die Grenzwerte mit den Variablen $LinkPercentage und $LinkDensity abgleichen und man hat einen Pseudo-Spam-o-Meter.

Grüsse
jeko



Nachtrag: Ich spreche oben auch oft von Links. Tatsächlich sucht der Algo nach URLs und nicht nur nach Links. Der Grund, ist der, dass solche Spameinträge verschiedene Arten von Links enthalten (HTML-Links und Forenlinks div. Art) aber auch einfach nur Plain Text Links, also die URLs als solches. Ich habe mich daher auf die URLs erweitet, um so alle zu kriegen.
Beispieleinträge sind unter anderem hier zu finden: Spameintraege_auf_NoPaste.ch_-_Analyse.txt
 
Zuletzt bearbeitet:
Ist zwar schon lange her - Dein posting.
Frage trotzdem:
Inhaltsabfrage mit "preg_match" sollte doch genügen.
Warum daher so kompliziert?
 
Hallo Ron Wood,

Ich verstehe deine Frage leider nicht ganz - zum Einen das mit dem "kompliziert" (Was empfindest du als kompliziert?) und zum Anderen das mit preg_match; wie willst du denn mit preg_match alleine die obigen Kennzahlen ermitteln?

Grüsse
jeko
 
Zurück
Oben