• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

Webkataloge nach links/domains durchsuchen

Capi

New member
Hallo kennt jemmand ein Programm welches nach folgendem Schema arbeitet:

- verfolge interne links
- durchsuche die webseite nach links
- speichere externe links
- mache aus links die reinen domain-namen

Es gibt zwar Programme wie Xenu, nehmen aber viel zu viel Kapazitäten in Anspruch, sollte wirklich sein sehr simple aufgebauter Script sein.
 
Naja, das selber zu machen ist eigentlich nicht so schwer. Ich hab auch mal so was gemacht, für eine interne Suche auf meiner Seite. Hier der Code. Verfolgt die Links aber nur bis zur 2. Dimension und speichert die Contents dann inner DB.

PHP:
<?php
/* (C) 2005 Dominique Sandoz, jeko@gmx.ch */

// Aufruf: spider.php?site=http://www.example.com/datei.php

//DB-Connect
include("datas.php");
$connection=mysql_connect($host,$user,$pw) or die("Verbindung konnte nicht hergestellt werden");
$dbco=mysql_select_db($db, $connection) or die("Datenbank konnte nicht ausgewählt werden");

// zuweisen von wichtigen Variablen
$start_site = $_REQUEST['start'];
$host = explode("/",$start_site);
$host = $host[2];

// File lesen und inhalt $content zuweisen
ob_start();
readfile($start_site);
$content = ob_get_clean();
ob_start();
echo '<pre>';

echo "Location: $start_site \n Gelesen...\n\n";
//Auslesen von Informationen
$info = get_meta_tags($start_site);
foreach ($info as $key => $value) {
   echo $key.": <b>".$value."</b>\n";
}
// Suche nach links starten
$suchstring = '/<a .*href="(.*)".*>.*<\/a>/U';
preg_match_all($suchstring,$content,$treffer);
unset($treffer[0]); // Gesamte Suchstrings löschen, nur den gematchten ausdruck
ob_end_flush(); // Outputbuffer leeren und ausgeben
$treffer[1] = array_unique($treffer[1]);
foreach ($treffer[1] as $value) {
   if (preg_match('/^(http:|javascript:|mailto:|\#).*/i',$value)) {
      unset($treffer[1][array_search($value,$treffer[1])]);
   }
}
$tokenlinks = array();
$tokencontent = array();
foreach ($treffer[1] as $link) {
$oldlink = $link;
if ($link{0} == "?") { // absolute URL generieren
   $link = $start_site.$link;
}
else {
   $link = "http://".$host."/".$link;
}
   ob_start();
   readfile($link);
   $content = ob_get_clean();
   ob_start();
   echo "\nLocation: $link \n Gelesen...\n";
   $suchstring = '/<a.*href="(.*)".*>.*<\/a>/U';
   preg_match_all($suchstring,$content,$treffer2);
   foreach ($treffer2[1] as $value) {
      if ($value{0} == "?") { // absolute URL generieren
         $tokenlinks[] = $start_site.$value;
      }
      else {
         $tokenlinks[] = "http://".$host."/".$value;
      }
   }
   $tokencontents[] = $content;
   unset($treffer2);
   ob_end_flush();
}
$tokenlinks = array_unique($tokenlinks);
$tokencontents = array_unique($tokencontents);
foreach ($tokenlinks as $value) {
   if (preg_match('/^(http:|javascript:|mailto:|\#).*/i',$value)) {
      unset($tokenlinks[array_search($value,$tokenlinks)]);
   }
}
$sql = "DELETE FROM search";
$erg = mysql_query($sql);
if ($erg) {
   echo "\nAlle Daten gelöscht...\n";
}
else {
   die("\nKonnte Datensätze nicht löschen!\n");
}

