Zur Navigation

alle Links (auf auf Unterseiten) auflisten

1 webuser

Hallo,
wir haben bei uns auf der Homepage irgendwo noch Links zu "alten" Unterseiten.
Wie kann ich alle Seiten mit den Links finden?

Foldendes Script zeigt eine EINE Seite an:

<?php

    $url= 'http://www.xxxxx.de/index.php';

    $var = fread_url($url);

    preg_match_all ("/a[\s]+[^>]*?href[\s]?=[\s\"\']+".
                    "(.*?)[\"\']+.*?>"."([^<]+|.*?)?<\/a>/",
                    $var, &$matches);

    $matches = $matches[1];
    $list = array();

    foreach($matches as $var)
    {
        print($var."<br>");
    }


// The fread_url function allows you to get a complete
// page. If CURL is not installed replace the contents with
// a fopen / fget loop

    function fread_url($url,$ref="")
    {
        if(function_exists("curl_init")){
        echo $url."<br>----------------------------<br>";
            $ch = curl_init();
            $user_agent = "Mozilla/4.0 (compatible; MSIE 5.01; ".
                          "Windows NT 5.0)";
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
            curl_setopt( $ch, CURLOPT_HTTPGET, 1 );
            curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
            curl_setopt( $ch, CURLOPT_FOLLOWLOCATION , 1 );
            curl_setopt( $ch, CURLOPT_FOLLOWLOCATION , 1 );
            curl_setopt( $ch, CURLOPT_URL, $url );
            curl_setopt( $ch, CURLOPT_REFERER, $ref );
            curl_setopt ($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
            $html = curl_exec($ch);
            curl_close($ch);
        }
        else{
            $hfile = fopen($url,"r");
            if($hfile){
                while(!feof($hfile)){
                    $html.=fgets($hfile,1024);
                }
            }
        }
        return $html;
    }

?>
Es sollen aber alle verlinkten Seiten gezeigt werden.

Ideal wäre z.B. erst die Hauptseite, dann leicht eingerückt alle Links.
index.php
..eins.php
..zwei.php
..drei.html
-------------------------
unterseite1.php
..viel.php
..und so weiter....
-------------------------
unterseite2.php
..vielmehr.php
..und so weiter....

Es gibt zwar Tools die zeigen alle Links, aber nicht von welcher Seite der Link kommt.
(Ich habe jedenfalls das noch nicht gefunden)

Gruß
Uwe

15.08.2016 00:18

2 Jörg Kruse

Es sollen aber alle verlinkten Seiten gezeigt werden.

Dazu bräuchtest du einen Crawler bzw. Spider. Im Prinzip müssen die vom Crawler gefunden URLs, die auf die selbe Domain zeigen, zwischengespeichert und dann wiederum abgearbeitet werden. So etwas zu programmieren ist nicht ganz unaufwendig, zumal auch noch die Laufzeitbeschränkung von PHP zu beachten ist. Mit den Suchbegriffen "php crawler" oder "php spider" lassen sich aber Bibliotheken und Scripte finden, auf die man aufbauen kann.

15.08.2016 10:17

3 webuser

Hallo,
danke für die Rückinfo.
Ich habe dann nachfolgendes Script gefunden:

<?php
//set_time_limit (0);
function crawl_page($url, $depth = 5){
$seen = array();
if(($depth == 0) or (in_array($url, $seen))){
    return;
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
$result = curl_exec ($ch);
curl_close ($ch);
if( $result ){
    $stripped_file = strip_tags($result, "<a>");
    preg_match_all("/<a[\s]+[^>]*?href[\s]?=[\s\"\']+"."(.*?)[\"\']+.*?>"."([^<]+|.*?)?<\/a>/", $stripped_file, $matches, PREG_SET_ORDER );
    foreach($matches as $match){
        $href = $match[1];
            if (0 !== strpos($href, 'http')) {
                $path = '/' . ltrim($href, '/');
                if (extension_loaded('http')) {
                    $href = http_build_url($href , array('path' => $path));
                } else {
                    $parts = parse_url($href);
                    $href = $parts['scheme'] . '://';
                    if (isset($parts['user']) && isset($parts['pass'])) {
                        $href .= $parts['user'] . ':' . $parts['pass'] . '@';
                    }
                    $href .= $parts['host'];
                    if (isset($parts['port'])) {
                        $href .= ':' . $parts['port'];
                    }
                    $href .= $path;
                }
            }
            crawl_page($href, $depth - 1);
        }
}
echo "Crawled {$href}";
}
crawl_page("http://www.meineseite.de/",3);
?>

Das Programm läuft einen kurzen Moment und dann wird diese angezeigt:
Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled Crawled :///#top


Soweit ich das Script verstehe, müßte es doch 5Seiten in die Tiefe gehen und dann alle Links zeigen.

Gruß
Uwe

15.08.2016 22:21

4 Jörg Kruse

Das Script ist wohl buggy. Es scheint dem Script auf stackoverflow.com sehr ähnlich:

http://stackoverflow.com/questions/2313107/how-do-i-make-a-simple-crawler-in-php

Letzteres ist möglicherweise das (mehrmals ausgebesserte) Original von deinem Code. Probier dieses Script mal, wobei du dir nur die URLs ausgeben lässt:

    echo "URL:",$url,PHP_EOL;

bzw. bei Aufruf über den Webbrowser:

    echo "URL:",$url,'<br/>';

Soweit ich das Script verstehe, müßte es doch 5Seiten in die Tiefe gehen und dann alle Links zeigen.

Wenn du den zweiten Parameter nicht angibst bzw. eine 5. In dem Beispiel-Aufruf werden zwei Ebenen gespidert:

crawl_page("http://hobodave.com", 2);

16.08.2016 09:34 | geändert: 16.08.2016 09:39

5 webuser

Hallo Jörg,
das Script gibt es in verschiedenen Versionen.
Ich einige probiert. Dieses läuft:

http://www.webgalli.com/blog/script-to-create-a-php-site-crawl-robot-easily/
<?php
set_time_limit (0);
function crawl_robot($url, $depth = 5){
    $seen = array();
    if(($depth == 0) or (in_array($url, $seen))){
        return;
    }
    $seen[] = $url;
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
    $result = curl_exec ($ch);
    curl_close ($ch);
    if( $result ){
        $stripped_file = strip_tags($result, "<a>");
        preg_match_all("/<a[\s]+[^>]*?href[\s]?=[\s\"\']+"."(.*?)[\"\']+.*?>"."([^<]+|.*?)?<\/a>/", $stripped_file, $matches, PREG_SET_ORDER );
        foreach($matches as $match){
            $href = $match[1];
                if (0 !== strpos($href, 'http')) {
                    $path = '/' . ltrim($href, '/');
                    if (extension_loaded('http')) {
                        $href = http_build_url($href, array('path' => $path));

                    } else {
                        $parts = parse_url($href);
                        $href = $parts['scheme'] . '://';
                        if (isset($parts['user']) && isset($parts['pass'])) {
                            $href .= $parts['user'] . ':' . $parts['pass'] . '@';

                        }
                        $href .= $parts['host'];
                        if (isset($parts['port'])) {

                            $href .= ':' . $parts['port'];

                        }
                        $href .= $path;

                       }
                }


                crawl_robot($href, $depth - 1);
            }

        }
        echo "URL:",$url,'<br/>';

    }

crawl_robot("http://www.meineseite.de/",5);
?>
Was noch fehlt ist die Seite von der der Link kommt.

So sieht es jetzt aus:
URL::///#top
URL::///link1.php
URL::///adsaf.php
URL::///contact.php
URL::///suchen.php
URL::///neu.php
URL::///#top
......

Gruß
Uwe

16.08.2016 18:51

6 Jörg Kruse

Das Script hat einen üblen Bug:

crawl_robot($href, $depth - 1);

Da dieser Aufruf in der foreach Schleife steht, wird $depth nicht pro Ebene um 1 herabgesetzt, sondern pro URL, die gecrawlt wird! nach fünf Seiten ist dann Schluss.

Was noch fehlt ist die Seite von der der Link kommt.

Das könnte man dadurch realisieren, dass die Ausgabe der Seite vor einer foreach Schleife steht, und die Ausgabe einer gefundenen URL innerhalb der Schleife

Ich habe mal das Script von stackoverflow.com entsprechend angepasst (da dieses wenigstens halbwegs ordentlich gecodet ist):

<?php
function crawl_page($url, $depth = 5)
{
    static $seen = array();
    if ($depth === 0) {
        return;
    }
    $depth = $depth - 1;

    $seen[$url] = true;

    $dom = new DOMDocument('1.0');
    @$dom->loadHTMLFile($url);

    $anchors = $dom->getElementsByTagName('a');
    if ($anchors) {
        echo "<br/>Seite:",$url,'<br/>';
    }
    foreach ($anchors as $element) {
        $href = $element->getAttribute('href');
        if (0 !== strpos($href, 'http')) {
            $path = '/' . ltrim($href, '/');
            if (extension_loaded('http')) {
                $href = http_build_url($url, array('path' => $path));
            } else {
                $parts = parse_url($url);
                $href = $parts['scheme'] . '://';
                if (isset($parts['user']) && isset($parts['pass'])) {
                    $href .= $parts['user'] . ':' . $parts['pass'] . '@';
                }
                $href .= $parts['host'];
                if (isset($parts['port'])) {
                    $href .= ':' . $parts['port'];
                }
                $href .= $path;
            }
        }
        echo "URL:",$href,'<br/>';
        if (! isset($seen[$href])) {
            crawl_page($href, $depth);
        }
    }
}
crawl_page("http://example.com/", 3);

Die Überprüfung, ob eine URL bereits als Key in $seen enthalten ist, habe ich dabei auch in die Schleife verlegt, so dass sich diese nur auf die zu crawlenden Seiten auswirkt und nicht auf die gefundenen URLs

16.08.2016 22:41

7 webuser

Hallo,
danke für deine Bemühungen.
Leider wird nur eine Zeile gezeigt:

Seite:http://www.meine seite.de/

Gruß Uwe

17.08.2016 22:12

8 Jörg Kruse

Bei mir funktioniert's

Wird auch bei anderen Domains nur die Seite angezeigt? beispielsweise:

crawl_page("https://joergs-forum.de/", 1);

... ergibt bei mir:

Seite:https://joergs-forum.de/
URL:https://joergs-forum.de/
URL:https://joergs-forum.de/browser-f-9-1
URL:https://joergs-forum.de/html-und-css-f-2-1

[...]

URL:https://jkip.de
URL:https://blog.jkip.de/
URL:https://jkbb.de/

Falls nein: ist in deinem PHP das Modul dom geladen? Hier sollte ein Abschnitt "dom" erscheinen:

phpinfo(INFO_MODULES);

Standardmäßig ist das Modul aktiviert.

18.08.2016 10:32

9 Jörg Kruse

In der phpinfo() Ausgabe, die du mir zugesandt hast, ist das DOM-Modul aktiviert ("enabled"). Die libxml Version ist allerdings schon etwas älter

Wenn du hier das @ Zeichen entfernst:

    @$dom->loadHTMLFile($url);

... wird dann eine Fehlermeldung ausgegeben?

Wenn das DOM-Modul bei dir nicht funktioniert, kannst du zur Extraktion der Link-URLs alternativ die Regex-Lösung mit preg_match_all() aus dem anderen Script verwenden (welches nur zweite Wahl ist, weil man das Parsen von HTML mithilfe von Regexen vermeiden sollte)

18.08.2016 22:23 | geändert: 18.08.2016 22:24

Beitrag schreiben (als Gast)

Die Antwort wird nach der Überprüfung durch einen Moderator freigeschaltet.





[BBCode-Hilfe]