diff --git a/spidy.py b/spidy.py
index 51bc6d6..84e54db 100755
--- a/spidy.py
+++ b/spidy.py
@@ -21,9 +21,11 @@ url_counter = range(size)
max_steps = 5
-debug = False
+debug = 0
outfile = "connections.txt"
+ExitRequired = False
+
def get_links(page):
"""Restituisce una lista con i link
@@ -52,6 +54,9 @@ def expand_url(parent, url):
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 ..
@@ -105,16 +110,17 @@ class Page():
def __repr__(self):
return "<Page object: %s>" % self.url
- def __init__(self, url=""):
+ def __init__(self, url="", parent=None):
+
if(url != ""):
- mtx_url_dict.lock(self.__new_page, url)
+ mtx_url_dict.lock(self.__new_page, (url, parent))
mtx_url_dict.unlock()
else:
- mtx_url_dict.lock(self.__get_page, 0)
+ mtx_url_dict.lock(self.__get_page, parent)
mtx_url_dict.unlock()
- def __get_page(self, num):
+ def __get_page(self, parent):
if(len(url_counter) == 0):
self.exhausted = True
@@ -134,14 +140,22 @@ class Page():
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):
+ def __new_page(self, (url, parent)):
# Questo ci serve per tenere il
# conto di tutti gli url
global url_dict
@@ -150,11 +164,18 @@ class Page():
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:
@@ -163,14 +184,20 @@ class Page():
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:
+ if debug >= 2:
print " => Adding link to %s" % page.url
mtx_url_dict.lock(self.__add_link, page.ID)
mtx_url_dict.unlock()
@@ -193,27 +220,43 @@ class Crawler(threading.Thread):
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):
- step_counter = 0
-
# 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
- if(step_counter > max_steps):
+ if page.step >= max_steps:
+ print " => Ohi, troppi step! Riparto"
page = Page(self.start_page)
- step_counter = 0
- else:
- page = Page()
- step_counter += 1
+
+ self.waitingforpage = False
if page.exhausted:
break
+ 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
@@ -227,7 +270,7 @@ class Crawler(threading.Thread):
if not links == -1:
random.shuffle(links)
for l in links:
- lpage = Page(l)
+ lpage = Page(l, page)
if not lpage.exhausted:
page.add_link(lpage)
@@ -242,8 +285,8 @@ 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_true",
- help="Activate debug mode", default=False)
+ 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",
@@ -263,6 +306,7 @@ if __name__ == "__main__":
outfile = option.outfile
size = int(option.size)
url_counter = range(size)
+ url_counter.reverse()
max_steps = int(option.max_steps)
default_page = option.start_page
@@ -276,23 +320,52 @@ if __name__ == "__main__":
" % (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 i in range(0, concurrency):
- threads[i].join()
+ for t in threads:
+ t.join()
## A questo punto mi devo preoccupare di salvare
## la matrice in un formato soddisfacente
out = open(outfile, 'w')
- out.write(str(size) + "\n")
+
+ ## Il numero massimo di pagine meno quelle avanzate =
+ ## le pagine effettivamente usate!
+ out.write(str(size - len(url_counter)) + "\n")