foreach ($tokencontents as $key => $value) {
   if ($treffer[1][$key]{0} == "?") { // absolute URL generieren
      $url = $start_site.$treffer[1][$key];
   }
   else {
      $url = "http://".$host."/".$treffer[1][$key];
   }
   preg_match('|<title>(.*)</title>|iU',$value,$title);
   $title = $title[1];
$suche = array ("'<script[^>]*?>.*?</script>'si",  // JavaScript entfernen
               "'<[\/\!]*?[^<>]*?>'si",          // HTML-Tags entfernen
               "'([\r\n])[\s]+'",                // Leerräume entfernen
               "'&(quot|#34);'i",                // HTML-Entitäten ersetzen
               "'&(amp|#38);'i",
               "'&(lt|#60);'i",
               "'&(gt|#62);'i",
               "'&(nbsp|#160);'i",
               "'&(iexcl|#161);'i",
               "'&(cent|#162);'i",
               "'&(pound|#163);'i",
               "'&(copy|#169);'i",
               "'&#(\d+);'e");                    // als PHP auswerten

$ersetze = array ("",
                 "",
                 "\\1",
                 "\"",
                 "&",
                 "<",
                 ">",
                 " ",
                 chr(161),
                 chr(162),
                 chr(163),
                 chr(169),
                 "chr(\\1)");

$text = preg_replace($suche, $ersetze, $value);
   $sql = "INSERT INTO search (url,title,content) VALUES ('$url','$title','$text')";
   $erg = mysql_query($sql);
   if ($erg) {
      echo $url." erfolgreich gespeichert...\n";
   }
   else {
      echo $url." konnte nicht gespeichert werden!\n";
   }
   echo '<textarea>'.$text.'</textarea>';
}
echo "\nRefresh abgeschlossen";

echo '</pre>';
?>
 
Hallo Jeko,

vielen Dank für den Script !

Ich habe leider keine Ahnung von PHP und MySQL,
hättest du eventuell Lust gegen Entgelt diesen Script für meine Bedürfnisse auszubauen ?

Viele Grüße aus Hamburg,

Josef

ICQ Nummer: 66892579
E-Mail: info_ad_webby.de
 
Kein Entgelt, ich hab grad so Lust dir des zu machen. Also,

- Wie sind die internen Links gekenntzeichnet?
- Wie sind externe Links gekenntzeichnet?
- Wo sollen die externen Links gespeichert werden?
- Was soll alles gespeichert werden?
- Wieviele Dimensionen verfolgen?
- Was verstehst du unter "reinen Domainnamen"?
 
Sorry, jetzt habe ich dich auch noch so lange warten lassen, vielen Dank für deine Bereitschaft.. vielleicht bist du an anderen Aufträgen mit Entgelt interessiert :) ?

Zum Script:
- Wie sind die internen Links gekenntzeichnet?
.-. Die internen Links sind so gekennzeichnet, dass Sie immer die Start URL beinhalten, also z.B.
[lycos.de]http://webkatalog.[B]lycos.de/[/B]10031135/?path=100-31135
oder
[dmoz.org/world/deutsch/]http://dmoz.org/World/Deutsch/Gesundheit/Senioren/
WICHTIG:http://dmoz.org/World/Armenian/ sollte weder als interne Domain noch als externe Domain erkannt werden, also rausgefilter wo wir gerade bei den externen Domains angelangt sind:

-Wie sind externe Links gekenntzeichnet?:
.-.die externen Links müssen die TLD .de beinhalten um gespidert zu werden und ausschließlich richtige Domains sein dürfen, also z.B. www.jswelt.de oder jswelt.de und nicht jswelt.com oder jswelt.de/unterordner/
WICHTIG: Nur bis zu 1. Dimension bei den internen Links spidern, also je internen Subordner /xyz/ nur bis zu einer Dimension spidern, was auf der externen Seite nochmals für Verlinkungen existieren ist nicht weiter relevant.

- Wo sollen die externen Links gespeichert werden?
.-. Die externen Links können in der MySQL Datenbank gespeichert werden, jede zeile sollte eine externe Domain in folgender Form beinhalten: externe-domain.de und nicht www.externe-domain.de
WICHTIG: Doppelte Domains bitte beim Eintrag löschen.

- Was soll alles gespeichert werden?
.-. Lediglich die externen Links in oben beschriebener Weise, reicht völlig aus.

- Wieviele Dimensionen verfolgen?
.-. Interne Links bitte unendlich, externe Links wie oben beschrieben nur die Spiderung der externen Domain und nicht weiter. ( Vielleicht kann man die Option des Weitermachens für spätere Variationen offenhalten)

- Was verstehst du unter "reinen Domainnamen"?
.-. Wie oben beschrieben, nur Domains wie www.domain.de oder domain.de undnicht domain.de/unterordner/ oder www.domain.com/seite10.php


Ich hoffe ich habe nichts vergessen, wie du siehst ist es wirklich nicht gerade wenig was ich beanspruche, deshalb würde ich Dir wirklich gerne wenigstens ein kleines Entgelt leisten.

Viele Grüße und danke im Voraus,

Josef
 
Zuletzt bearbeitet:
Du meinst also nur die externen Hostnamen speichern?

Also nur links, welche zum Beispiel www.blub.de oder blah.de heissen?

Hier hab ichs nochmal zusammengefasst:

Aufgabe:
- Verfolge interne Links
- Speichern der HOSTS der EXTERNEN Links in eine MYSQL-DB

*** Interne Links
Kennzeichnung durch http://webkatalog.lycos.de

*** Externe Links
Kennzeichnug durch
- DE-Domain (*.de)
- Links, welche nur aus Hostnamen bestehen und nicht auf explizite Dateien oder Verzeichnisse verweisen

so richtig verstanden?
 
Zuletzt bearbeitet:
Alles korrekt, was bei der Zusammenfassung fehlt:
Doppelte Domains bitte beim Eintrag in die MySQL DB löschen.

Vielleicht noch mal zu der Kennzeichnung der Internen Links, damit es keine Missverständnisse gibt:
Bevor die Suchabfrage durchgeführt wird, sollte man in der Config die Startadresse eingeben können, wenn diese jetzt folgendes enthält: dmoz.org/world/deutsch/
werden alle internen Links die folgende URL enthalten: dmoz.org/world/deutsch/
unendlich gespidert.
dmoz.org/world/france/ sollte hingegen nicht gespidert werden, weil es den Subordner deutsch/ nicht enthält, es sollte auch nicht in die MySQL DB übertragen werden weil es sich nicht als externer Link kennzeichnet (keine reine .de Domain, enthält Subordner)

Gruß,

Josef
 
Achso! Ja, das wär noch wichtig ^^

Doppelte Einträge wirds kaum geben, da ich am Anfang jedes Durchlaufs die Tabelle in der DB leere..

Hier meine Algos...
PHP:
Algorithmen:

1. Durchlauf
Startseite = start
	-> Quellcode holen
	-> Alles bis auf Links entfernen
	-> Interne Links und Externe Links in 2 separate Arrays speichern
	-> Externe in DB schreiben
		-> Überprüfen ob Link nicht schon drin
	-> Interne Links in Textdatei schreiben
	-> nächster Durchlauf durch aufrufen von spider.php mit start = 1. Link in textdatei

n. Durchlauf
Startseite = n.ter Link aus Textdatei
	-> Quellcode holen
	-> Alles bis auf Links entfernen
	-> Interne Links und Externe Links in 2 separate Arrays speichern
	-> Externe in DB schreiben
		-> Überprüfen ob Link nicht schon drin
	-> interne Links in Textdatei schreiben
		-> Überprüfen ob Link nicht schon drin
	-> nächster Durchlauf durch aufrufen von spider.php mit start = n+1 . Link in Textdatei

Nach dem letzten Durchlauf:
	-> Textdatei löschen
 
-> nächster Durchlauf durch aufrufen von spider.php mit start = 1. Link in textdatei

Die spider.php sollte jedesmal automatisch aufgerufen werden, sonst sitzt man ewig dran :)
 
Das ist logisch ;)

Mal ein Beispiel:
Code:
(...)
<a href="/World/Deutsch/">Deutsch</a>:
<a href="/World/Deutsch/Online-Shops/">Online-Shops</a>:
<a href="/World/Deutsch/Online-Shops/Nischenprodukte/">Nischenprodukte</a>:
Linkshänder</b></font>  <i>(4)</i>
</td></tr></table>
<hr>

