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