Discussioni utente:Qualc1/bot ricerca su dump

Contenuti della pagina non supportati in altre lingue.
Da Wikisource.
#!/usr/bin/python

from lxml import etree
import sys
import re

"""
Esempi di utilizzo:
python dumpSearch.py -dump:itwikisource-20081216-pages-articles.xml -text '-containing:Archimede'
    Visualizza nomi delle pagine con il testo contenente "Archimede".

python dumpSearch.py -dump:itwikisource-20081216-pages-articles.xml -text '-regex:.*Archimede.*'
    Visualizza i nomi delle pagine con il testo contenente "Archimede", usando una espressione regolare.

python dumpSearch.py -dump:itwikisource-20081216-pages-articles.xml -title '-containing:Archimede' '-notContaining:Favaro'
    Visualizza la lista delle pagine con il titolo contenente "Archimede" non contente "Favaro"

python dumpSearch.py -dump:itwikisource-20081216-pages-articles.xml -title '-regex:.*Archimede.*'
    Visualizza la lista delle pagine con il titolo contenente "Archimede", usando una espressione regolare.
    
Parametri:
-dump:nomeFileDump , e` obbligatorio
-text e -title , indicano se eseguire i test sul titolo o sul testo della pagina
                uno dei due e` da specificare
-containing:TESTO , indica di verificare la presenza di TESTO
-notContaining:TESTO , indica di verificare l'assenza di TESTO
-regex:ESPR , indica di testare se matcha ESPR

-containing e -notContaing si posso usare insieme; -regex da solo.
"""


class DumpSearch:
    NAMESPACE = "{http://www.mediawiki.org/xml/export-0.3/}"
    EVENTS = ("start", "end")
    
    
    def __init__(self, fileLikeObj):
        """Crea un oggetto DumpSearch su cui eseguire ricerche.
        "fileLikeObj" e` un file object contenente testo di un dump di mediawiki.
        """
        self.file = fileLikeObj
        self.elmentsIter = etree.iterparse(fileLikeObj, events = self.EVENTS)

    
    def reload(self):
        """Riporta l'oggetto allo stato iniziale.
        E` da chiamare prima dei metodi di ricerca (tranne che per la prima chiamata).
        """
        self.file.seek(0)
        self.elmentsIter = etree.iterparse(self.file, events = self.EVENTS)

    
    def getTitlesByTextMatch(self, containing = None, notContaining = None):
        """Restituisce la lista titoli che (non) contengono le stringhe passate.
        "containing" e` la stringa che deve essere contenuta nel titolo.
        "notContaining" e` la stringa che non deve essere contenuta nel titolo.        
        """
        return self.titlesByTextTest(self.containingTest(containing, notContaining))


    def getTitlesByTextRegex(self, regex):
        """Restituisce i titoli che matchano l'espressione regolare "regex".
        """
        return self.titlesByTextTest(self.regexTest(regex))
        
    def getTitlesByTitleMatch(self, containing = None, notContaining = None):
        """Restituisce la lista titoli delle pagine il cui testo (non)
        contiene le stringhe passate.
        "containing" e` la stringa che deve essere contenuta nel testo.
        "notContaining" e` la stringa che non deve essere contenuta nel testo.        
        """
        return self.titlesByTitleTest(self.containingTest(containing, notContaining))
        
        
    def getTitlesByTitleRegex(self, regex):
        """Restituisce i titoli delle pagine il cui testo matcha  l'espressione
        regolare "regex".
        """
        return self.titlesByTitleTest(self.regexTest(regex))
    
    
    # "private" :

    def containingTest(self, containing = None, notContaining = None):
        return lambda text : (containing is None or containing in text) \
                        and (notContaining is None or notContaining not in text)
    
    def regexTest(self, regex):
        compiledRe = re.compile(regex, re.MULTILINE | re.DOTALL)
        return lambda text : compiledRe.match(text)
    
    def titlesByTitleTest(self, testFunction):
        titles = []
        for event, element in self.elmentsIter:
            if event == "start" and element.tag == self.NAMESPACE + "title":
                if element.text is not None and testFunction(element.text):
                    titles.append(element.text)
        return titles
    
    def titlesByTextTest(self, testFunction):
        titles = []
        currentTitle = ""
        for event, element in self.elmentsIter:
            if event == "start":
                if element.tag == self.NAMESPACE + "title":
                    currentTitle = element.text
                if element.tag == self.NAMESPACE + "text":
                    if element.text is not None and testFunction(element.text):
                        titles.append(currentTitle)
        return titles
        
def main():
    dump = None
    titleSearch = None # true -> title search. false -> text search
    regex = None
    containing = None
    notContaining = None
    for arg in sys.argv[1:]:
        if arg.startswith("-dump:"):
            dump = arg[len("-dump:"):]
        elif arg.startswith("-regex:"):
            regex = arg[len("-regex:"):]
        elif arg.startswith("-containing:"):
            containing = arg[len("-containing:"):]
        elif arg.startswith("-notContaining:"):
            notContaining = arg[len("-notContaining:"):]
        elif arg == "-text":
            titleSearch = False
        elif arg == "-title":
            titleSearch = True
        else:
            sys.stderr.write("parameter '" + arg + "' unknown\n")
            sys.exit(1)
    if dump is None or titleSearch is None or \
            (regex is None and containing is None and notContaining is None):
        sys.stderr.write("Error: invalid arguments\n")
        sys.exit(1)
        
    titleList = None
    dumpObj = DumpSearch(open(dump))
    if (titleSearch):
        if (regex):
            titleList = dumpObj.getTitlesByTitleRegex(regex)
        else:
            titleList = dumpObj.getTitlesByTitleMatch(containing, notContaining)
    else: # text search
        if (regex):
            titleList = dumpObj.getTitlesByTextRegex(regex)
        else:
            titleList = dumpObj.getTitlesByTextMatch(containing, notContaining)
    for title in titleList:
        print title
    sys.exit(0)
    
if __name__ == "__main__":
    main()