Webseiten Analysieren
lima-city → Forum → Programmiersprachen → PHP, MySQL & .htaccess
agent
anfang
array
aussehen
browser
code
datenbank
datum
format
frage
funktion
global host
host
http
laden
optimieren
speichern
tabelle
url
verbindung
-
Hallöchen ;D
Mir war mal wieder langweilig, da habe ich mir hier ein kleines System zum mehr oder weniger Analysieren von Websites gebastelt. Den Originalcode habe ich ausm Netz (Finde gerade nicht wo genau), habe da ein wenig um und rein gebastelt. Ich finde mein Code ist evtl nicht gerade der beste oder effizienteste, evtl findet ihr was was man verbessern kann. Derzeit bekommt man damit zwischen 1 und ~250 Seiten pro Sekunde durch.
Hier ist so ein ungefährer überblick was der Code machen soll:
Überprüfen ob noch Startpunkte im Pool verfügbar sind {Wenn nein diese Tabelle zurücksetzen, die Startpunkte aus Tabelle 3 laden, rückwärts sortieren, einsetzen in Tabelle 2 und Tabelle 3 dann zurücksetzen} URL für Startpunkt aus Tabelle 2 hohlen, aus Tabelle 2 löschen in Tabelle 3 setzen Einige Werte für das hohlen der Daten festlegen, header, Laufzeit, arrays Hier arbeitet der Webcrawler Kucken ob URL bereits in der DB war, dann erneuern oder erstellen.
Und hier ist der Code. Name der Tabellen und Verbindung zur DB steht in sql.php.
<?php include './sql.php'; sturl(); function sturl(){ global $host, $user, $db, $pass, $table2, $table3, $currentdate; //Check $mysqli = new mysqli($host, $user, $pass, $db); $select = "SELECT url from $table2)"; $resultu = $mysqli->query($select); if (mysqli_num_rows($resultu) == 0){ //RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET// //Datenbank 1 zurücksetzen $mysqli = new mysqli($host, $user, $pass, $db); $format = "TRUNCATE TABLE $table2)"; $result0 = $mysqli->query($format); //Datenbank 2 laden: $mysqli = new mysqli($host, $user, $pass, $db); $select = "SELECT url from $table3)"; $result1 = $mysqli->query($select); while($row = $result->fetch_array()) { $rows[] = $row; $urls[$x]= $row[0]; $x = $x+1; } //Umkehren $reurl = array_reverse($url); $x = 0; while ($x<=sizeof($reurl)){ //Einsetzen in DB 1 $mysqli = new mysqli($host, $user, $pass, $db); $insert = "INSERT INTO $table2 (url) VALUES ('$reurl[$x]')"; $result2 = $mysqli->query($insert); $x = $x+1; } //Datenbank 2 zurücksetzen $mysqli = new mysqli($host, $user, $pass, $db); $format = "TRUNCATE TABLE $table3)"; $result3 = $mysqli->query($format); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Get $mysqli = new mysqli($host, $user, $pass, $db); $view = "SELECT url FROM $table2"; $result = $mysqli->query($view); $var = mysqli_fetch_array($result); $url = $var[0]; //Del $mysqli = new mysqli($host, $user, $pass, $db); $view = "DELETE FROM $table2 WHERE url='$url'"; $result = $mysqli->query($view); //Set $mysqli = new mysqli($host, $user, $pass, $db); $view = "INSERT INTO $table3 (url) VALUES ('$url')"; $result = $mysqli->query($view); procst($url); } function procst($url){ $runtime = 2;//Time Limit der Suche //AUSFÜHREN##AUSFÜHREN##AUSFÜHREN##AUSFÜHREN##AUSFÜHREN##AUSFÜHREN##AUSFÜHREN##AUSFÜHREN##AUSFÜHREN##AUSFÜHREN##AUSFÜHREN##AUSFÜHREN##AUSFÜHREN##AUSFÜHREN##AUSFÜHREN## //Bezeichnung des Crawlers $name_crawl = "Mr-Horstexplorer/1.04\n"; $currentdate = date('Y.d.m'); //Setzen des aktuellen Datums im yyy.dd.mm Format set_time_limit($runtime*60); //Script soll nur n Minuten lang arbeiten, dann wird script mit anderer URL neu gestartet. // $untime in Minuten angeben $already_crawled = array(); $crawling = array(); follow_links($url); } //FUNKTIONEN##FUNKTIONEN##FUNKTIONEN##FUNKTIONEN##FUNKTIONEN##FUNKTIONEN##FUNKTIONEN##FUNKTIONEN##FUNKTIONEN##FUNKTIONEN##FUNKTIONEN##FUNKTIONEN##FUNKTIONEN##FUNKTIONEN## function follow_links($url) { global $already_crawled; global $crawling; global $name_crawl; $options = array('http'=>array('method'=>"GET", 'headers'=>$name_crawl)); $context = stream_context_create($options); $doc = new DOMDocument(); @$doc->loadHTML(@file_get_contents($url, false, $context)); $linklist = $doc->getElementsByTagName("a"); foreach ($linklist as $link) { $l = $link->getAttribute("href"); if (substr($l, 0, 1) == "/" && substr($l, 0, 2) != "//") { $l = parse_url($url)["scheme"]."://".parse_url($url)["host"].$l; } else if (substr($l, 0, 2) == "//") { $l = parse_url($url)["scheme"].":".$l; } else if (substr($l, 0, 2) == "./") { $l = parse_url($url)["scheme"]."://".parse_url($url)["host"].dirname(parse_url($url)["path"]).substr($l, 1); } else if (substr($l, 0, 1) == "#") { $l = parse_url($url)["scheme"]."://".parse_url($url)["host"].parse_url($url)["path"].$l; } else if (substr($l, 0, 3) == "../") { $l = parse_url($url)["scheme"]."://".parse_url($url)["host"]."/".$l; } else if (substr($l, 0, 11) == "javascript:") { continue; } else if (substr($l, 0, 5) != "https" && substr($l, 0, 4) != "http") { $l = parse_url($url)["scheme"]."://".parse_url($url)["host"]."/".$l; } if (!in_array($l, $already_crawled)) { $already_crawled[] = $l; $crawling[] = $l; get_details($l); } } array_shift($crawling); foreach ($crawling as $site) { follow_links($site); } } function get_details($url) { global $name_crawl; $options = array('http'=>array('method'=>"GET", 'headers'=>"User-Agent: ".$name_crawl)); $context = stream_context_create($options); $doc = new DOMDocument(); @$doc->loadHTML(@file_get_contents($url, false, $context)); $title = $doc->getElementsByTagName("title"); $title = $title->item(0)->nodeValue; $description = ""; $keywords = ""; $metas = $doc->getElementsByTagName("meta"); for ($i = 0; $i < $metas->length; $i++) { $meta = $metas->item($i); if (strtolower($meta->getAttribute("name")) == "description") $description = $meta->getAttribute("content"); if (strtolower($meta->getAttribute("name")) == "keywords") $keywords = $meta->getAttribute("content"); } // $tile = str_replace("\n", "", $title); $description = str_replace("\n", "", $description); $keywords = str_replace("\n", "", $keywords); //Einfügen in Datenbank bzw Erneuern. global $host, $user, $db, $pass, $table, $currentdate; $mysqli = new mysqli($host, $user, $pass, $db); $view = "SELECT * FROM $table WHERE url='$url'"; $result = $mysqli->query($view); if (mysqli_num_rows($result) == 1) { //Eintrag updaten. $mysqli = new mysqli($host, $user, $pass, $db); $insert = "UPDATE $table SET last_refresh='$currentdate', title='$title', description = '$description', keywords='$keywords' WHERE url='$url'"; $result = $mysqli->query($insert); } else{ //Eintrag erstellen. $mysqli = new mysqli($host, $user, $pass, $db); $insert = "INSERT INTO $table (url, title, description, keywords, last_refresh) VALUES ('$url','$title','$description','$keywords', '$currentdate')"; $result = $mysqli->query($insert); } }
Das Datum der letzen Aktualisierung kommt deswegen hin um nicht mehr gültige Links nach 3 Wochen auszusortieren.
Beitrag zuletzt geändert: 15.12.2017 8:58:41 von horstexplorer -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
Du Speicherst die komplette Webseite in eine DB oder habe ich das falsch verstanden? Müsste mir das mal ansehen in einer ruhigen Minute.
-
OT: Wenn du schon deinen Code so formatierst, dass man ihn denkbar schlecht lesen kann, dann posten ihn doch hier wenigstens so:
<?php include './sql.php'; sturl(); function sturl(){ global $host, $user, $db, $pass, $table2, $table3, $currentdate; //Check $mysqli = new mysqli($host, $user, $pass, $db); $select = "SELECT url from $table2)"; $resultu = $mysqli->query($select); if (mysqli_num_rows($resultu) == 0){ //RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET// //Datenbank 1 zurücksetzen $mysqli = new mysqli($host, $user, $pass, $db); $format = "TRUNCATE TABLE $table2)"; $result0 = $mysqli->query($format); //Datenbank 2 laden: $mysqli = new mysqli($host, $user, $pass, $db); $select = "SELECT url from $table3)"; $result1 = $mysqli->query($select); while($row = $result->fetch_array()) { $rows[] = $row; $urls[$x]= $row[0]; $x = $x+1; }
Das sind nur 4 Zeichen Zusatzaufwand. -
mein-wunschname schrieb:
OT: Wenn du schon deinen Code so formatierst, dass man ihn denkbar schlecht lesen kann, dann posten ihn doch hier wenigstens so:
<?php include './sql.php'; sturl(); function sturl(){ global $host, $user, $db, $pass, $table2, $table3, $currentdate; //Check $mysqli = new mysqli($host, $user, $pass, $db); $select = "SELECT url from $table2)"; $resultu = $mysqli->query($select); if (mysqli_num_rows($resultu) == 0){ //RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET//RESET// //Datenbank 1 zurücksetzen $mysqli = new mysqli($host, $user, $pass, $db); $format = "TRUNCATE TABLE $table2)"; $result0 = $mysqli->query($format); //Datenbank 2 laden: $mysqli = new mysqli($host, $user, $pass, $db); $select = "SELECT url from $table3)"; $result1 = $mysqli->query($select); while($row = $result->fetch_array()) { $rows[] = $row; $urls[$x]= $row[0]; $x = $x+1; }
Das sind nur 4 Zeichen Zusatzaufwand.
Okay die Funktion kannte ich nicht nicht ;) -
Hallo Horst,
unabhängig von den Formatierungsproblemen, was ist genau dein Ziel damit? Willst du einen bestimmten Content einer Webseite auslesen?
Also ich hab mir auch mal ein Script geschrieben um Amazon Artikelnummern aus zu lesen, finde es nur grad nicht mehr! Ist aber auch schon fast 10 Jahre her und habs seitdem nicht mehr wirklich genutzt
Aber man liest ja andere Seiten nur aus um etwas davon zu nutzen oder speichern und ggf. zu analysieren. Also, was bezweckst du damit etwas konkreter?
-
Oh genaue Ziele :D
Eigentlich soll es erstmal nur weg speichern was es findet. Danach hatte ich mir überlegt das nach Inhalten durchsuchen zu können. Wie das aber aussehen soll habe ich mir noch nicht wirklich überlegt.
Problematisch ist das nicht alle Webseiten Content in Meta Tags schreiben. Somit bleibt das ganze meist leer. Da könnte man ggf irgendwie nachbessern.
Sonnst ist sehr viel mit SQL gearbeitet. Evtl kann man dort etwas zusammenfassen. -
Also nur um es richtig zu verstehen, du willst mit der Seite den Textnhalt komplett wegspeichern?
Dann müsste es ganz einfach gehen, indem du einfach die komplette Seite liest und alles zwischen den "<" und ">" Tags löschst. Am Ende fügst du es zusammen und speicherst es ab.
Um Menus etc zu ignorieren musst du halt spezifische Tags noch suchen, die in Frage kommen könnten um diese zu ignorieren. Aber da geht es schon eher drum, dass man dann Detailarbeit machen muss um zu gewährleisten, dass sinnlose Inhalte ignoriert werden.
Gibt zwar wenig bis keinen Sinn für mich aber so kannst du einfach und schnell Seitenkontexte einfach lesen und speichern!
Wie gestaltest du die Suche der Webseiten? gibst du die Seiten vor, die durchsucht werden sollen oder wie hast du dir das gebaut, dass Seiten gesucht werden? -
Ganz so meinte ich das nicht.
Derzeit werden (und sollen) nur neben dem Titel der Webseite die Content Daten aus dem Meta Tag gespeichert werden. Also so ala Stichwörter über den Seiteninhalt<meta content="Äpfel,Birnen, Bananen" />
Würde ich die ganze Seite speichern würde die DB größe explodieren und das suchen nochmal deutlich länger dauern :)
Leider ist nur in ca 1/20 aller Seiten solch ein Content gesetzt, da müsste man sich ggf mit Hilfssystemen den Inhalt erarbeiten z.bsp an Überschriften. (Evtl baue ich das noch irgendwie ein)
Wie meinst du das mit dem Suche der Webseiten? Wie ich die laden um sie zu analysieren?
An sich gebe ich eine Seite an wo die Analyse starten soll. Z.bsp Lima-City.de
(Diese Seiten werden nach und nach aus einem Pool aus einer DB geladen, ist der Pool leer wird er wieder zurück gesetzt.)
Der webcrawler arbeitet sich nun n Minuten (2) an allen Verlinkungen die es auf den Seiten und den nächsten findet weiter. Somit kommt man Recht gut an viele Informationen die die Seite anbietet ran. Natürlich wird auch viel müll mitgenommen.
Den Startwert gibt es um Seiten einfacher auch erneut auslesen zu können fals sich der Inhalt ändern sollte. Datensätze die dann nach 3Wochen (3 Suchdurchläufen) nicht mehr aktualisiert wurden werden gelöscht.
So die Theorie.
(Ich kucke Mal ob ich da die Ausgabe auch ohne das DB Zeugs hin bekomme falls sich das jemand ansehen will. Link kommt dann hier rein)
Beitrag zuletzt geändert: 17.12.2017 12:06:14 von horstexplorer -
Ah OK, naja stimmt, die Meta daten pflegen die wenigsten! Vor allem Privatpersonen verzichten oft darauf. Professionelle Seiten setzen das meistens aber auch nicht immer!
Hast du den Aufruf über einen Cronjob gesteuert?
Nach wie vor erschließt sich mir zwar der Sinn noch nicht so wirklich aber ich hoffe dass du diesen für dich erkannt hast!
Jetzt nochmal ne blöde Frage, wolltest du Hilfe bei deinem Ursprungspost? Willst du das Auslesen optimieren oder eher Unterstützung um es zu optimieren?
-
Hast du den Aufruf über einen Cronjob gesteuert?
Nach wie vor erschließt sich mir zwar der Sinn noch nicht so wirklich aber ich hoffe dass du diesen für dich erkannt hast!
Jetzt nochmal ne blöde Frage, wolltest du Hilfe bei deinem Ursprungspost? Willst du das Auslesen optimieren oder eher Unterstützung um es zu optimieren?
Ja das ganze wird dann später über einen Cron gestartet.
An sich ging es mir um Code Optimierung, vorallem bei den Datenbankabfragen am Anfang, aber auch noch das hinzufügen des Auslesens der Überschriften der Seite, fals es keine Content Tags geben sollte (Also alle h Tags)
Hier mal so zum Test der Ausgabe
http://horstexplorer.lima-city.de/LinkTest/test.php
Beitrag zuletzt geändert: 17.12.2017 16:44:32 von horstexplorer -
horstexplorer schrieb:
An sich ging es mir um Code Optimierung, vorallem bei den Datenbankabfragen am Anfang
Ein Anfang wäre: Nicht für jede Abfrage eine neue Verbindung auf machen.
aber auch noch das hinzufügen des Auslesens der Überschriften der Seite, fals es keine Content Tags geben sollte (Also alle h Tags)
Die entsprechenden Methoden nutzt du doch schon. Musste nur den Aufruf entsprechend anpassen.
Zur Übersichtlichkeit kann ich dir nur (wieder) sagen: Formatiere anständig und schau dir das OOP-Konzept an. -
Okay.
Das mit den Überschriften war tatsächlich einfacher als gedacht:
$uschrift = $doc->getElementsByTagName("h1"); $uschrift = $uschrift->item(0)->nodeValue;
Einfach hinzugefügt, läuft, freut mich :D
Das Mysql kann also auch so aussehen?:
$mysqli = new mysqli($host, $user, $pass, $db); $select = "SELECT url from $table2)"; $resultu = $mysqli->query($select); if (mysqli_num_rows($resultu) == 0){ //Datenbank 1 zurücksetzen $format = "TRUNCATE TABLE $table2)"; $result0 = $mysqli->query($format);
Also dass man nur einmal die Verbindung öffnen muss.
(Muss man das in jeder Funktion erneut machen oder reicht einmal ganz am Anfang und $mysqli als global?)
Hier ist nochmal der Code in Aktion, ohne DB
http://horstexplorer.lima-city.de/LinkTest/test.php
//Bei Lima-City.de als Startpunkt sind es gerade 916 Seiten in 3Min -> 5 /s
//Gerade gesehen, Facebook z.bsp meint "Browser aktualisieren". WIe kommt man denn da drum...
Beitrag zuletzt geändert: 17.12.2017 17:08:12 von horstexplorer -
horstexplorer schrieb:
Das Mysql kann also auch so aussehen?:
[...]
Also dass man nur einmal die Verbindung öffnen muss
Freilich. Wenn dir irgendein Tutorial oder so sagt, es wäre notwenig nach jeder Query eine neue Verbindung aufzumachen kannst du das direkt in die Tonne kloppen.
(Muss man das in jeder Funktion erneut machen oder reicht einmal ganz am Anfang und $mysqli als global?)
Warum solltest du das in jeder Funktion einzeln machen müssen? Der Geltungsbereich ist der selbe wie bei anderen Variablen.
Ich bringe hier nochmal OOP ins Spiel, dann kannste die Datenbank-Dinge auch schön und easy als Singleton umsetzen.
Gerade gesehen, Facebook z.bsp meint "Browser aktualisieren". WIe kommt man denn da drum...
Einfach einen passenden User-Agent bei den Anfragen mit senden -
muellerlukas schrieb:
horstexplorer schrieb:
Das Mysql kann also auch so aussehen?:
[...]
Also dass man nur einmal die Verbindung öffnen muss
Freilich. Wenn dir irgendein Tutorial oder so sagt, es wäre notwenig nach jeder Query eine neue Verbindung aufzumachen kannst du das direkt in die Tonne kloppen.
(Muss man das in jeder Funktion erneut machen oder reicht einmal ganz am Anfang und $mysqli als global?)
Warum solltest du das in jeder Funktion einzeln machen müssen? Der Geltungsbereich ist der selbe wie bei anderen Variablen.
Habe das immer wieder Copy-Paste eingefügt und deswegen nicht drüber nach gedacht wie es aussehen kann :D
Ich bringe hier nochmal OOP ins Spiel, dann kannste die Datenbank-Dinge auch schön und easy als Singleton umsetzen.
Gerade gesehen, Facebook z.bsp meint "Browser aktualisieren". WIe kommt man denn da drum...
Einfach einen passenden User-Agent bei den Anfragen mit senden
OOP ist mit von Java noch immer etwas gruselig, deswegen traue ich mich da erstmal nicht dran.
Wie geht des das mit dem User-Agent?
Hätte überlegt das es irgendwie mit
$_SERVER['HTTP_USER_AGENT'] = Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36;
funktionieren könnte, bezweifle ich aber trotzdem :D
//Habe gerade nachgelesen dass das mit
ini_set('user_agent', 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.47 Safari/536.11');
angeblich funktioniert. Getestet habe ich's noch nicht.
//Scheinbar geht es :)
Beitrag zuletzt geändert: 17.12.2017 22:52:57 von horstexplorer -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage