Feed subscription » blog | » comments | » google+ | » mobi | » twitter

Spracovanie obsiahlych slovníkov v pythone

Z času na čas chcete vytvoriť zoznam unikátnych reťazcov, či už na crackovanie hesiel, alebo pre iné potreby. Získať dobrý a komplexný slovník je často veľmi zložité, no na internete sa dá nájsť veľké množstvo rôznych kratších a špecializovanejších slovníkov.

Pri ich ručnom spájaní narazíte na niekoľko problémov. Textové editory začnú mať pri určitej veľkosti dosť veľké problémy so spracovaním takého množstva dát, reťazce v slovníku sú samozrejme nezoradené a často narazíte na mnohonásobné duplicity. Tento problém sa dá odstrániť veľmi jednoducho napríklad aj v pythone.

Načítať a uložiť veľké množstvo textu nie je v pythone vôbec žiadny problém. Python bez problémov zvláda pracovať s obrovskými masami dát bez prílišnej záťaže počítača. Problém nastáva až vtedy, keď sa rozhodnete zbaviť duplicít a zároveň chcete výsledný slovník mať zoradený, napríklad podľa abecedy.

Python poskytuje niekoľko natívnych dátových typov, ako napríklad slovníky (dictionaries), alebo listy (lists). Aj napriek zhode názvov, dátový typ slovník je na tento účel nevhodný. Lepší by sa mohol javiť list, ktorý umožňuje overiť prítomnosť reťazca v zozname a zároveň umožňuje zoradiť všetky položky zoznamu. List je v skutočnosti rovnako nevhodný, pretože je strašne pomalý a pri veľkých súboroch (nad 100MB) by ich spracovanie trvalo celú večnosť. Najvhodnejšie je využiť sety (sets). Tie sa správajú veľmi podobne ako listy, no su mnohonásobne rýchlejšie a umožňuje spracovať oveľa väčšie množstvo dát.

Aby sme zaručili unikátnosť každého reťazca, je potrebné overiť jeho prítomnosť v zozname. Ak sa v zozname nenachádza, jednoducho ho do zoznamu pridáme. Je úplne jedno, či overujete prítomnosť alebo neprítomnosť reťazca, rozdiel je len v zadaní podmienky.

Tu nájdete funkčný, jednoduchý skript, ktorý načítava súbory zo zadanej zložky, odfiltruje ich a prípadne očistí o prázdne znaky aj zľava aj zprava a výsledok uloží do určeného súboru. U mňa spojenie 1,9 GB z takmer 400 súborov trvalo približne 10 minút. Samozrejme, skript pri svojej práci celkom dosť vyťažuje procesor.

#!/usr/bin/python
# This Python file uses the following encoding: utf-8
 
from optparse import OptionParser
from sets import Set
import os
import sys
 
 
def join(folder,strip,output):
 
    # vytvorime novy set
    done = Set()
 
    # nacitame zoznam vsetkych suborov v urcenej zlozke
    for filename in os.listdir(folder):
        # nacitame jednotlive subory z danej zlozky
        f = open(folder + '/' + filename)
        # vypiseme zaciatok spracovania daneho suboru
        print "Processing file: %s" % filename
 
        # oddelime jednotlive riadky
        for text in f:
            # overime, ci je poziadavka na odstranenie prazdnych znakov
            if strip is True:
                # pridame retazec do zoznamu
                done.add(text.strip())
            else:
                # pridame retazec do zoznamu
                done.add(text)
        # uzavrieme subor
        f.close()
    # otvorime zadany subor na zapis a ak existuje, prepiseme jeho obsah
    o = open(output,'w')
    # hotovy zoznam zoradime podla abecedy a zacneme nacitavat jednotlive polozky
    for lines in sorted(done):
        # kazdu polozku (retazec) zo zoznamu postupne zapiseme
        o.write(lines+'\n')
    # subor uzavrieme
    o.close()
 
    # vypiseme spravu o dokonceni zapisu
    print "Finished and saved to file %s" % output
 
 
 
def main():
 
    parser = OptionParser()
    parser.add_option("-f", "--folder", dest="folder",
                      help="folder with text files")
    parser.add_option("-s", "--strip", dest="strip",
                      help="strip string from both sides", 
                      action="store_true",
                      default=False)
    parser.add_option("-o", "--o", dest="output",
                      help="name and extension of output file")
 
    (args, _) = parser.parse_args(args=None, values=None)
 
    folder = args.folder
    output = args.output
    strip = args.strip
 
    if folder is None or output is None:
 
        print "Split and sort all files into one"
        print "Usage: python dictionary.py -f 'text/' -o 'out.txt'"
        print "Remove empty spaces in every string [True/False]"
        print "Usage: python dictionary.py -f 'text/' -s True -o 'out.txt'"
 
        sys.exit()
 
 
    join(folder,strip,output)
 
 
if __name__ == '__main__':
    main()
Zaujal vás článok? Sledujte ma na Twitteri.