<p>Siehe auch:<ul>
<li><a href="/World/Deutsch/Gesellschaft/Menschen/Linksh%c3%a4nder/"><b>World: Deutsch: Gesellschaft: Menschen: Linkshänder</b></a>  <i>(18)</i>
</ul>
<hr>
<ul>
<li><a href="http://www.lefthand.de">Lefthand</a> - Geschenke, aber auch Gebrauchsgegenstände für Haushalt, Garten und Büro, auch für Kinder, sowie Literatur. Mit SSL-Verschlüsselung der Daten.
<li><a href="http://www.derlinkshaender.de">Der Linkshänder</a> - Der Versandhandel hat neben den üblichen Haushalts- und Büro-Artikeln auch einige Gartengeräte im Programm.
<li><a href="http://www.linkshaender-shop.de">Linkshänder Shop</a> - Versand mit reichhaltigen Angeboten speziell für Linkshänder.

<li><a href="http://www.sinistrius.de/">Sinistrius, Evelyn Gardemann</a> - Der Versandhandel bietet auch den Download des kompletten Katalogs an und informiert auf Wunsch per Newsletter über neue Produkte.
</ul><hr>
<table width="95%" cellpadding=0 cellspacing=0><tr><td height=3></td></tr><tr><td valign="top"><ul><li>Suche "<b>Linkshänder</b>" mit:  </ul></td><td valign="top"><small>
<a href="http://www.alltheweb.com/search?type=all&query=linksh%c3%a4nder">All the Web</a> - 
<a href="http://www.altavista.com/cgi-bin/query?q=linksh%c3%a4nder">AltaVista</a> - 
<a href="http://gigablast.com/search?q=linksh%c3%a4nder">Gigablast</a> - 
(...)

In der DB stehen dann am Ende des Scannens dieses Abschnittes folgende Einträge:
PHP:
lefthand.de
derlinkshaender.de
linkshaender-shop.de
sinistrius.de
Und gespidert werden folgende (also in der Textdatei stehen am Ende folgende...):
Code:
/World/Deutsch/
/World/Deutsch/Online-Shops/
/World/Deutsch/Online-Shops/Nischenprodukte/
/World/Deutsch/Gesellschaft/Menschen/Linksh%c3%a4nder/

Wäre das so richtig?
 
Zuletzt bearbeitet:
wunderbar :D

Bitte noch beachten, dass die internen Links nicht mehrfach durchlaufen werden, da höchstwahrscheinlich die gleichen internen Links auch mehrfach auf den internen Seiten verlinkt sind.

Also in unserem Beispiel wird der interne Link: /World/Deutsch/ wohl sehr häufig vorkommen, wenn er immerwieder von neu gescannt wird, würde es sehr viel unnötige Zeit in Anspruch nehmen.

Vielleicht kann man für Log Zwecke die internen Links entweder in einer Textdatei oder in der Datenbank für spätere Überprüfungen(ob er auch wirklich alle internen Links durchlaufen hat) mitspeichern.
 
[] Hättest du dir die Algorithmen mal angeschaut, hätteste gesehen dass ich genau das schon eingebunden habe ;)

egal...
Ich schau mal ob ich heut fertig werd---
 
Ne, ich hatte grad Stress in der Schule. Bin aber ziemlich weit. Hab jetzt soweit, dass er alle internen und externen Links abspeichert (in separate Arrays).
 
So habs jetzt fertig ^^

Anfangs hab ich viel zu weit gedacht und zu komplizierte Überlegungen angestellt. Aber jetzt isses fertig.

Also, was du wissen musst:

- Die Datei kann heissen wie sie will :D

- Das Script legt am Anfang einmalig eine Tabelle namens "links" an.

- Du musst deine Login-Daten für die Datenbank angeben (Zeile 45).

- Aufruf normal mit einem Browser über die URL: http://www.example.com/spider.php
-> Eingabe der URL
-> "Spider starten!"

- Auch wenn es vielleicht so aussieht, werden trotzdem keine doppelten Einträge in der DB gemacht.

Ich denk das war alles. Bei Fragen einfach fragen :D

