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, urllib2, threading, re, time, sys from optparse import OptionParser default_page = "http://poisson.phc.unipi.it" __author__ = "Leonardo Robol <leo@robol.it>" freepages = threading.Event() size = 1000 url_stack = range(size) link_counter = 0 max_steps = 5 debug_value = 0 outfile = "connections.txt" ExitRequired = False def debug(message, level): """Stampa debug se il livello è abbastanza alto""" if debug_value >= level: print " => " + message class UrlDict(): def __init__(self): ## Creo il dizionario che mi servirà ## in seguito self.url_dict = {} self.lock = threading.RLock() freepages.set() def getPage(self, url): """Ritorna un oggetto Page per URL, oppure None se non è presente""" self.acquire() if self.url_dict.has_key(url): ## Effettuiamo una copia locale e ## poi usciamo page = self.url_dict[url] else: page = None self.release() return page def addPage(self, page): """Aggiunge una pagina al database""" self.acquire("addPage") self.url_dict[page.url] = page if not page.analyzed: freepages.set() debug("Aggiunta %s" % str(self.url_dict[page.url]), 3) self.release("addPage") return None def getNewPage(self): """Ottiene una pagina non analizzata""" ## Aspetto che ci siano pagine libere freepages.wait() debug("Abbiamo ottenuto una nuova pagina", 3) self.acquire("getNewPage") resp_page = None for url in self.url_dict: page = self.url_dict[url] if (not page.analyzed) & (page.step <= max_steps): resp_page = page debug("Restituisco la pagina %s" % str(resp_page), 3) break debug("Page vale %s" % str(resp_page), 4) last = True for url in self.url_dict: page = self.url_dict[url] if (not page.analyzed) & (page.step <= max_steps): last = False if last: freepages.clear() self.release("getNewPage") return resp_page def hasKey(self, url): """Ritorna True se la key url è presente""" self.acquire("hasKey") resp = self.url_dict.has_key(url) self.release("hasKey") return resp def addLink(self, url, ID): global link_counter self.acquire("addLink") self.url_dict[url].links.append(ID) link_counter += 1 self.release("addLink") def getLinks(self, url): """Ritorna una lista con i link della pagina contrassegnata da url""" self.acquire("getLinks") links = self.url_dict[url].links self.release("getLinks") return links def __iter__(self): """Iteratore sulle pagine nel dizionario""" # self.acquire("__iter__") try: for url in self.url_dict: try: yield url except Exception, e: print " => Exception: %s" % e except Exception, e: print " => Exception caught, %s" % e # self.release("__iter__") def setAnalyzed(self, url): """Contrassegna un url come analizzato""" self.acquire("setAnalyzed") if self.url_dict.has_key(url): self.url_dict[url].analyzed = True self.release("setAnalzyed") return None def acquire(self, message=""): debug("Thread %s acquiring lock -- %s " % (str(threading.currentThread()), message), 4) self.lock.acquire() def release(self, message = ""): debug("Thread %s releasing lock -- %s" % (str(threading.currentThread()), message), 4) self.lock.release() url_dict = UrlDict() 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 != ""): self.__new_page(url, parent) else: self.__get_page(parent) def __get_page(self, parent): if(len(url_stack) == 0): self.exhausted = True return page = None while(page == None): page = url_dict.getNewPage() # 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: debug("Ho incontrato exit required!", 2) return if not page.exhausted: self.ID = page.ID self.analyzed = page.analyzed self.exhausted = page.exhausted self.step = page.step self.url = page.url url_dict.setAnalyzed(page.url) 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.hasKey(url)): # Preservo i parametri che esistono già! page = url_dict.getPage(url) if page.exhausted: self.exhausted = page.exhausted return self.ID = page.ID self.analyzed = page.analyzed self.step = page.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 self.links = [] url_dict.addPage(self) def add_link(self, page): if(page.exhausted): return -1 if debug >= 2: debug("Adding link to %s" % page.url, 2) url_dict.addLink(page.url, page.ID) return 0 def links(self): return url_dict.getLinks(url) 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() while page == None: 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 self.waitingforpage = False if debug >= 1: debug("Analyzing page %s" % str(page), 1) # 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") parser.add_option("-l", "--legend-file", dest="legend_file", action="store", help="Conversion table from integers indexes to urls", default="legend.txt") (option, args) = parser.parse_args() concurrency = int(option.concurrency) debug_value = int(option.debug) outfile = option.outfile legend_file = option.legend_file 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\ %d level of debug\n\ Writing on file %s and %s\n\ " % (l.tm_hour,l.tm_min,l.tm_sec, concurrency, size, max_steps, default_page, debug_value, outfile, legend_file) ## 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 try: time.sleep(1) except KeyboardInterrupt: sys.exit() ## 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') leg = open(legend_file, '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") ## Con questa contiamo quante pagine abbiamo ## perso troncando il procedimento no_id = 0 for url in url_dict: try: leg.write(str(url_dict.getPage(url).ID) + "\t" + url + "\n" ) except AttributeError: no_id += 1 for link in url_dict.getLinks(url): out.write(str(url_dict.getPage(url).ID) + "\t" + str(link) + "\n") print " => %d pagine sono state analizzate ma non incluse per rispettare \n\ la dimensione della matrice scelta" % no_id out.close() leg.close() l = time.localtime(time.time()) print " => Work completed at %s:%s:%s " % (l.tm_hour,l.tm_min,l.tm_sec)