22 Responses to “Spracovanie obsiahlych slovníkov v pythone”


  1. 1 hkhk Dec 11th, 2009 at 11:03

    cat *.txt | sort -u > big.txt

    (programatorov cas je drahy, strojovy cas je lacny)

  2. 2 oooo Dec 11th, 2009 at 11:29

    #1 hkhk: neodstrani ti to duplicitu a nie kazdy pouziva unix like system

  3. 3 ayslix Dec 11th, 2009 at 11:46

    sort big.txt | uniq > big-no-duplicates.txt

    (programatorov cas je drahy, strojovy cas je lacny)

  4. 4 kzr Dec 11th, 2009 at 11:55

    Preklad list = list nie je veľmi dobrý, list v angličtine je v slovenčine predsa zoznam.

  5. 5 Asti Dec 11th, 2009 at 13:22

    Stiahnut si EN slovnik je bezproblemove.
    Mna by viac zaujimalo, kde zohnat SK slovniky (plain text) s diakritikou. Nejake navrhy?

  6. 6 oooo Dec 11th, 2009 at 14:17

    #4 kzr: veru, na tom nieco bude

    #3 ayslix: opat to iste. nie kazdy ma unix like system. taktiez sa to da pouzit na ine veci vramci programu.

  7. 7 Gimli2 Dec 11th, 2009 at 14:50

    #5 Asti: Mno ja si generoval ceske slovniky tak, ze jsem vzal moji slozku s e-bookama (a pridal k tomu jiz par hotovych vygooglenych sloveniku) a nechal nejakou tu chvili bezet PHP skriptik.
    Daj se pouzit napriklad i stenoprotokoly ze snemovny. Zalezi, jak moc odborne chces slovniky.

    Ad unix-like system:
    Kdo nema unix-like system, nebude mit ani python… vyjimky budou vzacne a potvrzovat pravidlo.

  8. 8 Keff Dec 11th, 2009 at 15:37

    I když nemám Unix, unixové command-line utility mi přijdou natolik užitečné, že jsem si nainstaloval Cygwin, a můžu tedy napsat sort big.txt | uniq > big-no-duplicates.txt i ve windowsí command line.

    A jinak, za asi nejsvižnější editor pro práci se soubory o velikostech ve stovkách MB považuji HiEditor: http://www.winasm.net/free-small-fast-text-editor.html

  9. 9 natman Dec 11th, 2009 at 16:21

    #7 Gimli2: heh, no napad pouzit “i stenoprotokoly ze snemovny…” na tvorbu slovnika sa mi vcelku paci :)). v slovenskom parlamente, ale mame take hovada, ze cokolvek co povedia je nepouzitelne aj na tie hlupe string-y do passwordlist-u…
    #oooo ten parserik je sikovny, ale zalezitost riesim podobne ako #1 hkhk a #3 ayslix. popravde skriptovaci stroj pre python som na inej platforme nez unix-like videl len raz v zivote… hm, no posobilo jemne povedane pitoreskne. samozrejme proti gustu ziaden disputat…

  10. 10 oooo Dec 11th, 2009 at 18:13

    #7 Gimli2: tu samozrejme neslo o ukazku uzasneho riesenia, ako si generovat slovniky, ale ako pracovat s velkym mnozstvom dat v pythone. dany priklad som zvolil preto, ze mi momentalne nic ine nenapadlo.

    #8 Keff: ja mam tiez cygwin, ale budeme skor vynimky. co sa tyka editoru, notepad2 relativne hravo otvara obrovske subory a celkom pekne s nimi pracuje.

    #9 natman: ako som napisal vyssie, priklad som pouzil len ako ilustraciu. tu ide o spracovanie velkeho mnozstva dat v pythone. na co to kto bude potrebovat vyuzit ja uz neviem, ja som to nahodou pouzil presne na toto, tak preto som to uviedol ako priklad.

    ja mam python na windowse a nevidim v tom ziadny problem. funguje skvele. poznam velke mnozstvo bezpecnostnych analytikov, ktori pouzivaju python na windowse, kedze v kombinacii s ctypes je to najlepsi nastroj na hladanie chyb vo win sw. rovnako tak jeho univerzalnost a “lepivost” je extremne vyhodna a pouzitelna. ja teda skriptovacie masiny nerozdelujem na dobre a zle. kazdy podla toho co pozna a vyhovuje mu.

  11. 11 natman Dec 11th, 2009 at 20:50

    #10 oooo: o pythone samotnom si myslim len to najlepsie. ci je potencial funkcnosti a aplikovatelnosti pythonu identicky v unix-like systemoch a na ms win/ak to uvazime v kontexte znacnych ehm, “filozofickych” diferencii spominanych platforiem/…uf, to uz by som si taky isty nebol. kazdopadne to co popisujes funkcne riesenie je. ja by som vsak v tomto konkretnom “nasadeni” netahal hada z vreca. s troskou sudnosti je snad rozdiel medzi 50 riadkami kodu a 2 shell prikazmi signifikantny… neber to prosim v zlom

  12. 12 Jan Garaj Dec 11th, 2009 at 22:58

    #5 Asti: Slovniky s diakritikou = slovníky na kontrolu pravopisu, no necakaj, ze vsetky budu ulozene v plain texte. No aj take najdes, napr. pspad take pouziva. Alebo v druhom pripade ala #7 Gimli2: si najdi vhodny zdroj textu (idealne korpus slovenskeho jazyka) a vytvor si slovnik sam.
    Tip: Wikipedia je tiez vhodny zdroj textu :-) http://blog.sebastien.raveau.name/2009/03/cracking-passwords-with-wikipedia.html

  13. 13 oooo Dec 12th, 2009 at 03:00

    #11 natman: ako som povedal. to ze som uviedol konkretny priklad pouzitia kodu na tento ucel neznamena, ze tam jeho funkcnost aj konci. v celom priklade ide o spracovanie velkeho mnozstva dat. urcite nebudes vramci nejakej aplikacie, ktora bude z nejakeho dovodu pracovat s takymito datami do toho tahat bash a este k tomu na os, kde ho nemaju.

    takisto, ked si kod pozries, je tam hodne vela zbytocneho textu. cele sa to da napisat, keby si nutne chcel aj na dovch riadkoch. je to len pripravene tak, aby to mohol kazdy pouzit velmi jednoducho bez nutneho zasahu do kodu.

  14. 14 natman Dec 12th, 2009 at 11:59

    #13 oooo: ok, ok…sak ja nic, ja som len muzikant :-). nechajme uz hada spat, radsej cosi konstruktivnejsie… co keby sme zalozili projekt pwl listu jazyka slovenskieho – bistu bohu auditorskieho/resp. cesko-slovensko-moravskeho, keby sa aj bratia cesi a moravaci pridali/? zaujimavy projekt slovnika je napr. http://www.churchofwifi.org/default.asp?PageLink=Project_Display.asp?PID=95. zakladnou otazkou je ako v takomto slovniku minimalizovat obsah balastu, ak by sme ho generovali len robotmi. zatial som o poctivej statistickej analyze slovenskeho jazyka aplikovatelnej na “ocistnu heuristiku”, takto hlupucko vygenerovaneho lst nepocul.

  15. 15 ver Dec 12th, 2009 at 19:11

    Btw, pouzitie optparse sa mozno da trocha vylepsit.
    Ak si spravne spominam, da sa mu priamo povedat ze ‘ak najdes switch “s”, nastav takuto premennu na True’, a nemusis to potom osetrovat osobitne v kode.

  16. 16 stej Dec 12th, 2009 at 23:40

    Pro zajímavost, jak by toto šlo napsat (bez toho stripu) taky na Windowsech:
    gc file.txt | sort -unique | sc res.txt
    Ale bude to určitě pomalejší než Python. A to je právě ten důvod, proč jsem se ho začal učit.

  17. 17 oooo Dec 13th, 2009 at 05:07

    #14 natman: ja uz mam aj tak dost vela inych projektov. mozno sa ale niekto najde, kto si vysetri na to cas

    #15 ver: veruze da, mas pravdu. cez store_true, store_false. parser.add_option(“-v”, action=”store_true”, dest=”verbose”)
    mohol som usetrit zo dva riadky.

  18. 18 majak Dec 13th, 2009 at 14:33

    Ja len dodam, ze set je po slovensky mnozina.
    A preto je aj overenie toho ci sa tam uz nejaky prvok nachadza zbytocne,
    pretoze po pridani uz existujuceho sa nic nestane.
    (Kazdy prvok v mnozine moze byt len raz.)

  19. 19 oooo Dec 13th, 2009 at 16:15

    #18 majak: pravdu mas. to som si ani neuvedomil. dik za upozornenie

  20. 20 xpista Dec 13th, 2009 at 16:21

    Viac drobnosti na vylepsenie skriptu:

    1) Uz spominane: Neoverovat existenciu prvku v set-e (to robi set automaticky v add())
    2) Zatvarat subory ktore otvaras v riadku “f = open(folder + ‘/’ + filename)”. Explicitne, alebo v 2.6 pouzit “with statement”
    3) Ak pouzivas python 2.6, tak pouzit built-in typ set a nie Set zo sets modulu (ktory je deprecated). (vymazat “from sets import Set” a pouzivat set s malym “s”)
    4) strip() urobit len raz a pamatat si vysledok.

  21. 21 oooo Dec 13th, 2009 at 16:58

    #20 xpista: pouzivam py 2.5
    prvy a druhy krok som upravil, 3 nie kvoli verzii a 4 asi moc neusetri

  22. 22 luboss Dec 24th, 2009 at 14:43

    Ludia, snad nemyslite vazne, ze neviete zohnat slovniky. Ak trosku pohnete hlavou tak si uvedomite, ze slovniky predsa musi pouzivat napriklad spell checker v openoffice, napriklad slovensky ma 175210 slov, co nieje zle, anglicky ma len 62157, kto hlada ten najde

Zanechajte odkaz

  • na ďalšie komentáre odkazujte za použitia čísla komentáru v hranatej zátvorke, napríklad [3]
  • vaša IP adresa je logovaná a zneužívaná na výskumné účely
  • môžete mi tykať
  • komentáre sú moderované, kritiku prijímam, snažte sa prosím strániť invektív