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]

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4.  
  5. import random, urllib2, threading, re, time, sys
  6. from optparse import OptionParser
  7.  
  8. default_page = "http://poisson.phc.unipi.it"
  9.  
  10. __author__ = "Leonardo Robol <leo@robol.it>"
  11.  
  12. freepages = threading.Event()
  13.  
  14. size = 1000
  15. url_stack = range(size)
  16. link_counter = 0
  17.  
  18. max_steps = 5
  19.  
  20. debug_value = 0
  21. outfile = "connections.txt"
  22.  
  23. ExitRequired = False
  24.  
  25. def debug(message, level):
  26. """Stampa debug se il livello è abbastanza alto"""
  27. if debug_value >= level:
  28. print " => " + message
  29.  
  30. class UrlDict():
  31.  
  32. def __init__(self):
  33. ## Creo il dizionario che mi servirà
  34. ## in seguito
  35.  
  36. self.url_dict = {}
  37. self.lock = threading.RLock()
  38. freepages.set()
  39.  
  40. def getPage(self, url):
  41. """Ritorna un oggetto Page per URL, oppure
  42. None se non è presente"""
  43.  
  44. self.acquire()
  45. if self.url_dict.has_key(url):
  46. ## Effettuiamo una copia locale e
  47. ## poi usciamo
  48. page = self.url_dict[url]
  49. else:
  50. page = None
  51.  
  52. self.release()
  53. return page
  54.  
  55. def addPage(self, page):
  56. """Aggiunge una pagina al database"""
  57. self.acquire("addPage")
  58. self.url_dict[page.url] = page
  59. if not page.analyzed:
  60. freepages.set()
  61. debug("Aggiunta %s" % str(self.url_dict[page.url]), 3)
  62. self.release("addPage")
  63. return None
  64.  
  65. def getNewPage(self):
  66. """Ottiene una pagina non analizzata"""
  67. ## Aspetto che ci siano pagine libere
  68. freepages.wait()
  69. debug("Abbiamo ottenuto una nuova pagina", 3)
  70.  
  71. self.acquire("getNewPage")
  72. resp_page = None
  73. for url in self.url_dict:
  74. page = self.url_dict[url]
  75. if (not page.analyzed) & (page.step <= max_steps):
  76. resp_page = page
  77. debug("Restituisco la pagina %s" % str(resp_page), 3)
  78. break
  79.  
  80. debug("Page vale %s" % str(resp_page), 4)
  81. last = True
  82. for url in self.url_dict:
  83. page = self.url_dict[url]
  84. if (not page.analyzed) & (page.step <= max_steps):
  85. last = False
  86. if last:
  87. freepages.clear()
  88.  
  89. self.release("getNewPage")
  90. return resp_page
  91.  
  92. def hasKey(self, url):
  93. """Ritorna True se la key url è presente"""
  94. self.acquire("hasKey")
  95. resp = self.url_dict.has_key(url)
  96. self.release("hasKey")
  97. return resp
  98.  
  99. def addLink(self, url, ID):
  100. global link_counter
  101. self.acquire("addLink")
  102. self.url_dict[url].links.append(ID)
  103. link_counter += 1
  104. self.release("addLink")
  105.  
  106. def getLinks(self, url):
  107. """Ritorna una lista con i link della pagina
  108. contrassegnata da url"""
  109. self.acquire("getLinks")
  110. links = self.url_dict[url].links
  111. self.release("getLinks")
  112. return links
  113.  
  114. def __iter__(self):
  115. """Iteratore sulle pagine nel dizionario"""
  116. # self.acquire("__iter__")
  117. try:
  118. for url in self.url_dict:
  119. try:
  120. yield url
  121. except Exception, e:
  122. print " => Exception: %s" % e
  123. except Exception, e:
  124. print " => Exception caught, %s" % e
  125. # self.release("__iter__")
  126.  
  127. def setAnalyzed(self, url):
  128. """Contrassegna un url come analizzato"""
  129. self.acquire("setAnalyzed")
  130. if self.url_dict.has_key(url):
  131. self.url_dict[url].analyzed = True
  132. self.release("setAnalzyed")
  133. return None
  134.  
  135. def acquire(self, message=""):
  136. debug("Thread %s acquiring lock -- %s " % (str(threading.currentThread()), message), 4)
  137. self.lock.acquire()
  138.  
  139. def release(self, message = ""):
  140. debug("Thread %s releasing lock -- %s" % (str(threading.currentThread()), message), 4)
  141. self.lock.release()
  142.  
  143. url_dict = UrlDict()
  144.  
  145.  
  146. def get_links(page):
  147. """Restituisce una lista con i link
  148. presenti nella pagina data, in forma canonica"""
  149. content, real_url = get_content(page.url)
  150.  
  151. if(content == -1):
  152. return -1
  153.  
  154. links = re.findall(r"<a href=\"(\S*)\"[^>]*>",content)
  155. ret = []
  156. for link in links:
  157. # Espando il link in modo da (speriamo!)
  158. # garantire l'unicità
  159. ret.append(expand_url(real_url, link))
  160.  
  161. return ret
  162.  
  163.  
  164. def expand_url(parent, url):
  165. """Questa funzione prende l'url della pagina parent
  166. e l'url del link e dà all'url del link una forma unica
  167. e canonica, del tipo
  168.  
  169. http://www.example.com/pagina
  170. http://www.example.com/pagina.html
  171. """
  172.  
  173. if len(url) == 0:
  174. return url
  175.  
  176. ## Controllo che l'url non cominci con un punto
  177. ## nel qual caso cerchiamo di rimediare subito,
  178. ## ma non cadiamo nel tranello di ignorare i ..
  179. if url[0] == ".":
  180. if len(url) == 1:
  181. url = parent
  182.  
  183. else:
  184. if(url[1] != "."):
  185. url = url[1:]
  186.  
  187. ## Se all'inizio dell'url c'è uno slash non ci serve tutto
  188. ## il parent, ma solo la prima parte
  189. if url.startswith("/"):
  190. parent = re.search(".+//[^/]*", parent).group(0)
  191. else:
  192. # in caso contrario dobbiamo assicurarci di troncare
  193. # l'ultima parte dell'url dopo il /, a meno che non
  194. # finisca senza estensione (in quel caso aggiungiamo un /)
  195. if re.search("\.[^/]*$", parent):
  196. parent = re.sub("[^/]*$", "", parent)
  197. else:
  198. if not parent.endswith("/"):
  199. parent += "/"
  200.  
  201.  
  202.  
  203. ## Controlliamo prima di tutto se nell'url c'è un
  204. ## protocollo
  205. protocol = re.search(r"(\w+):", url)
  206. if protocol == None:
  207. url = parent + url
  208. return url
  209.  
  210. def get_content(url):
  211. """Cerca di scaricare l'url dato e restituisce
  212. -1 se non ce la fa, il contenuto altrimenti"""
  213. try:
  214. req = urllib2.urlopen(url)
  215. except:
  216. return (-1, None)
  217.  
  218. return (req.read(), req.geturl())
  219.  
  220. class Page():
  221. """Una pagina web. Questa classe, quando viene istanziata,
  222. controlla se una pagina con quel nome è già presente (una
  223. pagina è unica!) e se lo è restituisce lo stesso oggetto,
  224. altrimenti ne crea uno nuovo con un nuovo ID"""
  225.  
  226. def __repr__(self):
  227. return "<Page object: %s>" % self.url
  228.  
  229. def __init__(self, url="", parent=None):
  230.  
  231. if(url != ""):
  232. self.__new_page(url, parent)
  233. else:
  234. self.__get_page(parent)
  235.  
  236. def __get_page(self, parent):
  237.  
  238. if(len(url_stack) == 0):
  239. self.exhausted = True
  240. return
  241.  
  242. page = None
  243. while(page == None):
  244.  
  245. page = url_dict.getNewPage()
  246.  
  247. # Questo è un punto dove il Crawler
  248. # si potrebbe bloccare e quindi facciamo
  249. # un check sull' ExitRequired
  250. # Ovviamente poi sarà necessario che anche
  251. # il chiamante lo faccia!
  252. if ExitRequired:
  253. debug("Ho incontrato exit required!", 2)
  254. return
  255. if not page.exhausted:
  256. self.ID = page.ID
  257.  
  258. self.analyzed = page.analyzed
  259. self.exhausted = page.exhausted
  260. self.step = page.step
  261. self.url = page.url
  262. url_dict.setAnalyzed(page.url)
  263.  
  264. def __new_page(self, url, parent):
  265. # Questo ci serve per tenere il
  266. # conto di tutti gli url
  267. global url_dict
  268. global url_stack
  269.  
  270. self.exhausted = False
  271. self.analyzed = False
  272. self.url = url
  273.  
  274.  
  275. if(url_dict.hasKey(url)):
  276. # Preservo i parametri che esistono già!
  277. page = url_dict.getPage(url)
  278. if page.exhausted:
  279. self.exhausted = page.exhausted
  280. return
  281.  
  282. self.ID = page.ID
  283.  
  284. self.analyzed = page.analyzed
  285. self.step = page.step
  286. if parent == None:
  287. self.step = 0
  288. else:
  289. if(parent.step < self.step):
  290. self.step = parent.step + 1
  291.  
  292. else:
  293. try:
  294. self.ID = url_stack.pop()
  295. except IndexError:
  296. self.exhausted = True
  297.  
  298. # Conto in quanti passi si raggiunge questa pagina
  299. if parent == None:
  300. self.step = 0
  301. else:
  302. self.step = parent.step + 1
  303. self.links = []
  304. url_dict.addPage(self)
  305.  
  306.  
  307.  
  308. def add_link(self, page):
  309.  
  310. if(page.exhausted):
  311. return -1
  312. if debug >= 2:
  313. debug("Adding link to %s" % page.url, 2)
  314. url_dict.addLink(page.url, page.ID)
  315. return 0
  316.  
  317. def links(self):
  318. return url_dict.getLinks(url)
  319.  
  320.  
  321.  
  322.  
  323. class Crawler(threading.Thread):
  324. """Partendo da startpage, segue tutti i link registrando
  325. i vari collegamenti fra le pagine. Una volta raggiunto il
  326. limite di pagine da controllare termina"""
  327.  
  328. def __init__(self, startpage=default_page):
  329. threading.Thread.__init__(self)
  330. self.start_page = startpage
  331. self.waitingforpage = False
  332.  
  333. def WaitingForPage(self):
  334. """Ritorna True se il Crawler sta cercando di ottenere
  335. una nuova pagina"""
  336. return self.waitingforpage
  337.  
  338.  
  339. def run(self):
  340.  
  341. # Capiamo che pagina ci serve
  342. page = Page(self.start_page)
  343.  
  344. while(not page.exhausted):
  345. self.waitingforpage = True
  346. ## Stiamo attenti a non fare troppi passi
  347. ## dalla pagina di partenza
  348. page = Page()
  349.  
  350. while page == None:
  351. page = Page()
  352.  
  353.  
  354. ## Se ci chiedono di uscire perché abbiamo
  355. ## analizzato tutte la pagine ce ne andiamo
  356. if ExitRequired:
  357. return
  358.  
  359. ## Analogamente ce ne andiamo se non ci sono
  360. ## più vie da seguire in questa direzione
  361. if page.exhausted:
  362. break
  363.  
  364.  
  365.  
  366. self.waitingforpage = False
  367.  
  368.  
  369. if debug >= 1:
  370. debug("Analyzing page %s" % str(page), 1)
  371.  
  372.  
  373.  
  374. # Come prima cosa devo fare il parsing dei
  375. # link che ci sono nella pagina
  376. # Diamo una mixata per simulare meglio
  377. # il caso.. dato che tanto è probabile che
  378. # alcuni link rimarranno non visitati!
  379. links = get_links(page)
  380.  
  381. ## A questo punto io che mi occupo della pagina devo
  382. ## aggiungere tutti i link alla pagina
  383.  
  384. if not links == -1:
  385. random.shuffle(links)
  386. for l in links:
  387. lpage = Page(l, page)
  388.  
  389. if not lpage.exhausted:
  390. page.add_link(lpage)
  391. else:
  392. break
  393.  
  394.  
  395.  
  396.  
  397. if __name__ == "__main__":
  398.  
  399. parser = OptionParser()
  400. parser.add_option("-c", "--concurrency", dest="concurrency", action="store",
  401. help="Set level of concurrency (i.e. how many threads)", default=3)
  402. parser.add_option("-d", "--debug", dest="debug", action="store",
  403. help="Set debug level", default=0)
  404. parser.add_option("-o", "--output", dest="outfile", action="store",
  405. help="Name of the output file for the connection matrix", default="connections.txt")
  406. parser.add_option("-n", "--number", dest="size", action="store",
  407. help="Number of pages to analyze", default=1000)
  408. parser.add_option("-m", "--max-steps", dest="max_steps", action="store",
  409. help="Max steps to walk from the starting page", default=5)
  410. parser.add_option("-s", "--start-page", dest="start_page",
  411. default="http://poisson.phc.unipi.it",
  412. help="Starting page for all the crawlers",
  413. action="store")
  414. parser.add_option("-l", "--legend-file", dest="legend_file", action="store",
  415. help="Conversion table from integers indexes to urls", default="legend.txt")
  416.  
  417.  
  418. (option, args) = parser.parse_args()
  419.  
  420. concurrency = int(option.concurrency)
  421. debug_value = int(option.debug)
  422. outfile = option.outfile
  423. legend_file = option.legend_file
  424. size = int(option.size)
  425. url_stack = range(size)
  426. url_stack.reverse()
  427. max_steps = int(option.max_steps)
  428. default_page = option.start_page
  429.  
  430.  
  431. l = time.localtime(time.time())
  432. print " => Starting with this configuration at %s:%s:%s\n\
  433. %d thread(s)\n\
  434. %d pages to analyze\n\
  435. %d max steps from the start page, %s\n\
  436. %d level of debug\n\
  437. Writing on file %s and %s\n\
  438. " % (l.tm_hour,l.tm_min,l.tm_sec, concurrency, size, max_steps, default_page, debug_value, outfile, legend_file)
  439.  
  440.  
  441. ## Avvio i thread, di modo che si impegnino a lavorare
  442. ## Ora il mio scopo sarà controllare che non finiscano
  443. ## le pagine
  444. threads = []
  445. for i in range(0, concurrency):
  446. threads.append(Crawler(default_page))
  447. threads[i].start()
  448.  
  449. while threads[0].isAlive():
  450. ## Controllo se tutti i thread sono
  451. ## alla ricerca di una pagina. Se la
  452. ## risposta è sì le pagine sono finite
  453. ## e possiamo uscire
  454. PageAreExhausted = True
  455. for t in threads:
  456. if not t.WaitingForPage():
  457. PageAreExhausted = False
  458. break
  459.  
  460. if PageAreExhausted:
  461. ## Questa variabile globale farà
  462. ## uscire tutti i thread
  463. ExitRequired = True
  464. print " => There are no more pages in my range, exiting"
  465. break
  466.  
  467. ## Se non c'è niente da fare posso
  468. ## anche rilassarmi ed aspettare un
  469. ## secondo prima di rieseguire il check
  470. try:
  471. time.sleep(1)
  472. except KeyboardInterrupt:
  473. sys.exit()
  474.  
  475.  
  476. ## Qui non c'è modo umano di terminare il
  477. ## suo lavoro, bisognerà studiarci sopra
  478. for t in threads:
  479. t.join()
  480.  
  481.  
  482. ## A questo punto mi devo preoccupare di salvare
  483. ## la matrice in un formato soddisfacente
  484.  
  485. out = open(outfile, 'w')
  486. leg = open(legend_file, 'w')
  487.  
  488. ## Il numero massimo di pagine meno quelle avanzate =
  489. ## le pagine effettivamente usate!
  490. out.write(str(size - len(url_stack)) + "\n")
  491.  
  492. ## Il numero di elementi non 0 sono i link!
  493. out.write(str(link_counter) + "\n")
  494.  
  495. ## Con questa contiamo quante pagine abbiamo
  496. ## perso troncando il procedimento
  497. no_id = 0
  498.  
  499. for url in url_dict:
  500. try:
  501. leg.write(str(url_dict.getPage(url).ID) + "\t" + url + "\n" )
  502. except AttributeError:
  503. no_id += 1
  504. for link in url_dict.getLinks(url):
  505. out.write(str(url_dict.getPage(url).ID) + "\t" + str(link) + "\n")
  506.  
  507. print " => %d pagine sono state analizzate ma non incluse per rispettare \n\
  508. la dimensione della matrice scelta" % no_id
  509.  
  510. out.close()
  511. leg.close()
  512.  
  513. l = time.localtime(time.time())
  514. print " => Work completed at %s:%s:%s " % (l.tm_hour,l.tm_min,l.tm_sec)
  515.  
  516.  
  517.  
  518.