viewgit/index.php:465 Only variables should be passed by reference [2048]
viewgit/index.php:466 Non-static method GeSHi::get_language_name_from_extension() should not be called statically [2048]
#!/usr/bin/env python # -*- coding: utf-8 -*- # import random import urllib2 import mutex import threading import re, time from optparse import OptionParser default_page = "http://poisson.phc.unipi.it" __author__ = "Leonardo Robol <leo@robol.it>" mtx_url_dict = mutex.mutex() size = 1000 url_dict = {} url_stack = range(size) link_counter = 0 max_steps = 5 debug = 0 outfile = "connections.txt" ExitRequired = False def get_links(page): """Restituisce una lista con i link presenti nella pagina data, in forma canonica""" content, real_url = get_content(page.url) if(content == -1): return -1 links = re.findall(r"<a href=\"(\S*)\"[^>]*>",content) ret = [] for link in links: # Espando il link in modo da (speriamo!) # garantire l'unicità ret.append(expand_url(real_url, link)) return ret def expand_url(parent, url): """Questa funzione prende l'url della pagina parent e l'url del link e dà all'url del link una forma unica e canonica, del tipo http://www.example.com/pagina http://www.example.com/pagina.html """ if len(url) == 0: return url ## Controllo che l'url non cominci con un punto ## nel qual caso cerchiamo di rimediare subito, ## ma non cadiamo nel tranello di ignorare i .. if url[0] == ".": if len(url) == 1: url = parent else: if(url[1] != "."): url = url[1:] ## Se all'inizio dell'url c'è uno slash non ci serve tutto ## il parent, ma solo la prima parte if url.startswith("/"): parent = re.search(".+//[^/]*", parent).group(0) else: # in caso contrario dobbiamo assicurarci di troncare # l'ultima parte dell'url dopo il /, a meno che non # finisca senza estensione (in quel caso aggiungiamo un /) if re.search("\.[^/]*$", parent): parent = re.sub("[^/]*$", "", parent) else: if not parent.endswith("/"): parent += "/" ## Controlliamo prima di tutto se nell'url c'è un ## protocollo protocol = re.search(r"(\w+):", url) if protocol == None: url = parent + url return url def get_content(url): """Cerca di scaricare l'url dato e restituisce -1 se non ce la fa, il contenuto altrimenti""" try: req = urllib2.urlopen(url) except: return (-1, None) return (req.read(), req.geturl()) class Page(): """Una pagina web. Questa classe, quando viene istanziata, controlla se una pagina con quel nome è già presente (una pagina è unica!) e se lo è restituisce lo stesso oggetto, altrimenti ne crea uno nuovo con un nuovo ID""" def __repr__(self): return "<Page object: %s>" % self.url def __init__(self, url="", parent=None): if(url != ""): mtx_url_dict.lock(self.__new_page, (url, parent)) mtx_url_dict.unlock() else: mtx_url_dict.lock(self.__get_page, parent) mtx_url_dict.unlock() def __get_page(self, parent): if(len(url_stack) == 0): self.exhausted = True return page_found = False while(not page_found): for url in url_dict: page = Page(url) if not page.analyzed: page_found = True self.url = url break if not page_found: time.sleep(1) # Questo è un punto dove il Crawler # si potrebbe bloccare e quindi facciamo # un check sull' ExitRequired # Ovviamente poi sarà necessario che anche # il chiamante lo faccia! if ExitRequired: return self.ID = page.ID self.analyzed = page.analyzed self.exhausted = False self.step = page.step url_dict[url].analyzed = True def __new_page(self, (url, parent)): # Questo ci serve per tenere il # conto di tutti gli url global url_dict global url_stack self.exhausted = False self.analyzed = False self.url = url if(url_dict.has_key(url)): # Preservo i parametri che esistono già! self.ID = url_dict[url].ID self.analyzed = url_dict[url].analyzed self.step = url_dict[url].step if parent == None: self.step = 0 else: if(parent.step < self.step): self.step = parent.step + 1 else: try: self.ID = url_stack.pop() except IndexError: self.exhausted = True # Conto in quanti passi si raggiunge questa pagina if parent == None: self.step = 0 else: self.step = parent.step + 1 url_dict[url] = self url_dict[url].links = [] def add_link(self, page): if(page.exhausted): return -1 if debug >= 2: print " => Adding link to %s" % page.url mtx_url_dict.lock(self.__add_link, page.ID) mtx_url_dict.unlock() return 0 def __add_link(self, ID): global link_counter url_dict[self.url].links.append(ID) link_counter += 1 def links(self): return url_dict[self.url].links class Crawler(threading.Thread): """Partendo da startpage, segue tutti i link registrando i vari collegamenti fra le pagine. Una volta raggiunto il limite di pagine da controllare termina""" def __init__(self, startpage=default_page): threading.Thread.__init__(self) self.start_page = startpage self.waitingforpage = False def WaitingForPage(self): """Ritorna True se il Crawler sta cercando di ottenere una nuova pagina""" return self.waitingforpage def run(self): # Capiamo che pagina ci serve page = Page(self.start_page) while(not page.exhausted): self.waitingforpage = True ## Stiamo attenti a non fare troppi passi ## dalla pagina di partenza page = Page() ## Se ci chiedono di uscire perché abbiamo ## analizzato tutte la pagine ce ne andiamo if ExitRequired: return ## Analogamente ce ne andiamo se non ci sono ## più vie da seguire in questa direzione if page.exhausted: break if page.step >= max_steps: print " => Ohi, troppi step! Riparto" page = Page(self.start_page) self.waitingforpage = False if debug >= 1: print " => Analyzing page %s" % page.url # Come prima cosa devo fare il parsing dei # link che ci sono nella pagina # Diamo una mixata per simulare meglio # il caso.. dato che tanto è probabile che # alcuni link rimarranno non visitati! links = get_links(page) ## A questo punto io che mi occupo della pagina devo ## aggiungere tutti i link alla pagina if not links == -1: random.shuffle(links) for l in links: lpage = Page(l, page) if not lpage.exhausted: page.add_link(lpage) else: break if __name__ == "__main__": parser = OptionParser() parser.add_option("-c", "--concurrency", dest="concurrency", action="store", help="Set level of concurrency (i.e. how many threads)", default=3) parser.add_option("-d", "--debug", dest="debug", action="store", help="Set debug level", default=0) parser.add_option("-o", "--output", dest="outfile", action="store", help="Name of the output file for the connection matrix", default="connections.txt") parser.add_option("-n", "--number", dest="size", action="store", help="Number of pages to analyze", default=1000) parser.add_option("-m", "--max-steps", dest="max_steps", action="store", help="Max steps to walk from the starting page", default=5) parser.add_option("-s", "--start-page", dest="start_page", default="http://poisson.phc.unipi.it", help="Starting page for all the crawlers", action="store") (option, args) = parser.parse_args() concurrency = int(option.concurrency) debug = bool(option.debug) outfile = option.outfile size = int(option.size) url_stack = range(size) url_stack.reverse() max_steps = int(option.max_steps) default_page = option.start_page l = time.localtime(time.time()) print " => Starting with this configuration at %s:%s:%s\n\ %d thread(s)\n\ %d pages to analyze\n\ %d max steps from the start page, %s\n\ Writing on file %s\n\ " % (l.tm_hour,l.tm_min,l.tm_sec, concurrency, size, max_steps, default_page, outfile) ## Avvio i thread, di modo che si impegnino a lavorare ## Ora il mio scopo sarà controllare che non finiscano ## le pagine threads = [] for i in range(0, concurrency): threads.append(Crawler(default_page)) threads[i].start() while threads[0].isAlive(): ## Controllo se tutti i thread sono ## alla ricerca di una pagina. Se la ## risposta è sì le pagine sono finite ## e possiamo uscire PageAreExhausted = True for t in threads: if not t.WaitingForPage(): PageAreExhausted = False break if PageAreExhausted: ## Questa variabile globale farà ## uscire tutti i thread ExitRequired = True print " => There are no more pages in my range, exiting" break ## Se non c'è niente da fare posso ## anche rilassarmi ed aspettare un ## secondo prima di rieseguire il check time.sleep(1) ## Qui non c'è modo umano di terminare il ## suo lavoro, bisognerà studiarci sopra for t in threads: t.join() ## A questo punto mi devo preoccupare di salvare ## la matrice in un formato soddisfacente out = open(outfile, 'w') ## Il numero massimo di pagine meno quelle avanzate = ## le pagine effettivamente usate! out.write(str(size - len(url_stack)) + "\n") ## Il numero di elementi non 0 sono i link! out.write(str(link_counter) + "\n") for page in url_dict: for link in url_dict[page].links: out.write(page + "\t" + str(url_dict[page].ID) + "\t" + str(link) + "\n") l = time.localtime(time.time()) print " => Work completed at %s:%s:%s " % (l.tm_hour,l.tm_min,l.tm_sec)