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:
  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:
  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 incotrato 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. try:
  279. self.ID = page.ID
  280. except:
  281. print " => Error getting ID of %s" % url
  282. self.analyzed = page.analyzed
  283. self.step = page.step
  284. if parent == None:
  285. self.step = 0
  286. else:
  287. if(parent.step < self.step):
  288. self.step = parent.step + 1
  289.  
  290. else:
  291. try:
  292. self.ID = url_stack.pop()
  293. except IndexError:
  294. self.exhausted = True
  295.  
  296. # Conto in quanti passi si raggiunge questa pagina
  297. if parent == None:
  298. self.step = 0
  299. else:
  300. self.step = parent.step + 1
  301. self.links = []
  302. url_dict.addPage(self)
  303.  
  304.  
  305.  
  306. def add_link(self, page):
  307.  
  308. if(page.exhausted):
  309. return -1
  310. if debug >= 2:
  311. debug(" => Adding link to %s" % page.url, 2)
  312. url_dict.addLink(page.url, page.ID)
  313. return 0
  314.  
  315. def links(self):
  316. return url_dict.getLinks(url)
  317.  
  318.  
  319.  
  320.  
  321. class Crawler(threading.Thread):
  322. """Partendo da startpage, segue tutti i link registrando
  323. i vari collegamenti fra le pagine. Una volta raggiunto il
  324. limite di pagine da controllare termina"""
  325.  
  326. def __init__(self, startpage=default_page):
  327. threading.Thread.__init__(self)
  328. self.start_page = startpage
  329. self.waitingforpage = False
  330.  
  331. def WaitingForPage(self):
  332. """Ritorna True se il Crawler sta cercando di ottenere
  333. una nuova pagina"""
  334. return self.waitingforpage
  335.  
  336.  
  337. def run(self):
  338.  
  339. # Capiamo che pagina ci serve
  340. page = Page(self.start_page)
  341.  
  342. while(not page.exhausted):
  343. self.waitingforpage = True
  344. ## Stiamo attenti a non fare troppi passi
  345. ## dalla pagina di partenza
  346. page = Page()
  347.  
  348. while page == None:
  349. page = Page()
  350.  
  351.  
  352. ## Se ci chiedono di uscire perché abbiamo
  353. ## analizzato tutte la pagine ce ne andiamo
  354. if ExitRequired:
  355. return
  356.  
  357. ## Analogamente ce ne andiamo se non ci sono
  358. ## più vie da seguire in questa direzione
  359. if page.exhausted:
  360. break
  361.  
  362.  
  363. if page.step >= max_steps:
  364. debug(" => Ohi, troppi step! Riparto",2)
  365. page = Page(self.start_page)
  366.  
  367. self.waitingforpage = False
  368.  
  369.  
  370. if debug >= 1:
  371. debug(" => Analyzing page %s" % str(page), 2)
  372.  
  373.  
  374.  
  375. # Come prima cosa devo fare il parsing dei
  376. # link che ci sono nella pagina
  377. # Diamo una mixata per simulare meglio
  378. # il caso.. dato che tanto è probabile che
  379. # alcuni link rimarranno non visitati!
  380. links = get_links(page)
  381.  
  382. ## A questo punto io che mi occupo della pagina devo
  383. ## aggiungere tutti i link alla pagina
  384.  
  385. if not links == -1:
  386. random.shuffle(links)
  387. for l in links:
  388. lpage = Page(l, page)
  389.  
  390. if not lpage.exhausted:
  391. page.add_link(lpage)
  392. else:
  393. break
  394.  
  395.  
  396.  
  397.  
  398. if __name__ == "__main__":
  399.  
  400. parser = OptionParser()
  401. parser.add_option("-c", "--concurrency", dest="concurrency", action="store",
  402. help="Set level of concurrency (i.e. how many threads)", default=3)
  403. parser.add_option("-d", "--debug", dest="debug", action="store",
  404. help="Set debug level", default=0)
  405. parser.add_option("-o", "--output", dest="outfile", action="store",
  406. help="Name of the output file for the connection matrix", default="connections.txt")
  407. parser.add_option("-n", "--number", dest="size", action="store",
  408. help="Number of pages to analyze", default=1000)
  409. parser.add_option("-m", "--max-steps", dest="max_steps", action="store",
  410. help="Max steps to walk from the starting page", default=5)
  411. parser.add_option("-s", "--start-page", dest="start_page",
  412. default="http://poisson.phc.unipi.it",
  413. help="Starting page for all the crawlers",
  414. action="store")
  415.  
  416.  
  417. (option, args) = parser.parse_args()
  418.  
  419. concurrency = int(option.concurrency)
  420. debug_value = bool(option.debug)
  421. outfile = option.outfile
  422. size = int(option.size)
  423. url_stack = range(size)
  424. url_stack.reverse()
  425. max_steps = int(option.max_steps)
  426. default_page = option.start_page
  427.  
  428.  
  429. l = time.localtime(time.time())
  430. print " => Starting with this configuration at %s:%s:%s\n\
  431. %d thread(s)\n\
  432. %d pages to analyze\n\
  433. %d max steps from the start page, %s\n\
  434. Writing on file %s\n\
  435. " % (l.tm_hour,l.tm_min,l.tm_sec, concurrency, size, max_steps, default_page, outfile)
  436.  
  437.  
  438. ## Avvio i thread, di modo che si impegnino a lavorare
  439. ## Ora il mio scopo sarà controllare che non finiscano
  440. ## le pagine
  441. threads = []
  442. for i in range(0, concurrency):
  443. threads.append(Crawler(default_page))
  444. threads[i].start()
  445.  
  446. while threads[0].isAlive():
  447. ## Controllo se tutti i thread sono
  448. ## alla ricerca di una pagina. Se la
  449. ## risposta è sì le pagine sono finite
  450. ## e possiamo uscire
  451. PageAreExhausted = True
  452. for t in threads:
  453. if not t.WaitingForPage():
  454. PageAreExhausted = False
  455. break
  456.  
  457. if PageAreExhausted:
  458. ## Questa variabile globale farà
  459. ## uscire tutti i thread
  460. ExitRequired = True
  461. print " => There are no more pages in my range, exiting"
  462. break
  463.  
  464. ## Se non c'è niente da fare posso
  465. ## anche rilassarmi ed aspettare un
  466. ## secondo prima di rieseguire il check
  467. try:
  468. time.sleep(1)
  469. except KeyboardInterrupt:
  470. sys.exit()
  471.  
  472.  
  473. ## Qui non c'è modo umano di terminare il
  474. ## suo lavoro, bisognerà studiarci sopra
  475. for t in threads:
  476. t.join()
  477.  
  478.  
  479. ## A questo punto mi devo preoccupare di salvare
  480. ## la matrice in un formato soddisfacente
  481.  
  482. out = open(outfile, 'w')
  483. leg = open("legenda.txt", 'w')
  484.  
  485. ## Il numero massimo di pagine meno quelle avanzate =
  486. ## le pagine effettivamente usate!
  487. out.write(str(size - len(url_stack)) + "\n")
  488.  
  489. ## Il numero di elementi non 0 sono i link!
  490. out.write(str(link_counter) + "\n")
  491.  
  492.  
  493.  
  494. for url in url_dict:
  495. try:
  496. leg.write(str(url_dict.getPage(url).ID) + "\t" + url + "\n" )
  497. except AttributeError:
  498. print " => No ID on %s" % str(url)
  499. for link in url_dict.getLinks(url):
  500. out.write(str(url_dict.getPage(url).ID) + "\t" + str(link) + "\n")
  501.  
  502. out.close()
  503. leg.close()
  504.  
  505. l = time.localtime(time.time())
  506. print " => Work completed at %s:%s:%s " % (l.tm_hour,l.tm_min,l.tm_sec)
  507.  
  508.  
  509.  
  510.