Beispiel #1
0
        public string getURL(string URL, page p, bool followRedirects)
        {
            errorString = String.Empty;
            contentType = String.Empty;
            statusCode  = 0;
            HTML        = String.Empty;

            try
            {
                HttpWebRequest request = HttpWebRequest.Create(URL) as HttpWebRequest;

                // imposta l'user-agent
                request.UserAgent = GlobalVars.OpenWebSpider.USERAGENT;

                // imposta il timeout (default: un minuto 60.000 ms)
                request.Timeout = GlobalVars.args.reqTimeout * 1000;

                // segue i redirect
                if (followRedirects)
                {
                    request.AllowAutoRedirect            = true;
                    request.MaximumAutomaticRedirections = 5;
                }
                else
                {
                    request.AllowAutoRedirect = false;
                }

                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                if (response.CharacterSet == null)
                {
                    return(HTML);
                }

                // Support to Encodings
                Encoding responseEncoding;
                responseEncoding = Encoding.UTF8;   //default UTF-8
                if (response.CharacterSet.Trim() != "")
                {
                    responseEncoding = Encoding.GetEncoding(response.CharacterSet);
                }

                StreamReader sr           = new StreamReader(response.GetResponseStream(), responseEncoding);
                BinaryReader binaryStream = new BinaryReader(response.GetResponseStream());

                statusCode = (int)response.StatusCode;

                contentType = response.Headers["Content-Type"];

                // il content-type di questa pagina è testo?
                if (contentType.StartsWith("text", StringComparison.CurrentCultureIgnoreCase))
                {
                    HTML = sr.ReadToEnd();
                }
                else if (GlobalVars.args.indexMP3 && contentType.ToLower() == "audio/mpeg")
                {
                    // se sappiamo chi è il padre e ha un hostID valido allora indicizza l'MP3
                    if (p != null)
                    {
                        if (p.isValidPage && p._hostID > 0)
                        {
                            string fullPath = binaryStream2MD5File(p, binaryStream, response.Headers["Content-Type"], response.Headers["Content-Length"]);

                            mp3 MP3 = new mp3(fullPath);
                            deleteFile(fullPath);

                            MP3.mp3Size = int.Parse(response.Headers["Content-Length"]);

                            db __db = new db();
                            __db.indexMP3(p, MP3);
                        }
                    }
                }
                else if (GlobalVars.args.indexPDF && contentType.ToLower() == "application/pdf")
                {
                    // se sappiamo chi è il padre e ha un hostID valido allora indicizza il PDF
                    if (p != null)
                    {
                        if (p.isValidPage && p._hostID > 0)
                        {
                            string fullPath = binaryStream2MD5File(p, binaryStream, response.Headers["Content-Type"], response.Headers["Content-Length"]);

                            pdf PDF = new pdf(fullPath);
                            deleteFile(fullPath);

                            db __db = new db();
                            __db.indexPDF(p, int.Parse(response.Headers["Content-Length"]), PDF.pdfText);
                        }
                    }
                }
                else
                {
                    HTML = string.Empty;
                }

                // forza l'encoding corrente a UTF-8
                Encoding utf8 = Encoding.Unicode;

                byte[] responseEncodingBytes = responseEncoding.GetBytes(HTML);

                byte[] utf8Bytes = Encoding.Convert(responseEncoding,
                                                    utf8,
                                                    responseEncodingBytes);

                HTML = utf8.GetString(utf8Bytes);

                sr.Close();
            }
            catch (WebException e)
            {
                // TODO: in caso di 404 leggere ugualmente lo stream e ritornare l'HTML

                HttpWebResponse response = (HttpWebResponse)e.Response;
                if (response != null)
                {
                    // in caso di eccezione: prova a recuperare da qui lo status code
                    statusCode = (int)response.StatusCode;

                    if (response.StatusCode == HttpStatusCode.Unauthorized)
                    {
                        string challenge = null;
                        challenge = response.GetResponseHeader("WWW-Authenticate");
                        if (challenge != null)
                        {
                            errorString = "The following challenge was raised by the server:" + challenge;
                        }
                    }
                    else
                    {
                        errorString = "The following WebException was raised : " + e.Message;
                    }
                }
                else
                {
                    errorString = "Response Received from server was null";
                }
            }
            catch (Exception e)
            {
                errorString = "The following Exception was raised :" + e.Message;
            }

            return(HTML);
        }
