tutorials.de Buch-Aktion 05/2012
ERLEDIGT
JA
ANTWORTEN
7
ZUGRIFFE
292
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    NTDY NTDY ist offline Mitglied Gold
    Registriert seit
    Mar 2004
    Ort
    no-comment
    Beiträge
    136
    Ich habe ein Skript geschrieben, das auf einer Webseite alle Hyperlinks einsammelt. Leider ist die Perfomance noch nicht gut genug und das Skript beendet sich nach 5 Minuten. Hat jemand eine Idee, wie man diesen Algorithmus verbessern kann?


    PHP-Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>Sucker</title>
    <style type="text/css">
    *,body{
    font-family:"Courier New", Courier, monospace;
    font-size:12px;
    }
    </style>
    </head>

    <body>
    <pre>
    <?php
    global $linkpuffer;

    function 
    suche_komplett_www($url){
        
    //Seite einlesen
        
    $zeile=@file_get_contents($url);
        
    // Pattern für Hyperlinks
        
    $pattern '=^(.*)<a(.*)href\="?(\S+)"([^>]*)>(.*)</a>(.*)$=msi';
        
    //solange ein Hyperlink noch gefunden wird, lesen
        
    while (preg_match($pattern$zeile$txt)){
        
            
    //txt[3] ist der Hyperlink
            
    if(preg_match("/http:/",$txt[3])){
            }elseif(
    preg_match("/Javascript:/i",$txt[3])){
            }elseif(
    preg_match("/.pdf/i",$txt[3])){
            }else{
                
    $variable $txt[3];
                if(
    substr($variable,0,2)=="./"){
                    
    //echo $variable." (mit ./)<br>";                        
                    // nun den Punkt (.) am Anfang loeschen
                    
    $variable substr($variable,1,strlen($variable)-1); 
                    
    $in_puffer=$url.$variable;
                    
    //echo $variable." (./ entfernen)<br>";
                    
    echo $variable."<br>";                
                    if(@
    array_search($variable,$linkpuffer)!=true){
                        
    $linkpuffer[] = $variable;
                        
    suche_komplett_www($in_puffer);                    
                    }        
                }elseif(
    substr($variable,0,1)=="/"){
                    
    //echo $variable." (mit /)<br>";
                    
    $in_puffer=$url.$variable;
                    
    //echo $variable." (/ entfernen)<br>";
                    
    echo $variable."<br>";
                    
    //wenn Wert noch nicht im Array, dann einfügen
                    
    if(@array_search($variable,$linkpuffer)!=true){
                        
    $linkpuffer[] = $variable;
                        
    suche_komplett_www($in_puffer);
                    }
                }else{
        
                    
    $variable="/".$variable;            
                    
    $in_puffer=$url."/".$variable;            
                    echo 
    $variable."<br>";                
                    if(@
    array_search($variable,$linkpuffer)!=true){
                        
    $linkpuffer[] = $variable;
                        
    suche_komplett_www($in_puffer);                    
                    }        
                }        
            }
          
    $zeile $txt[1]." hier war mal ein Link ".$txt[6];    
        }
        return 
    $linkpuffer;
    }

    $linkpuffer=suche_komplett_www("http://www.tech-island.com/technet/techtalk/rekursiv_programmieren");

    echo 
    "<hr>";
    echo 
    "<pre>";
    print_r($linkpuffer);
    echo 
    "</pre>";

    ?>    
    </pre>
    </body>
    </html>
     

  2. #2
    Avatar von Enumerator
    Enumerator Enumerator ist offline Mitglied Kamel
    Registriert seit
    Jan 2007
    Ort
    Schreibtisch
    Beiträge
    525
    Blog-Einträge
    2
    Abend!
    1. Liest nicht die gesamte Datei/Site auf einmal. Arbeite zeilenweise.
    2. Benutze einen anderen Regulären ausdruck, z.B.
      Code :
      1
      
      /(href|src)="([^"])"/
    3. Filtere die URIs erst nachdem Du sie gesammelt hast
    Das für's erste - aber da geht noch mehr...

    Greetz
    Enum

    PS, als Schmankerl: Damit kannst Du URLs validieren, nachdem Du sie gefiltert hast: http://internet.ls-la.net/folklore/url-regexpr.html
    Geändert von Enumerator (03.12.08 um 23:04 Uhr)
     
    Zitat Zitat von Aba Assa
    "Zitate sind so etwas wie Outsourcing des Geistes."
    just-lyrics.org :: my-lyrics.org

  3. #3
    Registriert seit
    Dec 2002
    Ort
    Trier
    Beiträge
    17.502
    Blog-Einträge
    10
    Der reguläre Ausdruck ist wirklich ungeeignet. Auch würde ich erst die a-Tags heraussuchen und dann die Attribute auswerten.
    PHP-Code:
    '/<a(\s+[^>]+)>/i' 
     
    Markus Wulftange

  4. #4
    Avatar von Enumerator
    Enumerator Enumerator ist offline Mitglied Kamel
    Registriert seit
    Jan 2007
    Ort
    Schreibtisch
    Beiträge
    525
    Blog-Einträge
    2
    Zitat Zitat von Gumbo Beitrag anzeigen
    Der reguläre Ausdruck ist wirklich ungeeignet. Auch würde ich erst die a-Tags heraussuchen und dann die Attribute auswerten.
    Es geht doch um Speed, richtig? Rekursive Hyperlinks? Quasi ein reiner Link-Crawler? Dann ist jede Vereinfachung des 1. regulären Ausdrucks ein Zeitgewinn, der sich mit der Laufzeit potenziert. Und href Attribute sind so ziemlich das einzige, was dann noch interessiert. Die srcs eventuell auch, wenn man Bilder haben möchte - aber war ja nur ein Beispiel.
    Ich bin davon überzeugt, dass man die Applikation mehrgleisig fahren muss, wenn man wirklich performant arbeiten will - Threads die Sammeln (mit einfachem RegEx) und Threads die Filtern...

    Greetz
    Enum
     
    Zitat Zitat von Aba Assa
    "Zitate sind so etwas wie Outsourcing des Geistes."
    just-lyrics.org :: my-lyrics.org

  5. #5
    NTDY NTDY ist offline Mitglied Gold
    Registriert seit
    Mar 2004
    Ort
    no-comment
    Beiträge
    136
    Hat jemand eine Idee, wie man meinen Algorithmus terminatorieren lassen kann?

    Die Funktion sammelt ja alle Links heraus, verwirft bereits welche, die nicht zur Seite gehören und baut dann Links zusammen, die dann wieder in die Funktion gehen.

    ./ETWAS.HTML
    werden zu http://www.seite.de/ETWAS.HTML

    /ETWAS.HTML
    werden zu http://www.seite.de/ETWAS.HTML
    usw.

    Ich komme aber nicht auf die Idee, wie man die Rekursion stoppen kann?


    PHP-Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>Sucker</title>
    <style type="text/css">
    *,body{
    font-family:"Courier New", Courier, monospace;
    font-size:12px;
    }
    </style>
    </head>

    <body>
    <pre>
    <?php

    function suche_komplett_www($url,$pufferarray,$uri="http://www.comicportal.de"){
            
    $puffer=@file($url);
            foreach(
    $puffer as $zeile){
                
    $pattern '=^(.*)<a(.*)href\="?(\S+)"([^>]*)>(.*)</a>(.*)$=msi';    
                
    //$pattern='/<a(\s+[^>]+)>/i';
                
    if(preg_match($pattern$zeile$txt)==true){
                    if(
    preg_match("/http:/",$txt[3])){
                    }elseif(
    preg_match("/Javascript:/i",$txt[3])){
                    }elseif(
    preg_match("/.pdf/i",$txt[3])){
                    }else{
                        
    $variable $txt[3];
                        
    //Link ist ein ./ Link
                        
    if(substr($variable,0,2)=="./"){
                            
    $variable substr($variable,1,strlen($variable)-1);
                            
    $in_puffer=$uri.$variable;
                            if(
    in_array($in_puffer,$pufferarray)!=true){
                                
    $pufferarray[] = $in_puffer;
                                echo 
    "1 ->".$in_puffer."<-\n";                        
                                
    suche_komplett_www($in_puffer,$pufferarray);                    
                            }                                            
                        }elseif(
    substr($variable,0,1)=="/"){
                            
    $in_puffer=$uri.$variable;            
                            
    //print_r($pufferarray)."..\n";
                            //echo $in_puffer."...\n";                
                            
    if(in_array($in_puffer,$pufferarray)!=true){
                                
    $pufferarray[] = $in_puffer;
                                echo 
    "2 ->".$in_puffer."<-\n";                        
                                
    suche_komplett_www($in_puffer,$pufferarray);                    
                            }                                    
                        }else{
                            
    $variable="/".$variable;            
                            
    $in_puffer=$uri.$variable;    
                            if(
    in_array($in_puffer,$pufferarray)!=true){
                                
    $pufferarray[] = $in_puffer;
                                echo 
    "3 ->".$in_puffer."<-\n";                        
                                
    suche_komplett_www($in_puffer,$pufferarray);                    
                            }        
                        }
                    }
                }
            }
        return 
    $linkpuffer;
    }



    $pufferarray = array();
    echo 
    "<textarea cols='160' rows='40'>";
    $valurl="http://www.comicportal.de";
    $linkpuffer=suche_komplett_www($valurl,$pufferarray,$valurl);
    echo 
    "</textarea>";    

    echo 
    "<hr>";
    echo 
    "<pre>";
    print_r($linkpuffer);
    echo 
    "</pre>";

    ?>    
    </pre>
    </body>
    </html>
     

  6. #6
    Registriert seit
    Dec 2002
    Ort
    Trier
    Beiträge
    17.502
    Blog-Einträge
    10
    Ich würde gar keine Rekursion verwenden, da sonst bei jeder Rekursion der benötigte Speicher (allein durch die Initialisierung der Variablen) immer weiter steigt. Stattdessen würde ich die gesammelten Links sequenziell abarbeiten. Das kannst du rein schematisch wie folgt machen:
    PHP-Code:
    $unvisited = array('http://localhost/start');
    $visited = array();
    while (
    $url array_shift($unvisited)) {
        if (
    $content file_get_contents($url)) {
            
    // neue URLs werden gesammelt
            // …
        
    }
        
    $visited[] = $url;
        foreach (
    $newUrls as $newUrl) {
            if (!
    in_array($newUrl$visited) && !in_array($newUrl$unvisited)) {
            
    // nur neue URLs werden aufgenommen
                
    $unvisited[] = $newUrl;
            }
        }

    Geändert von Gumbo (04.12.08 um 21:09 Uhr) Grund: Auf Hinweis von NTDY korrigiert
     
    Markus Wulftange

  7. #7
    NTDY NTDY ist offline Mitglied Gold
    Registriert seit
    Mar 2004
    Ort
    no-comment
    Beiträge
    136
    Hallo Gumbo,
    vielen Dank für die Gedankenstütze. Ich habe nun ein fertiges Skript heraus (für alle, die es interessiert).

    PHP-Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>Unbenanntes Dokument</title>
    </head>

    <body>
    <?php
    $uri
    ="http://www.intel.com/";
    $unvisited = array($uri);
    $visited = array();
    while (
    $url array_shift($unvisited)) {
        
    $puffer=@file($url);
        foreach(
    $puffer as $zeile){
            
    $pattern '=^(.*)<a(.*)href\="?(\S+)"([^>]*)>(.*)</a>(.*)$=msi';
            if(
    preg_match($pattern$zeile$txt)==true){
                
    $variable $txt[3];
                if(
    preg_match("/http:/",$variable)){
                }elseif(
    preg_match("/Javascript:/i",$variable)){
                }elseif(
    preg_match("/.pdf/i",$variable)){
                }elseif(
    substr($variable,0,2)=="./"){
                    
    // "./" wurde entfernt
                    
    $variable substr($variable,2,strlen($variable)-1);
                    
    $in_puffer=$uri.$variable;
                    
    $newUrls[] = $in_puffer;
                    
    //echo $in_puffer;
                
    }elseif(substr($variable,0,1)=="/"){
                    
    $variable substr($variable,1,strlen($variable)-1);
                    
    $in_puffer=$uri.$variable;                
                    
    $newUrls[] = $in_puffer;
    //                echo $in_puffer."<br>";            
                
    }else{
                    
    $in_puffer=$uri.$variable;                    
                    
    $newUrls[] = $in_puffer;
                    
    //echo $in_puffer."<br>";
                
    }
            }
            
    // neue URLs werden gesammelt
            // …
        
    }
        
    $visited[] = $url;
        foreach (
    $newUrls as $newUrl) {
            if (!
    in_array($newUrl$visited) && !in_array($newUrl$unvisited)) {
            
    // nur neue URLs werden aufgenommen
                
    $unvisited[] = $newUrl;
            }
        }    
    }

    echo 
    "<pre>";
    print_r($visited);
    echo 
    "</pre>";
    ?>
    </body>
    </html>
    Geändert von NTDY (04.12.08 um 21:50 Uhr)
     

  8. #8
    Avatar von DeeJTwoK
    DeeJTwoK DeeJTwoK ist offline Mitglied Brokat
    Registriert seit
    Jan 2004
    Beiträge
    342
    Hallo,
    sorry, dass ich hier noch mal nachhake, aber ich erkenne noch keinen Sinn in diesen Abfragen:
    PHP-Code:
    if(preg_match("/http:/",$variable)){
    }elseif(
    preg_match("/javascript:/i",$variable)){
    }elseif(
    preg_match("/.pdf/i",$variable)){
    }elseif(
    substr($variable,0,2)=="./"){ 
    Es soll also nur etwas gemacht werden wenn das Ziel mit ./ anfängt. Wenn es dies tut, wird wohl kaum noch ein hhtp: oder ein javascript: vorkommen. Warum machst du es nicht einfach so:
    PHP-Code:
    if(substr($variable,0,2)=="./" and !preg_match("/.pdf$/i",$variable)){ 
    "WENN der String mit ./ anfängt und nicht auf .pdf endet, DANN..."

    Da es hier ja um Performance geht, könnte das helfen, oder?

    Grüße und so
    DJ
     
    Hilfreiche Beiträge dürfen gerne über den Stern oder den "Danke" Button unter jedem Post positiv bewertet werden ;) Danke...

Ähnliche Themen

  1. Kombinationen über rekursiven Algorithmus berechnen?
    Von smartin123 im Forum Algorithmen & Datenstrukturen mit Java
    Antworten: 4
    Letzter Beitrag: 19.08.10, 11:38
  2. Problem mit dem rekursiven Einlesen von Verzeichnissen
    Von rpoehlert im Forum .NET Café
    Antworten: 2
    Letzter Beitrag: 18.03.10, 22:12
  3. MS SQL Server - Definition einer rekursiven Beziehung (m:n)
    Von Tarik_BS im Forum Relationale Datenbanksysteme
    Antworten: 2
    Letzter Beitrag: 27.12.07, 14:10
  4. Antworten: 3
    Letzter Beitrag: 25.07.07, 10:24
  5. Rendern verschnellern
    Von mibsteve im Forum Cinema 4D
    Antworten: 2
    Letzter Beitrag: 30.04.07, 18:28