PHP:
<?php
$EXEC_TIME = time();
set_time_limit(60);

/*
Copyright by. dominique sandoz. jeko@gmx.ch. http://jeko.homelinux.com. 22:17. 01.10.2005.
Für: capi. @forum.jswelt.de.
*/


// Aufruf durch: http://jeko.cwsurf.de/spider.php?start=http://jeko.cwsurf.de/index.php

/*
Aufgabe:
 - Verfolge interne Links (JEDEN und in unendlich Dimensionen)
 - Speichern der HOSTS der EXTERNEN Links in eine MYSQL-DB

*** Interne Links
Kennzeichnung durch * /world/deutsch/ *
OHNE http://dmoz.org/World/Armenian/

*** Externe Links
Kennzeichnug durch
	- DE-Domain (*.de)
	- Links, welche nur aus Hostnamen bestehen und nicht auf explizite Dateien oder Verzeichnisse verweisen


Algorithmen:

n. Durchlauf
	Schleife mit zähler n
1	n.tes Element aus Array mit internen Links holen
1.1	n.tes Element nicht gleich letztes Element
	JA	Ende, Statusseite anzeigen
	NEIN	weitermachen
2	Quellcode holen
3	Quellcode auf Links verkürzen
4	Interner Link in Array speichern, Externer in DB
4.1	!!! Interner Link nicht schon in Array?!
5	Loop
*/

//DB-Connect

$host = "localhost";
$user = "user";
$pw = "passwort";
$db = "datenbankname";

$connection=mysql_connect($host,$user,$pw) or die("Verbindung konnte nicht hergestellt werden");
$dbco=mysql_select_db($db, $connection) or die("Datenbank konnte nicht ausgewählt werden");


