Mercurial > hg > PyCrawler
view Search.py @ 2:6d8b6a689b2b default tip
changed to bs4
author | dwinter |
---|---|
date | Mon, 15 Oct 2012 15:09:35 +0200 |
parents | 57e2aa489383 |
children |
line wrap: on
line source
''' Created on 12.10.2012 @author: dwinter ''' from sqlalchemy import create_engine, Table, Column, Integer, String, MetaData, ForeignKey, DateTime, select from query import CrawlerDb import re import logging from BeautifulSoup import BeautifulSoup, Comment import urllib2 try: from Products.PageTemplates.PageTemplateFile import PageTemplateFile except: class PageTemplatefile: pass try: from OFS.SimpleItem import SimpleItem except: class SimpleItem: pass class Search(SimpleItem): meta_type = 'SearchCrawler' def readPage(self,url): req = urllib2.Request(str(url)) req.add_header('User-Agent', 'PyCrawler 0.2.0') request = None status = 0 try: request = urllib2.urlopen(req) except urllib2.URLError, e: logging.error("Exception at url: %s\n%s" % (url, e)) return None except urllib2.HTTPError, e: status = e.code if status == 0: status = 200 data = request.read() return data def __init__(self): self._v_db=CrawlerDb() self._v_db.connect() def search(self,keyword): if getattr(self, "_v_db",None)==None: self.__init__(); s = select([self._v_db.keyword_table]).where(self._v_db.keyword_table.c.keyword==keyword) ret=[] result = self._v_db.connection.execute(s) logging.debug(s) logging.debug(keyword) logging.debug(result) results= result.fetchall() logging.debug(results) for r in results: pid= r.page_id logging.debug(pid) s2 =select([self._v_db.crawl_table]).where(self._v_db.crawl_table.c.id==pid) resultPage = self._v_db.connection.execute(s2) for rp in resultPage.fetchall(): ret.append((rp.address,rp.title)) print self.getGetNeighbourhood(rp.address, keyword) return ret def getGetNeighbourhood(self,url, wordStr, length=100,tagging=True): """finde umgebung um die worte in wordStr, zurueckgegeben wird eine Array mit den Umgebungen von Fundstellen der Worte alle Tags werden entfernt, die Fundstellen werden mit <span class="found">XX</span> getaggt, die Umgebungen werden case insensitive gesucht @param wordStr: string mit Worten getrennt durch Leerzeichen, Phrasen sind mit " gekennzeichnet "eine phrase", "*" bezeichnet wildcards und wird ignoriert" @param length: optional, default wert 100, 2*length ist die groesse der Umgebung @param tagging: optional default wert true, kein span tag wird erzweugt falls tag=false """ ret=[] # nimmt das Array auf, dass spaeter zurueckgegeben wird ranges=[] #Array mit tupeln x,y wobei x die Position des Anfang und y des Endes der i-ten Umgebung angiebt wordStr=wordStr.lstrip().rstrip() def isInRanges(nr,length): """test ob eine gegeben Position nr schon irgendwo in einer Umgebung ist, gibt den Index des ersten Wertes aus ranges zurueck, -1, wenn kein Treffer @param nr: Position die geprueft werden soll @param length: Laenge des Wortes das geprueft werden soll """ for x in ranges: if (x[0]<=nr) and (nr < (x[1]-length)): return ranges.index(x) return -1 # deal with phrases, in Phrasen werden die Leerzeichen durch "_" ersetzt. def rep_empty(str): x= re.sub(" ","_",str.group(0)) return re.sub("\"","",x) wordStr=re.sub("\".*?\"", rep_empty,wordStr)#ersetze leerzeichen in " " durch "_" und loesche " #deal with wildcards, for our purposes it is enough to delete the wildcard wordStr=wordStr.replace("*","") words=wordStr.split(" ") #if not words is ListType: # words=[words] txtCache = self.en.getHarvestCache(); txt= txtCache.get(url,None) txt=None if txt==None: logging.debug("NO CACHE for: "+url) txt=self.readPage(url) if not txt: return ret soup = BeautifulSoup(txt) comments = soup.findAll(text=lambda text:isinstance(text, Comment)) [comment.extract() for comment in comments] txt = ''.join(soup.findAll(text=True)) #txt=re.sub("<.*?>", "", txt) # loesche alle Tags for word in words: word=re.sub("_"," ",word) # ersetze zurueck "_" durch " " pos=0 n=txt.lower().count(word.lower()) # wie oft tritt das Wort auf for i in range(n): pos=txt.lower().find(word.lower(),pos) if pos > 0: x=max(0,pos-length) y=min(len(txt),pos+length) #is word already in one of the results nr=isInRanges(pos,len(word)) if nr >=0:# word ist in einer schon gefunden Umgebung, dann vergroessere diese x=min(ranges[nr][0],x) y=max(ranges[nr][1],y) str=txt[x:y] if x!=0: #add dots if in the middle of text str="..."+str if y!=len(txt): #add dots if in the middle of text str=str+"..." if nr >=0: # word ist in einer schon gefunden Umgebung ranges[nr]=(x,y) # neue Position der Umgebung ret[nr]=str # neue Umgebung else: # andernfalls neue Umgebung hinzufuegen ranges.append((x,y)) ret.append(str) pos=pos+len(word) else: break; # now highlight everything if tagging: for x in range(len(ret)): for word in words: repl=re.compile(word,re.IGNORECASE) ret[x]=repl.sub(""" <span class="found">%s</span>"""%word.upper(),ret[x]) return ret def manage_addSearch(self,id,REQUEST): """ create the new MPIWGManager """ newinst = Search() self._setObject(id, newinst) REQUEST.RESPONSE.redirect('manage_main') try: manage_addSearchForm = PageTemplateFile('zpt/addSearch.pt',globals()) except: pass if __name__ == '__main__': logging.getLogger().setLevel(logging.DEBUG) s = Search() print s.search("Kuhn")