PDA

View Full Version : [Python] Beautiful Soup filtraggio multiplo


kwb
09-05-2013, 15:52
Mi sto cimentando con uno script che passando tramite parametro una parola ( in inglese ) me ne restituisce la traduzione ( le possibili traduzioni ) in italiano.
Per far ciò sto usando Beautiful Soup, ma siccome non lo conosco molto bene ( così come ho una conoscenza base di python ) mi sono subito imbattuto in un problema.
Questa è la porzione saliente della pagina che voglio filtrare:

<table>
<tbody><tr class="wrtopsection"><td colspan="3" title="Principal Translations"><strong>Principal Translations/Traduzioni principali</strong></td></tr>
<tr class="even"><td class="FrWrd"><strong>home</strong> <em class="POS2">n</em></td><td> (house, apartment)</td><td class="ToWrd">casa <em class="POS2">nf</em></td></tr>
<tr class="even"><td>&nbsp;</td><td colspan="2" class="FrEx">They've just bought their first home.</td></tr>
<tr class="even"><td>&nbsp;</td><td colspan="2" class="ToEx">Hanno appena comprato la loro prima casa.</td></tr>
<tr class="odd"><td class="FrWrd"><strong>home</strong> <em class="POS2">n</em></td><td> (household)</td><td class="ToWrd">casa <em class="POS2">nf</em></td></tr>
<tr class="odd"><td>&nbsp;</td><td colspan="2" class="FrEx">His home is always noisy and happy.</td></tr>
<tr class="odd"><td>&nbsp;</td><td colspan="2" class="ToEx">Casa sua è sempre allegra e vivace.</td></tr>
<tr class="even"><td class="FrWrd"><strong>home</strong> <em class="POS2">n</em></td><td> (headquarters, main office)</td><td class="ToWrd">patria <em class="POS2">nf</em></td></tr>
<tr class="even"><td>&nbsp;</td><td colspan="2" class="FrEx">Detroit is the home of the US's automobile industry.</td></tr>
<tr class="even"><td>&nbsp;</td><td colspan="2" class="ToEx">Detroit è la patria dell'industria automobilistica statunitense.</td></tr>
<tr class="odd"><td class="FrWrd"><strong>home</strong> <em class="POS2">adj</em></td><td> (domestic)</td><td class="ToWrd">casa <em class="POS2">nf</em></td></tr>
<tr class="odd"><td>&nbsp;</td><td colspan="2" class="FrEx">He's really into home decorating right now.</td></tr>
<tr class="odd"><td>&nbsp;</td><td colspan="2" class="ToEx">Proprio adesso si sta dedicando alla decorazione della casa.</td></tr>
<tr class="even"><td class="FrWrd"><strong>home</strong> <em class="POS2">adv</em></td><td> (toward or to home)</td><td class="ToWrd">casa <em class="POS2">nf</em></td></tr>
<tr class="even"><td>&nbsp;</td><td colspan="2" class="FrEx">Let's go home.</td></tr>
<tr class="even"><td>&nbsp;</td><td colspan="2" class="ToEx">Andiamo a casa.</td></tr>
<tr class="odd"><td colspan="3" class="wrtopsection">&nbsp;</td></tr><tr class="wrtopsection"><td colspan="3" title="Additional Translations" class="additional"><strong>Additional Translations</strong></td></tr>
<tr class="even"><td class="FrWrd"><strong>home</strong> <em class="POS2">adj</em></td><td> (of one's country)</td><td class="ToWrd">del proprio paese, di casa propria <em class="POS2"></em></td></tr>
<tr class="even"><td>&nbsp;</td><td class="To2"></td><td class="ToWrd">nazionale <em class="POS2">agg</em></td></tr>
<tr class="even"><td>&nbsp;</td><td colspan="2" class="FrEx">When we travel abroad, it's good to find a home newspaper from time to time.</td></tr>
<tr class="even"><td>&nbsp;</td><td colspan="2" class="ToEx">Quando si viaggia all'estero, ogni tanto è piacevole trovare un giornale di casa propria.</td></tr>
<tr class="odd"><td class="FrWrd"><strong>home</strong> <em class="POS2">adj</em></td><td> (sports: a team's locality)</td><td class="ToWrd">di casa <em class="POS2">avv</em></td></tr>
<tr class="odd"><td>&nbsp;</td><td colspan="2" class="FrEx">The home team is going to win the game.</td></tr>
<tr class="odd"><td>&nbsp;</td><td colspan="2" class="ToEx">La squadra di casa sta per vincere la partita.</td></tr>
<tr class="even"><td class="FrWrd"><strong>home</strong> <em class="POS2">adj</em></td><td> (sports: game played locally)</td><td class="ToWrd">in casa <em class="POS2">avv</em></td></tr>
<tr class="even"><td>&nbsp;</td><td colspan="2" class="FrEx">It's a home game today.</td></tr>
<tr class="even"><td>&nbsp;</td><td colspan="2" class="ToEx">È una partita in casa oggi.</td></tr>
<tr class="odd"><td class="FrWrd"><strong>home</strong> <em class="POS2">adv</em></td><td> (deeply)</td><td class="ToWrd">mostrare<a title="conjugate mostrare" class="conjugate" href="/conj/ITverbs.aspx?v=mostrare">⇒</a>, far vedere<a title="conjugate far vedere" class="conjugate" href="/conj/ITverbs.aspx?v=far+vedere">⇒</a> <em class="POS2">vtr</em></td></tr>
<tr class="odd"><td>&nbsp;</td><td class="To2"></td><td class="ToWrd">rendersi conto <em class="POS2">v rif</em></td></tr>
<tr class="odd"><td>&nbsp;</td><td class="To2"></td><td class="ToWrd">toccare con mano <em class="POS2">vtr</em></td></tr>
<tr class="odd"><td>&nbsp;</td><td colspan="2" class="FrEx">His words brought home how much he's been suffering.</td></tr>
<tr class="odd"><td>&nbsp;</td><td colspan="2" class="ToEx">Le sue parole mostravano quanto stia soffrendo.</td></tr>
<tr class="odd"><td>&nbsp;</td><td colspan="2" class="ToEx">Dalle sue parole ci si rende conto di quanto stia soffrendo.</td></tr>
<tr class="odd"><td>&nbsp;</td><td colspan="2" class="ToEx">Dalle sue parole si può toccare con mano quanto stia soffrendo.</td></tr>
<tr class="even"><td class="FrWrd"><strong>home</strong> <em class="POS2">n</em></td><td> (residence)</td><td class="ToWrd">casa <em class="POS2">nf</em></td></tr>
<tr class="even"><td>&nbsp;</td><td colspan="2" class="FrEx">They have a second home on the Mediterranean.</td></tr>
<tr class="even"><td>&nbsp;</td><td colspan="2" class="ToEx">Hanno una seconda casa sul Mediterraneo.</td></tr>
<tr class="odd"><td class="FrWrd"><strong>home</strong> <em class="POS2">n</em></td><td> (institution, asylum)</td><td class="ToWrd">casa di riposo <em class="POS2">nf</em></td></tr>
<tr class="odd"><td>&nbsp;</td><td class="To2">per anziani</td><td class="ToWrd">ricovero <em class="POS2">nm</em></td></tr>
<tr class="odd"><td>&nbsp;</td><td colspan="2" class="FrEx">She's living in an old peoples' home.</td></tr>
<tr class="odd"><td>&nbsp;</td><td colspan="2" class="ToEx">Vive in una casa di riposo per anziani.</td></tr>
<tr class="even"><td class="FrWrd"><strong>home</strong> <em class="POS2">n</em></td><td> (native place, homeland)</td><td class="ToWrd">casa <em class="POS2">nf</em></td></tr>
<tr class="even"><td>&nbsp;</td><td colspan="2" class="FrEx">I missed home a lot when I was studying abroad.</td></tr>
<tr class="even"><td>&nbsp;</td><td colspan="2" class="ToEx">Quando studiavo all'estero, mi mancava molto casa.</td></tr>
<tr class="odd"><td class="FrWrd"><strong>home</strong> <em class="POS2">n</em></td><td> (games: destination)</td><td class="ToWrd">pareggiare<a title="conjugate pareggiare" class="conjugate" href="/conj/ITverbs.aspx?v=pareggiare">⇒</a>, andare in parità <em class="POS2">vi</em></td></tr>
<tr class="odd"><td>&nbsp;</td><td colspan="2" class="FrEx">I can make it home with one more roll of the dice.</td></tr>
<tr class="odd"><td>&nbsp;</td><td colspan="2" class="ToEx">Posso pareggiare con un altro tiro di dadi.</td></tr>
<tr class="even"><td class="FrWrd"><strong>home</strong> <em class="POS2">n</em></td><td> (baseball: home plate)</td><td class="ToWrd">casa base <em class="POS2">nf</em></td></tr>
<tr class="even"><td>&nbsp;</td><td colspan="2" class="FrEx">He stole from third base to home.</td></tr>
<tr class="even"><td>&nbsp;</td><td colspan="2" class="ToEx">Ha rubato casa base partendo dalla terza base.</td></tr>
<tr class="odd"><td class="FrWrd"><strong>home</strong> <em class="POS2">vi</em></td><td> (go or return to home)</td><td class="ToWrd">ritornare a casa, tornare a casa <em class="POS2">vi</em></td></tr>
<tr class="odd"><td>&nbsp;</td><td class="To2"></td><td class="ToWrd">trovare la via di casa, trovare la strada di casa <em class="POS2">vtr</em></td></tr>
<tr class="odd"><td>&nbsp;</td><td colspan="2" class="FrEx">This pigeon always homes the quickest.</td></tr>
<tr class="odd"><td>&nbsp;</td><td colspan="2" class="ToEx">Questo piccione è sempre il più veloce a tornare a casa.</td></tr>
<tr class="odd"><td>&nbsp;</td><td colspan="2" class="ToEx">Questo piccione è sempre il più veloce a trovare la via di casa.</td></tr>
<tr class="even"><td class="FrWrd"><strong>home</strong> <em class="POS2">vi</em></td><td> (military: go towards a target)</td><td class="ToWrd">dirigersi <em class="POS2">v rif</em></td></tr>
<tr class="even"><td>&nbsp;</td><td colspan="2" class="FrEx">The missile homed on the heat radiation given off by the tank.</td></tr>
<tr class="even"><td>&nbsp;</td><td colspan="2" class="ToEx">Il missile si è diretto verso la radiazione di calore emessa dal carro armato.</td></tr>
<tr class="odd"><td class="FrWrd"><strong>home</strong> <em class="POS2">vi</em></td><td> (navigate)</td><td class="ToWrd">dirigersi <em class="POS2">v rif</em></td></tr>
<tr class="odd"><td>&nbsp;</td><td colspan="2" class="FrEx">We're homing in on our target.</td></tr>
<tr class="odd"><td>&nbsp;</td><td colspan="2" class="ToEx">Ci stiamo dirigendo verso il nostro obiettivo.</td></tr>
<tr class="even"><td class="FrWrd"><strong>home</strong> <em class="POS2">vtr</em></td><td> (bring, send home)</td><td class="ToWrd">mandare a casa, fare arrivare a casa <em class="POS2">vtr</em></td></tr>
<tr class="even"><td>&nbsp;</td><td colspan="2" class="FrEx">He managed to home a pigeon all the way from France to England.</td></tr>
<tr class="even"><td>&nbsp;</td><td colspan="2" class="ToEx">Riuscì a mandare a casa un piccione viaggiatore dalla Francia all'Inghilterra.</td></tr>
<tr class="odd"><td class="FrWrd"><strong>home</strong> <em class="POS2">vtr</em></td><td> (direct to a target)</td><td class="ToWrd">dirigere<a title="conjugate dirigere" class="conjugate" href="/conj/ITverbs.aspx?v=dirigere">⇒</a>, guidare<a title="conjugate guidare" class="conjugate" href="/conj/ITverbs.aspx?v=guidare">⇒</a> <em class="POS2">vtr</em></td></tr>
<tr class="odd"><td>&nbsp;</td><td colspan="2" class="FrEx">The missile was homed to its target.</td></tr>
<tr class="odd"><td>&nbsp;</td><td colspan="2" class="ToEx">Il missile è stato diretto verso il bersaglio.</td></tr>
</tbody>
</table>

Quello che interessa a me è ciò che si trova dentro i tr con classe even e classe odd.

Il problema di fondo è che per filtrare l'html faccio una cosa così:

for i in result.select("table.WRD tr.even td.FrWrd") or result.select("table.WRD tr.odd td.FrWrd"):
print i.text

Tuttavia, così facendo, BS prima mi stampa tutti i risultati even ( si c'è una classe interna ancora ma non ci interessa per ora ) e poi mi stampa gli odd. Il guaio è che, come si vede dall'html, gli even e gli odd sono mischiati, e vengono visualizzati per "rilevanza" della traduzione, esempio: se certo Last mi mostra prima come traduzione "Ultimo" ( sostantivo ) piuttosto che "Durare" ( verbo ). C'è un modo rapido, senza smanettare eccessivamente con strutture dati, per selezionare le classi sia even che odd ma nell'ordine in cui vengono presentate dall'html?
Ovvero, se c'è una sequenza: even, even, odd, even, odd . Voglio che mi stampi questa esatta sequenza e non ( come fa adesso ): even, even, even, odd, odd.

P.S: Se volete una visione più chiara dell'html, questo è il link: http://www.wordreference.com/enit/home

cdimauro
09-05-2013, 22:20
Non conosco Beautiful Soup, ma potresti recuperare tutti i dati senza filtrare per i tag even e odd, ed esegure il filtraggio soltanto dopo, da Python.

kwb
10-05-2013, 09:48
Non conosco Beautiful Soup, ma potresti recuperare tutti i dati senza filtrare per i tag even e odd, ed esegure il filtraggio soltanto dopo, da Python.
Grazie, sono riuscito però in maniera migliore.

...
toRemove=result.find_all(class_="wrtopsection")
[remove.extract() for remove in toRemove]

parsedLeft = result.find_all("td", "FrWrd")
parsedRight = result.find_all("td","ToWrd")

for i,k in zip(parsedLeft, parsedRight):
print i.strong.string, "Si traduce con: ", k.em.previous_sibling

Ho alcune domande in merito alla sintassi di Python ( qui credo tu mi possa aiutare ).
Cosa significa:

[remove.extract() for remove in toRemove]

Intendo chiudere tra quadre quell'istruzione? Immagino crei una lista, ma non c'è alcun variabile a sinistra dell'uguale ( non c'è nemmeno l'uguale!!! ) quindi il risultato dove finisce?? :mbe:
In buona sostanza quello che fa quell'istruzione è prendere gli elementi con classe wrtopsection ( istruzione sopra ) e poi secondo un meccanismo che mi sfugge, dando un remove.extract() , rimuove quegli elementi dalla variabile result ( result è una variabile di tipo BS, che contiene tutta la struttura html - e anche altro ) :confused: :confused:

Il problema che mi si presenta ora è che la traduzione ( ovvero la parola in italiano ) non è racchiusa in una struttura analoga ( in termini di tag ) alla parola in inglese: in alcuni casi succede che ci sia più di una traduzione disponibile e di conseguenza viene messa in un nuovo td a capo. Inoltre, le traduzioni non sono racchiuse dentro i tag strong, costringendomi ad usare la proprietà previous_sibling.

Nel caso ci fosse qualcuno che se ne intende di BS, sono tutt'orecchi! :help:

The_ouroboros
10-05-2013, 09:50
Cosa significa:

[remove.extract() for remove in toRemove]

Intendo chiudere tra quadre quell'istruzione? Immagino crei una lista, ma non c'è alcun variabile a sinistra dell'uguale ( non c'è nemmeno l'uguale!!! ) quindi il risultato dove finisce?? :mbe:
In buona sostanza quello che fa quell'istruzione è prendere gli elementi con classe wrtopsection ( istruzione sopra ) e poi secondo un meccanismo che mi sfugge, dando un remove.extract() , rimuove quegli elementi dalla variabile result ( result è una variabile di tipo BS, che contiene tutta la struttura html - e anche altro ) :confused: :confused:


E un "iteratore di azione".
La stessa cosa l'hai in javascript con

for(i=0;i < 10; a[i]=0) ;
Per inizializzare in array

kwb
10-05-2013, 10:06
E un "iteratore di azione".
La stessa cosa l'hai in javascript con

for(i=0;i < 10; a[i]=0) ;
Per inizializzare in array

Ma è un'istruzione "speciale" diciamo?
Quel for, preso li com è, lo leggo come: parti da i=0, vai avanti finchè i è minore di 10, ti fermi quando il valore del vettore a(in posizione i) è 0. Ed essenzialmente fa solo un giro perchè viene inizializzato solo la prima "cella" del vettore ( visto che i non viene incrementato )..

Ho provato a cercare iteratore d'azione python ( o action iterator python :D ) ma non ho trovato nulla. Mi potete fornire un link sull'argomento? :stordita:

The_ouroboros
10-05-2013, 10:18
Ma è un'istruzione "speciale" diciamo?
Quel for, preso li com è, lo leggo come: parti da i=0, vai avanti finchè i è minore di 10, ti fermi quando il valore del vettore a(in posizione i) è 0. Ed essenzialmente fa solo un giro perchè viene inizializzato solo la prima "cella" del vettore ( visto che i non viene incrementato )..


for(i=0;i < 10; a[i++]=0) ;
Sorry, mea culpa.


var a = []
for(i=0;i < 10; a[i++]=0) ;
a // => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]


Cmq: http://www.secnetix.de/olli/Python/list_comprehensions.hawk

P.S: per esempio
>>> [i%2 for i in range(0,10)]
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
>>>

cdimauro
10-05-2013, 12:02
Ma è un'istruzione "speciale" diciamo?
Quel for, preso li com è, lo leggo come: parti da i=0, vai avanti finchè i è minore di 10, ti fermi quando il valore del vettore a(in posizione i) è 0. Ed essenzialmente fa solo un giro perchè viene inizializzato solo la prima "cella" del vettore ( visto che i non viene incrementato )..

Ho provato a cercare iteratore d'azione python ( o action iterator python :D ) ma non ho trovato nulla. Mi potete fornire un link sull'argomento? :stordita:
Si chiama list comprehension (http://docs.python.org/2/tutorial/datastructures.html#list-comprehensions), ed è un costrutto utilissimo oltre che usatissimo dai pythonisti.

kwb
10-05-2013, 12:05
Si, ok che si tratti di una list comprehension l'avevo capito :D
Quello che non mi è chiaro è, dove va a finire l'output? Non è perso?
Perchè ho provato dalla console interattiva una cosa del genere:

[i*2 for i in range(0,5)]

E stampa: 0, 4, 6, 8 . Ok
Poi però se faccio:

print i,type(i)

L'out è: 4 <type 'int'>
Infatti se faccio:

for k in i:
print k

Mi dice che gli int non sono iterabili ( ovviamente!! ).

Di conseguenza, non capisco qual è il significato di azzerare ( o fare operazioni ) su una variabile che poi viene persa... :mbe:

EDIT: Anche il tuo link mostra che c'è sempre una variabile alla sinistra dell'uguale, a prende, appunto, l'output della list comprehension...

GByTe87
10-05-2013, 13:00
Si, ok che si tratti di una list comprehension l'avevo capito :D
Quello che non mi è chiaro è, dove va a finire l'output? Non è perso?
Perchè ho provato dalla console interattiva una cosa del genere:

[i*2 for i in range(0,5)]

E stampa: 0, 4, 6, 8 . Ok
Poi però se faccio:

print i,type(i)

L'out è: 4 <type 'int'>
Infatti se faccio:

for k in i:
print k

Mi dice che gli int non sono iterabili ( ovviamente!! ).

Di conseguenza, non capisco qual è il significato di azzerare ( o fare operazioni ) su una variabile che poi viene persa... :mbe:

EDIT: Anche il tuo link mostra che c'è sempre una variabile alla sinistra dell'uguale, a prende, appunto, l'output della list comprehension...

Presumo che remove.extract() modifichi l'oggetto remove in place; ed essendo questo collegato a result causi una modifica anche in questo. Ma ripeto, presumo eh..

The_ouroboros
10-05-2013, 13:06
Presumo che remove.extract() modifichi l'oggetto remove in place; ed essendo questo collegato a result causi una modifica anche in questo. Ma ripeto, presumo eh..

anche io ero arrivato alla stessa conclusione :)

cdimauro
10-05-2013, 16:12
E' esattamente come avete immaginato. La list comprehension è un'espressione, che fa un certo lavoro, ma non sta scritto da nessuna parte che la lista generata la si debba per forza memorizzare da qualche parte.

Nello specifico, l'unica cosa che conta è eliminare quegli elementi, e quell'espressione lo fa in maniera semplice e compatta. Ma non efficiente, perché la lista viene generata per intero, pur buttandola via; per gli amanti delle prestazioni si potrebbe sostituire con un expression generator, ma i cui elementi vanno comunque consumati.

kwb
10-05-2013, 17:56
anche io ero arrivato alla stessa conclusione :)

E' esattamente come avete immaginato. La list comprehension è un'espressione, che fa un certo lavoro, ma non sta scritto da nessuna parte che la lista generata la si debba per forza memorizzare da qualche parte.

Nello specifico, l'unica cosa che conta è eliminare quegli elementi, e quell'espressione lo fa in maniera semplice e compatta. Ma non efficiente, perché la lista viene generata per intero, pur buttandola via; per gli amanti delle prestazioni si potrebbe sostituire con un expression generator, ma i cui elementi vanno comunque consumati.


...
toRemove=result.find_all(class_="wrtopsection")
[remove.extract() for remove in toRemove]

parsedLeft = result.find_all("td", "FrWrd")
parsedRight = result.find_all("td","ToWrd")

for i,k in zip(parsedLeft, parsedRight):
print i.strong.string, "Si traduce con: ", k.em.previous_sibling


Cioè mi state dicendo che in questo codice sopra, quando faccio

toRemove=result.find_all(class_="wrtopsection")

In realtà oltre che cambiare la variabile di sinistra mi cambia anche quella di destra, segnandosi da qualche parte che c'è una variabile toRemove che si è copiata dei parametri?? :mbe:

GByTe87
10-05-2013, 19:06
...
toRemove=result.find_all(class_="wrtopsection")
[remove.extract() for remove in toRemove]

parsedLeft = result.find_all("td", "FrWrd")
parsedRight = result.find_all("td","ToWrd")

for i,k in zip(parsedLeft, parsedRight):
print i.strong.string, "Si traduce con: ", k.em.previous_sibling


Cioè mi state dicendo che in questo codice sopra, quando faccio

toRemove=result.find_all(class_="wrtopsection")

In realtà oltre che cambiare la variabile di sinistra mi cambia anche quella di destra, segnandosi da qualche parte che c'è una variabile toRemove che si è copiata dei parametri?? :mbe:

Ad occhio quell'espressione non va a modificare alcunchè; semplicemente crea toRemove, lista di riferimenti ad oggetto.
Poi extract() andrà a modificare gli oggetti.

cdimauro
10-05-2013, 21:31
E' così, infatti.