Beispiel #2
0
        // indexer vero e proprio
        public void DoWork(object threadID)
        {
            page   pageToIndex;
            string outStr;

            // funzioni per l'accesso al DB
            db __db = new db();

            while (!_shouldStop)
            {
                System.Threading.Thread.Sleep(50);

                System.Threading.Thread.Sleep(0);

                if (GlobalVars.OpenWebSpider.crawlerActPAUSE)
                {
                    // aspetta ulteriore tempo
                    System.Threading.Thread.Sleep(300);

                    continue;
                }

                outStr = string.Empty;

                // nsGlobalOutput.output.write("Thread["+ (int)threadID +"]: working.");

                // blocca l'accesso alla lista degli URL da indicizzare e ne estrae uno ( se disponibile )
                GlobalVars.threadsVars.mutexAccessURLList.WaitOne();

                // cerca una pagina da indicizzare
                // se siamo in stress test mode: usa sempre la prima pagina
                if (GlobalVars.args.stressTest == true)
                {
                    pageToIndex = GlobalVars.threadsVars.currentDomain;
                }
                else
                {
                    pageToIndex = GlobalVars.urlsLists.getPageByStatus(0);
                }

                if (pageToIndex == null)
                {
                    // rilascia il mutex
                    GlobalVars.threadsVars.mutexAccessURLList.ReleaseMutex();
                    // riparte dall'inizio
                    continue;
                }
                else
                {
                    try
                    {
                        // imposta la pagina come "indicizzazione in corso"
                        pageToIndex.isIndexed = 2;

                        // rilascia il mutex
                        GlobalVars.threadsVars.mutexAccessURLList.ReleaseMutex();

                        // indicizza questa pagina!!!
                        html htmlPage = new html();

                        outStr = outStr + "\nT[" + (int)threadID + "] \t Downloading... [ " + pageToIndex.GenerateURL() + " ] [Depth Level: " + pageToIndex._depthLevel + "]\n";

                        // siamo in presenza di un Crawl-Delay ( da robots.txt o da riga di comando)
                        if (GlobalVars.robotstxtVars.robotstxtCrawlDelay > 0 || GlobalVars.args.crawlDelay > 0)
                        {
                            // locka il mutex
                            GlobalVars.threadsVars.mutexCrawlDelay.WaitOne();

                            // aspetta il tempo del Crawl-Delay
                            // se c'è un crawl-delay da robots.txt usa quello; altrimenti quello da riga di comando
                            int crawlDelay2Use = (GlobalVars.robotstxtVars.robotstxtCrawlDelay > 0) ? GlobalVars.robotstxtVars.robotstxtCrawlDelay * 1000 : GlobalVars.args.crawlDelay * 1000;
                            System.Threading.Thread.Sleep(crawlDelay2Use);
                        }

                        long curTick = DateTime.Now.Ticks;

                        // scarica la pagina
                        htmlPage.getURL(pageToIndex, true);

                        // siamo in presenza di un Crawl-Delay ( da robots.txt o da riga di comando)
                        if (GlobalVars.robotstxtVars.robotstxtCrawlDelay > 0 || GlobalVars.args.crawlDelay > 0)
                        {
                            // un-locka il mutex
                            GlobalVars.threadsVars.mutexCrawlDelay.ReleaseMutex();
                        }

                        outStr = outStr + "T[" + (int)threadID + "] \t Downloaded ";
                        if (htmlPage.HTML.Length > 0)
                        {
                            outStr = outStr + htmlPage.HTML.Length / 1024 + " Kb (" + htmlPage.HTML.Length + " bytes)";
                        }
                        outStr = outStr + " in " + ((DateTime.Now.Ticks - curTick) / 10000) + " ms\n";

                        outStr = outStr + "T[" + (int)threadID + "] \t HTTP Status Code: " + htmlPage.statusCode + " -][- Content-Type: " + htmlPage.contentType + "\n";

                        if (htmlPage.errorString != "")
                        {
                            outStr = outStr + "T[" + (int)threadID + "] \t Error: " + htmlPage.errorString + "\n";
                        }

                        // se non stiamo in stress test mode: allora parsa la pagina e indicizza
                        if (GlobalVars.args.stressTest == false)
                        {
                            // se lo status code (HTTP) è 200 (OK) e il content-type è "text/html" :: indicizza!
                            if (htmlPage.statusCode == 200)
                            {
                                if (htmlPage.contentType.StartsWith("text/html"))
                                {
                                    // siamo in una pagina HTML: controlla i META TAG
                                    htmlPage.checkMETA();

                                    // siamo in una pagina HTML: estrai il titolo <title>...</title>
                                    string __title = htmlPage.getTitle();
                                    if (__title != string.Empty)
                                    {
                                        pageToIndex._title = __title;

                                        // controlla che il titolo rientri nel limite del campo sul DB
                                        if (pageToIndex._title.Length > GlobalVars.dbLimits.maxTitleLength)
                                        {
                                            pageToIndex._title = pageToIndex._title.Substring(0, 255);
                                        }

                                        outStr = outStr + "T[" + (int)threadID + "] \t Page Title: " + __title + "\n";
                                    }

                                    curTick = DateTime.Now.Ticks;
                                    outStr  = outStr + "T[" + (int)threadID + "] \t Getting URLs...";
                                    if (htmlPage.META_ROBOTS_FOLLOW)
                                    {
                                        int nValidURLs = htmlPage.GetURLs(htmlPage.HTML, pageToIndex);
                                        outStr = outStr + "OK [" + ((DateTime.Now.Ticks - curTick) / 10000) + " ms]  ( " + nValidURLs + " valid URLs found )\n";
                                    }
                                    else
                                    {
                                        // NOFOLLOW
                                        outStr = outStr + "NOFOLLOW (META ROBOTS)\n";
                                    }
                                }

                                curTick = DateTime.Now.Ticks;
                                outStr  = outStr + "T[" + (int)threadID + "] \t Indexing...";
                                if (htmlPage.META_ROBOTS_INDEX)
                                {
                                    if (__db.indexThisPage(pageToIndex, htmlPage) == true)
                                    {
                                        outStr = outStr + "OK [" + ((DateTime.Now.Ticks - curTick) / 10000) + " ms]\n";
                                    }
                                    else
                                    {
                                        outStr = outStr + "NOT INDEXED [" + ((DateTime.Now.Ticks - curTick) / 10000) + " ms ]\n";
                                    }
                                }
                                else
                                {
                                    // NOINDEX
                                    outStr = outStr + "NOINDEX (META ROBOTS)\n";
                                }
                            }
                            else
                            {
                                GlobalVars.limits.curErrorCodes++;              // TODO: da testare gli error code che arrivano qui
                                Console.WriteLine(" ##  Error code: " + htmlPage.statusCode + "  ## ");
                            }
                        }

                        // incrementa il numero di pagine indicizzate
                        GlobalVars.limits.curPages++;

                        // incrementa i bytes indicizzati
                        GlobalVars.limits.curBytes += htmlPage.HTML.Length;
                    }
                    catch (Exception e)
                    {
                        outStr += "Error: " + e.Message + "\n";
                    }
                    finally
                    {
                        // imposta la pagina come "indicizzata"
                        if (GlobalVars.args.stressTest == false)
                        {
                            pageToIndex.isIndexed = 1;
                        }
                        else
                        {
                            // se siamo in stress-test: la mette come da indicizzare
                            pageToIndex.isIndexed = 0;
                        }

                        nsGlobalOutput.output.write(outStr);
                    }
                }
            }

            nsGlobalOutput.output.write("T[" + (int)threadID + "] \t Worker thread: terminating gracefully.");
        }
