1. #1

    Registriert seit
    01.12.2011
    Beiträge
    4
    Thanked 0 Times in 0 Posts

    Standard [PHP] HTML Crawlbot

    Hallo alle zusammen,

    ich bin zwar neu hier, versuche mich aber mal direkt zu integrieren. Was ich hier poste ist ein Crawlbot, geschrieben mit PHP.


    Was macht ein Crawlbot?
    Dieser spezielle Crawlbot durchsucht Websites nach Hyperlinks, speichert diese Hyperlinks in einer "Liste" in einer Datenbank (ich habe mySQL benutzt, Anbindung an Postgres oder ODBC Datenbanken möglich!) und arbeitet die Liste dann weiter ab.


    Welche Funktionen hat der Bot noch?

    - Er prüft ob eine Website online ist
    - Er prüft ob Robots erlaubt sind
    - Er parsed die Seite und sucht nach Links
    - Er prüft ob der neue Link bereits in der Datenbank steht

    Wie kann man den Bot erweitern?
    Zur Zeit speichert der Bot keine Metatags wie keyword, description oder title. Man kann den Sourcecode aber leicht erweitern (siehe Step #6)

    Die Anbindung an die Datenbank erfolgt über eine PDO - Klasse (PDO wird ab PHP 5.3 von php.net empfohlen!), dadurch ist auch eine Anbindung an Postgres oder ODBC möglich!

    Wie crawlt der Bot automatisch?
    Es gibt zum einen die Möglichkeit das "crawlen" manuell zu halten, in dem man die Seite mit dem PHP script selbst aufruft, zum anderen gibt es die Möglichkeit das Script per CGI Befehl an PHP zu senden (z.B. in Windows) oder per Bash/Cronjob selbstständig aufzurufen (Unix)


    Hier der Sourcecode:

    main.php
    PHP-Code:
    <?
    /*
    Crawl Bot 

    Last Change: 30.08.2011

    Version: 3.0

    Author: Live0x00
            
            IRC: irc.freenode.net - ##code-aequitas
    */
        // Error Reporting is serious business
        
    error_reporting(E_ALL);

        
    // Including important classes and persistant DB connection
        
    require_once('dbcon.php');
        require_once(
    'tcpconnection.class.php');
        require_once(
    'httpconnection.class.php');
        require_once(
    'simple_html_dom.php');
        
        
    // Setting USER-Agent of our Crawler
         
    @ini_set('User-Agent','HTML CRAWLER - Live0x00'); 
         
         
         
    // Check if robots are allowed
        
    function robots_allowed($url$useragent=false
        { 
            
            
    $parsed parse_url($url); 

            
    $agents = array(preg_quote('*')); 
        
            if(
    $useragent$agents[] = preg_quote($useragent); 
            
    $agents implode('|'$agents); 

            
    $robotstxt = @file("http://{$parsed['host']}/robots.txt");
        
            if(!
    $robotstxt) return true
            
    $rules = array(); $ruleapplies false

            foreach(
    $robotstxt as $line
            { 
                if(!
    $line trim($line)) continue; # following rules only apply if User-agent matches $useragent or '*' 
                
    if(preg_match('/User-agent: (.*)/i'$line$match)) 
                { 
                    
    $ruleapplies preg_match('/($agents)/i'$match[1]);
                }
                if(
    $ruleapplies && preg_match('/Disallow:(.*)/i'$line$regs)) # an empty rule implies full access - no further tests required 
                

                    if(!
    $regs[1]) return true# add rules that apply to array for testing 
                    
    $rules[] = preg_quote(trim($regs[1]), '/'); 
                }
            } 
        
            foreach(
    $rules as $rule)  # check if page is disallowed to us 
            
    {
                if(
    preg_match("/^$rule/"$parsed['path'])) return false
            } 
    # page is not disallowed 
            
    return true
        } 
        
        
    // BEGIN OF THE ACTUAL CRAWLER
        
            # check ON/OFF settings
                
    $dbr "SELECT onoff FROM settings WHERE crawlerid = 1";
            
                
    # PDO works with FOREACH even if we're awaiting ONLY ONE result
                
    foreach ($dbh->query($dbr) as $row) {
                    if(
    $row[0] == 1)
                    {
                        
    # IF ONOFF IS SET TO 1 THE CRAWLER IS OFFLINE - script automatically ends
                        
    die('Crawler not running!');
                    }
                }
                
    # FREE DBR variable for further use
                
    unset($dbr);
                
            
    # STEP 1: GET url,qid of the next website out of the database
            
                
    $dbr "SELECT qid,url FROM queue_main ORDER BY qid ASC LIMIT 1";
                foreach (
    $dbh->query($dbr) as $row) {
                    
    $nextwebsite_url $row['url'];
                    
    $nextwebsite_id $row['qid'];
                }
                
    # FREE DBR variable for further use
                
    unset($dbr);
                
            
    # STEP 2: DELETE URL FROM QUEUE
            
                
    $statement_delete $dbh->prepare("DELETE from queue_main WHERE qid = ? AND url = ?");
                
    $statement_delete->bindParam(1$nextwebsite_id);
                
    $statement_delete->bindParam(2$nextwebsite_url);
                
    $statement_delete->execute();
            
            
    # STEP 3: CHECK IF WEBSITE IS AVAILABLE
            
                
    $nextwebsite_url stripslashes($nextwebsite_url);
                
    $parsed parse_url($nextwebsite_url);
                
                
    $checkhead = new httpconnection($parsed['host']);
                
    $nextwebsite_parsed $parsed['path'];
                
                if(isset(
    $parsed['query']))
                {
                    if(!empty(
    $parsed['query'])) 
                    {
                        
    $nextwebsite_parsed .= $parsed['query'];    
                    }
                }
            
                if(isset(
    $parsed['fragment']))
                {
                    if(!empty(
    $parsed['fragment'])) 
                    {
                        
    $nextwebsite_parsed .= $parsed['fragment'];    
                    }
                }
            
                
    $data $checkhead->head($nextwebsite_parsed);
                
    $responsecode $data['head']['code'];
            
                if((
    $responsecode != '200') and ($responsecode != '201') and ($responsecode != '202'))
                {
                    if((
    $responsecode == '301') or ($responsecode == '302'))
                    {
                        
    $responselocation $data['head']['location']['uri'];
                        
    $nextwebsite_url $responselocation;
                        echo 
    'Code 302 Found, new location: '.$nextwebsite_url.' used!<br /><br />';
                    }
                    else
                    {
                        die(
    'No Data found.');
                    }
                }
                unset(
    $checkhead);
            
            
    # STEP 4: CHECK FOR ROBOTS
                
                
    if(!robots_allowed($nextwebsite_urlHTML Crawl Bot'))
                {
                die('
    No Robots allowed.');
                }
            
            # STEP 5: CHECK FOR CONTENT TYPE - TEXT/HTML ALLOWED
            
                $urlheaders = $nextwebsite_url;
                $headermime = get_headers($urlheaders, 8);

                    if(!$headermime = "Content-Type: text/html")
                    {
                        die('
    Content Type not TEXT/HTML');
                    }
                    
            # STEP 6: CRAWL META TAGS - Checking for keywords, description, title
            
            # STEP 7: PARSE FOR HTML LINKS
            
                $html = file_get_html($nextwebsite_url);
                
                # PREPARE SQL STATEMENT FOR FASTER USAGE AND INCREASED PERFORMANCE
                $statement = $dbh->prepare("INSERT INTO queue_main (url) VALUES (:url)");
                $statement->bindParam('
    :url', $url_to_insert);
                
                $statement_select = $dbh->prepare("SELECT qid,url FROM queue_main WHERE url = ?");

                foreach($html->find('
    a') as $e)
                    {
                        $url = $e->href;

                        if (preg_match('
    /^(http|https):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_ ]*)+):?(\d+)?\/?/i', $url)) {
                        
                            # CHECK if website is already in queue, if yes skip it from inserting into database
                            if($statement_select->execute(array($url)))
                            {
                                if(!count($statement_select->fetchAll()) > 0) {
                            
                                    $url_to_insert = $e->href;
                                    $statement->execute();
                        
                                }
                                else {
                                    echo "Website ". $url ." already in queue! <br />";
                                }
                            }
                        }
                    }

                    $html->clear();    
                    
            # STEP 8: Final Output
            
            echo "Processing queue...";
    ?>

    dbcon.php
    PHP-Code:
    <?
    /*

    DATABASE CONNECTION

    */
    error_reporting(E_ALL);

    Class 
    SafePDO extends PDO {
     
            public static function 
    exception_handler($exception) {
                
    // Output the exception details
                
    die('Uncaught exception: '$exception->getMessage());
            }
     
            public function 
    __construct($dsn$username=''$password=''$driver_options=array()) {

                
    // Temporarily change the PHP exception handler while we . . .
                
    set_exception_handler(array(__CLASS__'exception_handler'));

                
    // . . . create a PDO object
                
    parent::__construct($dsn$username$password$driver_options);

                
    // Change the exception handler back to whatever it was before
                
    restore_exception_handler();
            }

    }

    // Connect to the database with defined constants
    $dbh = new SafePDO('mysql:host=localhost;dbname=test'testuser', 'testpass', array(PDO::ATTR_PERSISTENT => TRUE ));
    ?>
    Am wichtigsten ist wohl die HTML Parser Klasse.
    Hier gibt es Abhilfe. Ich habe den HTML Parser von PHP Simple HTML DOM Parser | Free Development software downloads at SourceForge.net genommen. Dieser funktioniert zuverlässig und schnell.

    Für die Httpconnection und tcpconnection class, kann man sich derer von PHP Class Collection bedienen. Die gibt es sowohl für ältere PHP Versionen, als auch für die neusten.

    // Edit

    Wie Comu bereits beschrieb, ist der Robot Parser von http://www.the-art-of-web.com/php/parse-robots/

  2. #2
    Avatar von Comu
    Registriert seit
    18.11.2011
    Beiträge
    772
    Thanked 753 Times in 363 Posts

    Standard [PHP] HTML Crawlbot

    Scheint wohl von hier kopiert zu sein Parsing robots.txt < PHP | The Art of Web ?

  3. #3

    Registriert seit
    01.12.2011
    Beiträge
    4
    Thanked 0 Times in 0 Posts

    Standard [PHP] HTML Crawlbot

    Die Robot-Funktion, richtig, habe ich vergessen anzuhängen

  4. #4
    Avatar von AFU
    Registriert seit
    19.11.2011
    Beiträge
    359
    Thanked 75 Times in 61 Posts

    Standard [PHP] HTML Crawlbot

    Wenn das ganze noch für Knuddels modifiziert wird, wirds intressant

  5. #5

    Registriert seit
    01.12.2011
    Beiträge
    4
    Thanked 0 Times in 0 Posts

    Standard [PHP] HTML Crawlbot

    Was genau soll denn für Knuddels modifiziert werden? Dass er nur innerhalb der Knuddels URLs parsed?

Ähnliche Themen

  1. HTML Editor
    Von Shane im Forum HTML
    Antworten: 5
    Letzter Beitrag: 21.10.2014, 21:04
  2. HTML/ SQL Grundlagen?
    Von x BoooM x im Forum Skriptsprachen
    Antworten: 3
    Letzter Beitrag: 14.01.2014, 17:00
  3. Antworten: 0
    Letzter Beitrag: 14.10.2012, 20:07
  4. HTML Templates?
    Von x BoooM x im Forum HTML
    Antworten: 1
    Letzter Beitrag: 28.01.2012, 17:11
  5. HTML-Einführung
    Von Dost im Forum Skriptsprachen
    Antworten: 16
    Letzter Beitrag: 19.10.2011, 21:23
Diese Seite nutzt Cookies, um das Nutzererlebnis zu verbessern. Klicken Sie hier, um das Cookie-Tracking zu deaktivieren.