if ( isset($_GET['start'])) { // wird die STATUSSeite angefragt?

// zuweisen von wichtigen Variablen
$start_site = $_REQUEST['start'];

// Host filtern

$host = str_replace("http://","",$start_site);
$host_arr = explode("/",$host);
$host = $host_arr[0];
unset($host_arr[0]);

// Verzeichnis filtern
$verz = array_reverse($host_arr);
unset($host_arr[0]);
$verz = implode("/",$host_arr);
$verz = rawurldecode("/".$verz);

echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head><title>SPIDER - '.$start_site.'-'.date("d.m.Y H:I:s").'</title>
</head>
<body style="background-color:#333; color:#fff;">
<h1>Spider</h1>
<p>Host: '.$host.'</p>
<p>Verzeichnis: '.$verz.'</p>
<p><a href="'.$_SERVER['SCRIPT_NAME'].'">Zum Status</a></p>';

// Prüfen ob Datenbank existiert
$tabellen = mysql_list_tables("$db");
$tabellen_zahl = mysql_num_rows($tabellen);
$ergebnis = 0;
for ($t = 0; $t < $tabellen_zahl; $t++){
     if (mysql_tablename($tabellen, $t) == "links"){
        $ergebnis = 1;
     }
}
if (! $ergebnis) {
	$erg = mysql_query("CREATE TABLE `links` (`name` varchar(254) collate latin1_general_ci NOT NULL default '', PRIMARY KEY  (`name`),	FULLTEXT KEY `name` (`name`)) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;");
	if ($erg) {
		print "<p>Datenbank erstellt</p>";
	}
	else {
		die("<p style='color:#f00;'>Datenbank konnte nicht erstellt werden!</p>");
	}
}

set_time_limit(60);

$interne = array($start_site);

for ($i = 0; $i < count($interne); $i++) {


/** 1 Quellcode holen **/

// File lesen und inhalt $content zuweisen
ob_start();
readfile($interne[$i]);
$content = ob_get_clean();

// Ausgabe an Benutzer
echo "<p>Location: $interne[$i] <br /> Gelesen...</p>";


/** 2 Links von QT trennen **/

$suchstring = '/<a .*href="(.*)".*>.*<\/a>/U';
preg_match_all($suchstring,$content,$treffer);
unset($treffer[0]); // Gesamte Übereinstimmungen löschen, nur den gematchten Ausdruck behalten (Werte in den href-Attributen der Links)

// Doppelte Einträge löschen
$treffer[1] = array_unique($treffer[1]);


/** 3 Externe und interne Links in zwei separate Arrays speichern **/

	set_time_limit(60);

foreach ($treffer[1] as $value) {
	if ($value == "/World/Armenian/") {
		continue;
	}
	elseif (substr($value,0,strlen($verz)) == $verz && ! in_array("http://".$host.$value,$interne) ) {
		$interne[] = "http://".$host.$value;
	}
	elseif (preg_match("/^http:\/\/(.*)\.de\//U",$value,$ext_treffer)) {
		$query = mysql_query("REPLACE links SET name='$ext_treffer[1].de'");
		if ($query == 1) {
			print "<p style='color:#0f0;'>Externer Link $value in Datenbank geschrieben.</p>\n";
		}
		if ($query == 0) {
			print "<p style='color:#f00;'>Konnte $value nicht in Datenbank schreiben!</p>\n";
		}
	}
}

ob_flush();

} // ENDE DER SCHLEIFE

echo '<p>Refresh abgeschlossen.</p>
<p>Durchgänge insg.: '.$i.'</p>
<p><a href="'.$_SERVER['SCRIPT_NAME'].'>Zum Status</a></p></body></html>';

} else { // STATUSSeite wird angefragt

	echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head><title>SPIDER - '.$start_site.'-'.date("d.m.Y H:I:s").'</title>
</head><body>
<h1>Spider-Status</h1>
<p>Hier sind die Einträge der Datenbank mit den externen Links</p>

<form action="'.$_SERVER['SCRIPT_NAME'].'" method="get">
<input type="text" name="start" value="http://example.com/foo/bar/" />
<input type="submit" value="Spider starten!" />
<input type="reset" value="Form anzeigen" />
</form>

<h2>Externe Links</h2>
<p>Folgende Links wurden als externe Links erkannt und in die Datenbank geschrieben</p>
';
// Prüfen ob Datenbank existiert
$tabellen = mysql_list_tables("$db");
$tabellen_zahl = mysql_num_rows($tabellen);
$ergebnis = 0;
for ($t = 0; $t < $tabellen_zahl; $t++){
     if (mysql_tablename($tabellen, $t) == "links"){
        $ergebnis = 1;
     }
}
if (! $ergebnis) {
	$erg = mysql_query("CREATE TABLE `links` (`name` varchar(254) collate latin1_general_ci NOT NULL default '', PRIMARY KEY  (`name`),	FULLTEXT KEY `name` (`name`)) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;");
	if ($erg) {
		print "<p>Datenbank erstellt</p>";
	}
	else {
		print "<p style='color:#f00;'>Datenbank konnte nicht erstellt werden!</p>";
	}
}
echo '
<ul style="border:1px solid #aaa;">';
$ergebnisse = mysql_query("SELECT * FROM links");
$i = 0;
while ($row = mysql_fetch_row($ergebnisse)) {
	echo "<li>$row[0]</li>";
	$i++;
}
echo '</ul>
<p>Insgesamt '.$i.' Einträge</p>
<p>Spider by Dominique Sandoz</p>
<p><a href="http://validator.w3.org/uri=referer">XHTML valid</a></p>
</body>
</html>';

}


?>
 
Vielen Dank, ich probier den Script heute Abend mal aus und sag dir bescheid, ob alles funktioniert.

Viele Grüße,

Josef
 
Hallo Jeko,

habe das Script mal auf Funktionalität testen lassen, leider ohne Erfolg.
Die Spiderung der internen Links scheint noch nicht richtig zu funktionieren.

Ich hinterlasse dir mal eine PM mit der direkten URL zu meinem Server und eine Webkatalog Übersicht zum Testen.
 
MHm...Wie meinst du das? Ich checks nicht ganz...

Ich hab natürlich das Spidering der internen Links an dmoz.de angepasst, das heisst dass es nur mit internen Links wie sie auf dmoz.de vorkommen funktioniert.

Willst du das etwa mit allen im Web vorkommenden Sites machen?
 
Zurück
Oben