Beispiel #3
0
        // inizia l'indicizzazione
        public bool startCrawling()
        {
            // inizializza le liste degli URL da indicizzare e esterni(cache) + la lista delle relazioni
            GlobalVars.urlsLists.init();
            GlobalVars.externUrlsLists.init();
            GlobalVars.relsList.init();
            GlobalVars.imagesLists.init();

            // inizializza i thread
            threads = new threading();

            bool haveToIndexSomething = true;

            // funzioni per l'accesso al DBs
            db __db = new db();

            // attiva l'handler per la pressione di CTRL+C
            nsGlobalOutput.output.handleCTRLC();

            while (haveToIndexSomething)
            {
                // svuota le liste
                nsGlobalOutput.output.write(" + Clearing structures...");
                GlobalVars.urlsLists.clear();
                GlobalVars.externUrlsLists.l.Clear();
                GlobalVars.relsList.rels.Clear();
                GlobalVars.imagesLists.clear();

                nsGlobalOutput.output.write("");

                // init mutexes
                threads.initMutexes();

                if (isMysqlNeeded())
                {
                    // *******************************************************************
                    nsGlobalOutput.output.write(" + Checking connection to MySQL servers...");
                    if (GlobalVars.mysqlConn.connHostList.ping() == false || GlobalVars.mysqlConn.connPageList.ping() == false)
                    {
                        nsGlobalOutput.output.write("   - One or both MySQL server disconnected, trying to reconnect!");
                        if (mysqlConnect() == false)
                        {
                            nsGlobalOutput.output.write("   - Unable to connect to one or both MySQL server!");
                            break;
                        }
                    }
                    // *******************************************************************

                    // inserisce/aggiorna nel DB il sito corrente e ritorna l'hostID
                    GlobalVars.threadsVars.currentDomain._hostID = __db.startIndexThisSite(GlobalVars.threadsVars.currentDomain);
                }

                // a questo punto ha aggiunto l'HOST al DB: possiamo uscire
                if (GlobalVars.args.add2Hostlist == true)
                {
                    nsGlobalOutput.output.write("\n\n");
                    nsGlobalOutput.output.write(" + Host added to the table of the hosts!");
                    nsGlobalOutput.output.write("   - Hostname : " + GlobalVars.threadsVars.currentDomain._hostname);
                    nsGlobalOutput.output.write("   - Host ID  : " + GlobalVars.threadsVars.currentDomain._hostID);
                    nsGlobalOutput.output.write("\n\n");
                    break;
                }

                if (isMysqlNeeded())
                {
                    // carica i limiti dal DB [ hostlist_extras ] se presenti
                    GlobalVars.limits.loadHostlistExtraLimits(GlobalVars.threadsVars.currentDomain._hostID);
                }

                GlobalVars.limits.showLimits();

                // setta il tempo esatto di inizio dell'indicizzazione del dominio corrente
                GlobalVars.limits.startTime = DateTime.Now.Ticks;

                // azzera le pagine, i bytes indicizzati e gli errori HTTP
                GlobalVars.limits.curPages      = 0;
                GlobalVars.limits.curBytes      = 0;
                GlobalVars.limits.curErrorCodes = 0;

                // se siamo in stress test non controllare il file robots.txt
                if (GlobalVars.args.stressTest == false)
                {
                    // recupera e analizza il file: robots.txt
                    {
                        robots prb = new robots();
                        http   tmpHttpRobotsTxt = new http();
                        string tmpsRobotsTxt;
                        tmpsRobotsTxt = tmpHttpRobotsTxt.getURL("http://" + GlobalVars.threadsVars.currentDomain._hostname + ":" + GlobalVars.threadsVars.currentDomain._port + "/robots.txt", null, false);
                        if (tmpHttpRobotsTxt.statusCode == 200)
                        {
                            prb.parseRobotsTxt(tmpsRobotsTxt);
                        }
                        else
                        {
                            nsGlobalOutput.output.write("   - robots.txt not found");
                        }
                    }
                }

                nsGlobalOutput.output.write("");

                // aggiunge al primo posto della lista la prima pagina da indicizzare
                GlobalVars.urlsLists.addURL(GlobalVars.threadsVars.currentDomain);

                // crea i threads che indicizzeranno le pagine
                try
                {
                    threads.createThreads();
                }
                catch (Exception e)
                {
                    nsGlobalOutput.output.write("   - Error while creating threads: " + e.Message);
                    threads.killThreads();
                    return(false);
                }

                try
                {
                    bool waitThreads = true;

                    while (waitThreads)
                    {
                        System.Threading.Thread.Sleep(250);

                        __db.checkCrawlerAct();

                        // se abbiamo premuto CTRL+C : esci dal ciclo di indicizzazione
                        if (GlobalVars.OpenWebSpider.stopItGracefully == true)
                        {
                            waitThreads = false;
                        }

                        // controlla ogni tot millisecondi se ci sono altre pagine da indicizzare
                        // se no: passa al prossimo dominio

                        GlobalVars.threadsVars.mutexAccessURLList.WaitOne();
                        try
                        {
                            if (GlobalVars.urlsLists.getPageByStatus(0) == null && GlobalVars.urlsLists.getPageByStatus(2) == null)
                            {
                                waitThreads = false;
                            }
                        }
                        catch (Exception e)
                        {
                            nsGlobalOutput.output.write("   - Error 1 [Wait Threads]: " + e.Message);
                        }
                        finally
                        {
                            GlobalVars.threadsVars.mutexAccessURLList.ReleaseMutex();
                        }

                        // controlla i limiti
                        if (GlobalVars.limits.checkLimits() == false)
                        {
                            waitThreads = false;
                        }
                    }
                }
                catch (Exception e)
                {
                    nsGlobalOutput.output.write("   - Error 2 [Wait Threads]: " + e.Message);
                }

                // killa i threads
                threads.killThreads();


                // *******************************************************************
                // ri-controlla la connessione al mysql e se down prova a ristabilirla
                if (isMysqlNeeded())
                {
                    nsGlobalOutput.output.write(" + Checking connection to MySQL servers...");
                    if (GlobalVars.mysqlConn.connHostList.ping() == false || GlobalVars.mysqlConn.connPageList.ping() == false)
                    {
                        nsGlobalOutput.output.write("   - One or both MySQL server disconnected, trying to reconnect!");
                        if (mysqlConnect() == false)
                        {
                            nsGlobalOutput.output.write("   - Unable to connect to one or both MySQL server!");
                            break;
                        }
                    }
                }

                // *******************************************************************

                // aggiorna nel DB il sito corrente ("indicizzato"; status = 1)
                __db.stopIndexThisSite(GlobalVars.threadsVars.currentDomain);

                // stampa le statistiche di indicizzazione
                printCurDomainStats();

                if (isMysqlNeeded())
                {
                    // lascia intatti i duplicati?
                    if (!GlobalVars.args.keepDup)
                    {
                        // elimina le pagine con MD5 duplicato lasciando solo quella con id minore
                        __db.deleteDuplicatedPages(GlobalVars.threadsVars.currentDomain._hostID);
                    }

                    // riversa gli URL esterni trovati nel DB
                    __db.swapExternURLs2DB();

                    // salva le relazioni nel DB
                    __db.saveRels();

                    //salva le immagini
                    __db.saveImages();

                    // calcolo del rank delle pagine
                    new rank(GlobalVars.threadsVars.currentDomain._hostID);
                }

                // c'è stata una pressione di CTRL+C : esci
                if (GlobalVars.OpenWebSpider.stopItGracefully == true)
                {
                    break;
                }

                // abbiamo indicizzato il primo sito! dobbiamo continuare?
                if (GlobalVars.args.singleHostMode == true)
                {
                    haveToIndexSomething = false;                      // siamo in single host mode; non indicizzare nient'altro
                }
                else
                {
                    // recupera il primo host libero dal DB
                    page p = __db.getFirstAvailableURL();

                    if (p == null)
                    {
                        // impossibile trovare un URL: esci!!!
                        haveToIndexSomething = false;

                        nsGlobalOutput.output.write(" + Nothing to do: no available website to index!!! (Try to add: --add-external to the command line arguments) ");
                    }
                    else
                    {
                        // imposta il dominio corrente da indicizzare
                        GlobalVars.threadsVars.currentDomain = p;
                        haveToIndexSomething = true;
                    }
                }
            }

            return(true);
        }