Mercurial > hg > PyCrawler
diff Search.py @ 0:57e2aa489383
initial
author | dwinter |
---|---|
date | Fri, 12 Oct 2012 15:23:33 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Search.py Fri Oct 12 15:23:33 2012 +0200 @@ -0,0 +1,209 @@ +''' +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") + \ No newline at end of file