2012-10-22 7 views
5

Nuovo in Python & BeautifulSoup. Ho un programma Python che apre un file chiamato "example.html", esegue un'azione BeautifulSoup su di esso, quindi esegue un'azione Bleach su di esso, quindi salva il risultato come file "example-cleaned.html". Finora funziona per tutti i contenuti di "example.html".Analizza ogni file in una directory con BeautifulSoup/Python, salva come nuovo file

Ho bisogno di modificarlo in modo che apra ciascun file nella cartella "/ posts /", esegue il programma su di esso, quindi lo salva come "/posts-cleaned/X-cleaned.html" dove X è il nome file originale.

Ecco il mio codice, ridotto al minimo:

from bs4 import BeautifulSoup 
import bleach 
import re 

text = BeautifulSoup(open("posts/example.html")) 
text.encode("utf-8") 

tag_black_list = ['iframe', 'script'] 
tag_white_list = ['p','div'] 
attr_white_list = {'*': ['title']} 

# Step one, with BeautifulSoup: Remove tags in tag_black_list, destroy contents. 
[s.decompose() for s in text(tag_black_list)] 
pretty = (text.prettify()) 

# Step two, with Bleach: Remove tags and attributes not in whitelists, leave tag contents. 
cleaned = bleach.clean(pretty, strip="TRUE", attributes=attr_white_list, tags=tag_white_list) 

fout = open("posts/example-cleaned.html", "w") 
fout.write(cleaned.encode("utf-8")) 
fout.close() 
print "Done" 

Assistenza & puntatori alle soluzioni esistenti volentieri ricevuti!

+6

['os.listdir()'] (http://docs.python.org/library/os.html#os.listdir), ['os.walk()'] (http: // docs. python.org/library/os.html#os.walk) – NullUserException

+1

'[s.decompose() per s nel testo (tag_black_list)]' dovrebbe essere scritto come 'per s nel testo (tag_black_list): s.decompose()' altrimenti stai costruendo una lista (con possibili valori di ritorno, solo per scartarla immediatamente) –

risposta

4

È possibile utilizzare os.listdir() per ottenere un elenco di tutti i file in una directory. Se vuoi recurse fino in fondo all'albero delle directory, avrai bisogno di os.walk().

Sposterei tutto questo codice per gestire un singolo file per funzionare e quindi scrivere una seconda funzione per gestire l'analisi dell'intera directory. Qualcosa di simile a questo:

def clean_dir(directory): 

    os.chdir(directory) 

    for filename in os.listdir(directory): 
     clean_file(filename) 

def clean_file(filename): 

    tag_black_list = ['iframe', 'script'] 
    tag_white_list = ['p','div'] 
    attr_white_list = {'*': ['title']} 

    with open(filename, 'r') as fhandle: 
     text = BeautifulSoup(fhandle) 
     text.encode("utf-8") 

     # Step one, with BeautifulSoup: Remove tags in tag_black_list, destroy contents. 
     [s.decompose() for s in text(tag_black_list)] 
     pretty = (text.prettify()) 

     # Step two, with Bleach: Remove tags and attributes not in whitelists, leave tag contents. 
     cleaned = bleach.clean(pretty, strip="TRUE", attributes=attr_white_list, tags=tag_white_list) 

     # this appends -cleaned to the file; 
     # relies on the file having a '.' 
     dot_pos = filename.rfind('.') 
     cleaned_filename = '{0}-cleaned{1}'.format(filename[:dot_pos], filename[dot_pos:]) 

     with open(cleaned_filename, 'w') as fout: 
      fout.write(cleaned.encode("utf-8")) 

    print "Done" 

Poi basta chiamare clean_dir('/posts') o cosa no.

Sto aggiungendo "-cleaned" ai file, ma penso che mi piaccia la tua idea di usare meglio una nuova directory. In questo modo non dovrai gestire i conflitti se esiste già -cleaned per qualche file, ecc.

Sto anche usando la dichiarazione with per aprire i file qui mentre li chiude e gestisce le eccezioni automaticamente.

+0

Ciò è eccezionalmente utile. Ho appena imparato a fare una mezza dozzina di cose nuove in Python dalla tua risposta, grazie per questo e per la chiara spiegazione di ciò che stai facendo. – Ila

+0

@Ali Prego; Ho aggiornato la risposta dal momento che Stack Overflow ha incasinato la mia indentazione la prima volta. – NullUserException

+0

@Ali Inoltre, ho appena scritto questo senza testarlo o altro, quindi potrebbe non funzionare, ma dovrebbe iniziare. – NullUserException

1

risposta alla mia domanda, per altri che potrebbero trovare la documentazione Python per os.listdir un po 'inutile:

from bs4 import BeautifulSoup 
import bleach 
import re 
import os, os.path 

tag_black_list = ['iframe', 'script'] 
tag_white_list = ['p','div'] 
attr_white_list = {'*': ['title']} 

postlist = os.listdir("posts/") 

for post in postlist: 

     # HERE: you need to specify the directory again, the value of "post" is just the filename: 
    text = BeautifulSoup(open("posts/"+post)) 
    text.encode("utf-8") 

    # Step one, with BeautifulSoup: Remove tags in tag_black_list, destroy contents. 
    [s.decompose() for s in text(tag_black_list)] 
    pretty = (text.prettify()) 

    # Step two, with Bleach: Remove tags and attributes not in whitelists, leave tag contents. 
    cleaned = bleach.clean(pretty, strip="TRUE", attributes=attr_white_list, tags=tag_white_list) 

    fout = open("posts-cleaned/"+post, "w") 
    fout.write(cleaned.encode("utf-8")) 
    fout.close() 

Ho tradito e ha fatto una cartella separata denominata "messaggi-puliti /" perché i file di risparmio era più facile che dividere il nome del file, aggiungere "pulito" e ricollegarlo, anche se se qualcuno vuole mostrarmi un buon modo per farlo, sarebbe ancora meglio.