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