dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org...

25

Transcript of dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org...

Page 1: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

Full CircleEDIZIONE SPECIALE SERIE PROGRAMMAZIONE

LA RIVISTA INDIPENDENTE PER LA COMUNITÀ LINUX UBUNTU

full circle magazine non è affiliata né sostenuta dalla Canonical Ltd .

EDIZIONE SPECIALE

SERIE PROGRAMMAZIONE

PROGRAMMARE

IN PYTHON

VOLUME 7

Page 2: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

Cos'è Full Circle

Full Circle è una rivista gratuita e

indipendente, dedicata alla famiglia

Ubuntu dei sistemi operativi Linux.

Ogni mese pubblica utili articoli

tecnici e articoli inviati dai lettori.

Full Circle ha anche un podcast di

supporto, il Full Circle Podcast, con

gli stessi argomenti della rivista e

altre interessanti notizie.

Si prega di notare che questaedizione speciale viene fornitasenza alcuna garanzia: né chi hacontribuito né la rivista Full Circlehanno alcuna responsabilità circaperdite di dati o danni chepossano derivare ai computer oalle apparecchiature dei lettoridall'applicazione di quantopubblicato.

Come contattarci

Sito web:http://www.fullcirclemagazine.org/

Forum:http://ubuntuforums.org/forumdisplay.php?f=270

IRC:#fullcirclemagazine suchat.freenode.net

Gruppo editoriale

Capo redattore: Ronnie Tucker(aka: RonnieTucker)[email protected]

Webmaster: Rob Kerfia(aka: admin / [email protected]

Modifiche e CorrezioniMike Kennedy, Lucas Westermann,Gord Campbell, Robert Orsino, JoshHertel, Bert Jerred

Si ringrazia la Canonical e i tantigruppi di traduzione nel mondo.

Ecco a voi un altro 'Specialemonotematico'

Come richiesto dai nostri lettori, stiamo assemblando in edizionidedicate alcuni degli articoli pubblicati in serie.

Quella che avete davanti è la ristampa della serie 'Programmare

in Python' parti 39-43, pubblicata nei numeri 68-72dall' impareggiabile professor Gregg Walters.

Vi preghiamo di tenere conto della data di pubblicazione: leversioni attuali di hardware e software potrebbero esserediverse rispetto ad allora. Controllate il vostro hardware e ilvostro software prima di provare quanto descritto nelle guide diqueste edizioni speciali. Potreste avere versioni più recenti delsoftware installato o disponibile nei repository delle vostredistribuzioni.

Buon divertimento!

Gli articoli contenuti in questa rivista sono stati rilasciati sotto la licenza Creative Commons Attribuzione - Non commerciale - Condividi allo stessomodo 3.0. Ciò significa che potete adattare, copiare, distribuire e inviare gli articoli ma solo sotto le seguenti condizioni: dovete attribuire il lavoroall'autore originale in una qualche forma (almeno un nome, un'email o un indirizzo Internet) e a questa rivista col suo nome ("Full Circle Magazine") econ suo indirizzo Internet www.fullcirclemagazine.org (ma non attribuire il/gli articolo/i in alcun modo che lasci intendere che gli autori e la rivista

abbiano esplicitamente autorizzato voi o l'uso che fate dell'opera). Se alterate, trasformate o create un'opera su questo lavoro dovete distribuire il lavoro risultante con la stessalicenza o una simile o compatibile.Full Circle magazine è completamente indipendente da Canonical, lo sponsor dei progetti di Ubuntu, e i punti di vista e le opinioni espresse nella rivista non sono in alcun

modo da attribuire o approvati dalla Canonical.

Full CircleLA RIVISTA INDIPENDENTE PER LA COMUNITÀ LINUX UBUNTU

Page 3: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #68 8 indice ^

HHOOWW--TTOOScritto da Greg Walters PPrrooggrraammmmaarree iinn PPyytthhoonn :: PPaarrttee 3399

M olti mesi fa abbiamolavorato con lechiamate API perWeather Underground.

Veramente, era nella parte 1 1 che eranel numero 37. Dunque avremo ancoraa che fare con le API, questa volta di unsito denominato TVRage(http://tvrage.com). Se non sietefamiliari con questo sito, ha a che farecon gli show televisivi. Finora, ognishow televisivo che mi passava per lamente era anche presente nel lorosistema. In questa serie di articolirivedremo XML, API e ElementTree(ndt Elementi ad Albero) per creareuna libreria wrapper che ci permetteràdi creare una piccola libreria chesemplifica il nostro recupero delleinformazioni TV sui nostri programmipreferiti.

Ora ho menzionato una libreriawrapper. Che cosa è? In terminisemplici quando voi create o usate unalibreria wrapper voi state usando uninsieme di codice che ingloba lacomplessità delle API del sito web inuna libreria facile da usare. Prima cosa,questo è un servizio gratuito.Comunque il sito richiede donazioniper l'uso delle loro API. Se valutate che

questo è un servizio che vale, perfavore considerate la donazione di 1 0dollari americani o più. Seconda cosa,dovreste registrarvi al loro sito web eottenere la vostra chiave per le API. Ègratuito, quindi non c'è davveronessuna ragione per non farlo,specialmente se voi state per usare leinformazioni qui fornite. Inoltre, avreteaccesso ad alcuni altri campi diinformazioni come le serie e i sommaridegli episodi che non sono inclusi nellaversione non registrata. Terzo, essifanno un lavoro pesante peraggiornare le API. Questo significa chequando voi starete leggendo questoarticolo, le loro API potrebbero esserecambiate. Utilizzeremo i feed pubblici,che sono gratuiti per tutti, delDicembre 201 2. Il sito delle API èhttp://services.tvrage.com/info.php?page=main e mostra alcuni esempi diinformazioni che sono disponibili.

Ora iniziamo a guardare alle APIe come possiamo usarle.

Usando la loro API, possiamoottenere delle informazioni moltospecifiche sullo spettacolo stesso e/opossiamo ottenere informazioni sulsingolo episodio. Ci sono

fondamentalmente tre passi percercare informazioni sugli spettacolitelevisivi. Qui sono i passi:• Cerca nel loro database usando ilnome dello spettacolo per ottenere lospecifico Show ID che deve essereusato per ottenere ulteriori dati.Pensate al valore di showid come aduna chiave che punta direttamente inun insieme di record di un database.• Una volta che avete lo Show ID,ottenete le informazioni di livello dellospettacolo.• Infine raccogliete le informazioniriguardo allo specifico episodio.Queste provengono da una lista di tuttigli episodi in cui lo spettacolo è statoprogrammato.

Ci sono tre chiamate web di baseche faremo per ottenere questeinformazioni. La prima è la chiamataper la ricerca, la seconda per leinformazioni sullo spettacolo e infine la

chiamata per la lista degli episodi.

Ecco qui le chiamate di base cheuseremo…• ricerca per ShowID basata sul nomedello spettacolo -http://services.tvrage.com/feeds/search.php?show={SomeShow}

• Estrazione delle informazioni a livellodi spettacolo in base allo ShowID -http://services.tvrage.com/feeds/showinfo.php?sid={SomeShowID}

• Estrazione della lista degli episodi perlo ShowID (sid) -http://services.tvrage.com/feeds/episode_list.php?sid={SomeShowID}

Quello che viene restituito è unflusso di dati in formato XML.Prendiamoci un po' di tempo perrivedere come l'XML appare. La primalinea deve sempre essere simile aquella mostrata sotto per essere

<?xml version="1.0" encoding="UTF-8" ?><ROOT TAG>

<PARENT TAG><CHILD TAG 1>DATA</CLOSING CHILD TAG 1><CHILD TAG 2>DATA</CLOSING CHILD TAG 2><CHILD TAG 3>DATA</CLOSING CHILD TAG 3>

</CLOSING PARENT TAG></CLOSING ROOT TAG>

Page 4: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #68 9 indice ^

HOWTO - PROGRAMMARE IN PYTHON Parte 39considerata come un flusso di dati XMLcorretto (sotto).

Ciascun pezzo di dato è inclusoall'interno di un tag (ndt contrassegno)di definizione e un tag di fine. Qualchevolta avrete un tag figlio che èall'interno di un tag genitore comequesto ...

<CHILD PARENT TAG>

<CHILD TAG 1>DATA</CLOSINGCHILD TAG 1>

</CLOSING CHILD PARENT TAG>

Potete anche vedere che un tagche ha un attributo associato:

<TAG INFORMATION = VALUE>

<CHILD TAG>DATA</CLOSING CHILDTAG>

</CLOSING TAG>

Qualche volta , potreste vedere untag con nessun dato associato ad esso.In questo caso sarebbe come questo ...

<prodnum/>

Qualche volta se non c'èinformazione per uno specifico tag, iltag stesso potrebbe non esserci. Ilvostro programma deve gestire queste

possibilità.

Così quando gestiamo i dati XML,iniziamo con il root tag (ndtcontrassegno di radice) e analizziamociascun tag – cercando i dati che ciinteressano. In alcuni casi, vogliamotutto; in altri ci interessiamo solo dicerti pezzi di informazioni.

Ora, andiamo a dare una occhiataalla prima chiamata e vediamo chevalore rende indietro. Assumente chelo spettacolo che stiamo cercando siaBuffy the Vampire Slayer. La nostrachiamata per la ricerca dovrebbeassomigliare a questa:

http://services.tvrage.com/feeds/search.php?show=buffy

Il file XML restituito dovrebbeessere come questo:http://pastebin.com/Eh6ZtJ9N.

Notate che io ho inserito leindentazioni per rendervi più facile lalettura. Ora spezziamo il file XMLpervedere che cosa abbiamo veramente.

<Results>Questa è la RADICE dei datiXML. L'ultima linea del flusso chericeviamo dovrebbe essere </Results>.Fondamentalmente questo segnal'inizio e la fine del flusso XML. Questopotrebbe essere di zero risultati o di 50

risultati.<show>Questo è il nodo genitore chedice “quello che segue ( fino al tag dichiusura di show) è la informazionerelativa ad un singolo show televisivo”.Anche questo è terminato dal suo tagfinale </show> . Qualsiasi cosa traquesti due tag dovrebbe essereconsiderato come un pezzo di valoredell'informazione dello show.<showid>2930</show>Questo è iltag showid. Questo contiene il sid chedobbiamo usare per ottenere leinformazioni dello show. In questocaso 2930.<name>Buffy the VampireSlayer</name>Questo è il nome delloshow.<link>...</link>Questo sarebbe ilcollegamento allo show stesso (o nelcaso di un episodio, le informazionisull'episodio) sul sito di TVRage.<country>...</country> Il paese diorigine dello show.…</show></Results>

Nel caso del nostro programma,siamo davvero interessati in soli duecampi <showid> e <name>. Possiamoanche considerare di fare attenzioneanche al campo <started>. Questoperché raramente recuperemo un soloinsieme di dati, specialmente se nondiamo il nome completo dellospettacolo. Per esempio, se siamointeressati allo spettacolo “The BigBang Theory”, e lo abbiamo cercatousando solo la stringa “Big Bang”potremmo ricevere venti o più insiemidi dati perché qualsiasi cosa che avesselontamente coinciso con “big” o “bang”sarebbe stato elencato. Comunque, sesiamo interessati allo spettacolo“NCIS”, e abbiamo fatto una ricerca,abbiamoricevuto indietro molterisposte. Alcune che non ci saremmoaspettati. Non solo avremmo ottenuto“NCIS”, “NCIS Los Angeles”, “the realNCIS”, ma anche “The Streets of SanFrancisco” e “Da Vinci's Inquest” emolti altri, dato che le lettere “N” “C”“I” “S” sono in tutte queste, quasi inquesto ordine.

Page 5: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #68 1 0 indice ^

HOWTO - PROGRAMMARE IN PYTHON Parte 39Una volta che conosciamo lo

showid che vogliamo, quindi possiamorichiedere le informazioni dellospettacolo per quel ID. I dati sono similiai dati che abbiamo appena ricevutoindietro nella risposta della ricerca, mapiù dettagliati. Dunque, usando Buffycome nella nostra richiesta di esempio,qui, (prossima pagina, destra) trovateuna abbreviata versione del file XML.

Potete vedere che la maggior partedei dati è incluso nel flusso di rispostaalla ricerca originale. Comunque, cosecome il canale, il paese del canale, ladata e l'ora della messa in onda sonospecifiche a questo insieme di risposta.

Poi avremmo richiesto l'elencodegli episodi. Se lo spettacolo ha unasola stagione e se ha o ha avuto solosei episodi, questo flusso potrebbeessere corto. Comunque, prendiamo ilcaso di uno dei miei spettacoli televisivipreferiti DoctorWho. DoctorWho èuno spettacolo britannico che nella suaforma originale è iniziato nel 1 963, ed èproseguito per 26 stagioni ('serie' per inostri amici in UK) fino al 1 989. La suaprima stagione da sola aveva 42episodi, mentre le altre stagioni/serieavevano circa 24 episodi. Potetevedere come si potrebbe avere unENORME flusso da analizzare.

Quello che otteniamo dalla nostra

richiesta di elenco degliepisodi è mostrato nellapagina seguente (ancorausando Buffy come esempio);sto per usare solo una partedel flusso in modo tale chevoi abbiate una buona idea diche cosa viene restituito.

Così per ricapitolare, leinformazioni di cui abbiamodavvero bisogno odesideriamo nella ricerca pershowid del flusso del nomepotrebbero essere<showid><name><started>

Nel flusso di informazionisullo spettacolo noi(normalmente) vogliamo...<seasons><started><start date><origin_country><status><genres><runtime><network><airtime><airday><timezone>

e dal flusso della lista degliepisodi...<Season><episode number><season number>

<Showinfo><showid>2930</showid><showname>Buffy the Vampire Slayer</showname><showlink>http://tvrage.com/Buffy_The_Vampire_Slayer</showlink><seasons>7</seasons><started>1997</started><startdate>Mar/10/1997</startdate><ended>May/20/2003</ended><origin_country>US</origin_country><status>Canceled/Ended</status><classification>Scripted</classification><genres>

<genre>Action</genre><genre>Adventure</genre><genre>Comedy</genre><genre>Drama</genre><genre>Mystery</genre><genre>Sci-Fi</genre>

</genres><runtime>60</runtime><network country="US">UPN</network><airtime>20:00</airtime><airday>Tuesday</airday><timezone>GMT-5 -DST</timezone><akas>

<aka country="SE">Buffy &amp; vampyrerna</aka><aka country="DE">Buffy - Im Bann der Dämonen</aka><aka country="NO">Buffy - Vampyrenes skrekk</aka><aka country="HU">Buffy a vámpírok réme</aka><aka country="FR">Buffy Contre les Vampires</aka><aka country="IT">Buffy l'Ammazza Vampiri</aka><aka country="PL">Buffy postrach wampirów</aka><aka country="BR">Buffy, a Caça-Vampiros</aka><aka country="PT">Buffy, a Caçadora de Vampiros</aka><aka country="ES">Buffy, Cazavampiros</aka><aka country="HR">Buffy, ubojica vampira</aka><aka country="FI">Buffy, vampyyrintappaja</aka><aka country="EE">Vampiiritapja Buffy</aka><aka country="IS">Vampírubaninn Buffy</aka>

</akas></Showinfo>

Page 6: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #68 1 1 indice ^

HOWTO - PROGRAMMARE IN PYTHON Parte 39<production number><airdate><link><title>

Una parola sugli “avvisi”. I dati delnumero della stagione e del numerodegli episodi non sono quello che voipotreste pensare come giusti. Nel casodei dati da TVRage, il numero dellastagione è il numero dell'episodioall'interno della stagione. Il numerodell'episodio è il numero perquell'episodio all'interno dell'interavita della serie. Il numero di produzioneè un numero che era usatointernamente alla serie, che, permoltepersone, significa poco se non niente.

Ora che abbiamo rinfrescato lanostra memoria sulle strutture dei fileXML, e esaminato le chiamate API diTVRage, siamo pronti per iniziare ascrivere il nostro codice ma dobbiamoaspettare fino alla prossima volta.

Fino ad allora, godetevi le vacanze.

<Show><name>Buffy the Vampire Slayer</name><totalseasons>7</totalseasons><Episodelist>

<Season no="1"><episode>

<epnum>1</epnum><seasonnum>01</seasonnum><prodnum>4V01</prodnum><airdate>1997-03-10</airdate><link>http://www.tvrage.com/Buffy_The_Vampire_Slayer/episodes/28077</link><title>Welcome to the Hellmouth (1)</title>

</episode><episode>

<epnum>2</epnum><seasonnum>02</seasonnum><prodnum>4V02</prodnum><airdate>1997-03-10</airdate><link>http://www.tvrage.com/Buffy_The_Vampire_Slayer/episodes/28078</link><title>The Harvest (2)</title>

</episode><episode>

<epnum>3</epnum><seasonnum>03</seasonnum><prodnum>4V03</prodnum><airdate>1997-03-17</airdate><link>http://www.tvrage.com/Buffy_The_Vampire_Slayer/episodes/28079</link><title>Witch</title>

</episode>...

</Season></Episodelist>

</Show>

Greg Walters è il proprietario dellaRainyDay Solutions, LLC, una società diconsulenza in Aurora, Colorado eprogramma dal 1 972. Ama cucinare, fareescursioni, ascoltare musica e passare iltempo con la sua famiglia. Il suo sito webè www.thedesignatedgeek.net.

Page 7: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #69 8 indice ^

HHOOWW--TTOOScritto da Greg Walters PPrrooggrraammmmaarree II nn PPyytthhoonn :: PPaarrttee 4400

L a volta scorsa abbiamo avuto unadiscussione di massima sulle API di

TVRag web. Ora inizieremo a guardarela scrittura del codice per lavorarci.

L'obiettivo di questa parte è diiniziare il processo di creazione delcodice, che sarà un modulo riusabileche potrà essere importato in qualsiasiprogramma python e fornirà un facileaccesso alle API.

Sebbene le API TVRage ci danno uncerto numero di cose da poter fare, emolte di più la versione registrata, ciconcentreremo solo su queste trechiamate:1 - Cercare la trasmissione tramitenome e ottenere lo ShowID2 –Ottenere le informazioni sullatrasmissione in base allo ShowID3 –Ottenere delle informazioni sullospecifico episodio in base allo ShowID

La volta scorsa vi ho mostrato lechiamate API “non registrate” eaccessibili da chiunque. Questa voltauseremo le chiamate registrate,utilizzando una mia chiave diregistrazione. Sto per condividere convoi questa chiave (TVRage è aconoscenza del fatto). Comunque vi

chiedo il favore, se userete le API, diregistrarvi e ottenere la vostra chiavepersonale e di non abusare del sito. Viprego inoltre di considerare disostenere i loro continui sforzi facendouna donazione.

Creeremo tre routine principali perfare le chiamate e restituire leinformazioni, tre routine che sarannousate permostrare le informazioni(assumendo che stiamo in modalità“stand alone”) e una routine Main perfare il lavoro, ancora supponendo chesi stia lavorando in modalità “standalone”.

Ecco qui la lista delle routine chestiamo per creare (benché non tuttequesta volta. Voglio lasciare spazio adaltro in questo numero).

def FindIdByName(self,showname, debug = 0)

def GetShowInfo(self, showid,debug = 0)

def GetEpisodeList(self,showid, debug = 0)

def DisplaySearchResult(self,ShowListDict)

def DisplayShowInfo(self, dict)

def DisplayEpisodeList(self,SeriesName, SeasonCount,EpisodeList)

def main()

La routine FindByName prendeuna stringa (showname), effettua lachiamata alle API, analizza la rispostaXML e ritorna una lista di trasmissioniche coincidono con le informazioni inun dizionario, così questa sarà una listadi dizionari. GetShowInfo prende loshowid dalla routine precedente eritorna un dizionario di informazionirelative alle serie. AncheGetEpisodeList usa lo showid dallaprecedente routine e ritorna una listadi dizionari contenenti informazioniper ciascun episodio.

Useremo una serie di stringhe pertenere la chiave e l'URL di base per poiaggiungerci quello di cui abbiamobisogno. Per esempio, considerate ilseguente codice (lo svilupperemo piùtardi).

self.ApiKey ="Itnl8IyY1hsR9n0IP6zI"

self.FindSeriesString ="http://services.tvrage.com/myfeeds/search.php?key="

La chiamata che abbiamo bisognodi inviare (per ottenere una lista diinformazioni sulle serie con l'Id dellaserie) potrebbe essere:

http://services.tvrage.com/myfeeds/search.php?key=Itnl8IyY1 hsR9n0IP6zI&show={ShowName}

Uniamo la stringa così...

strng = self.FindSeriesString +self.ApiKey + "&show=" +showname

Per gli scopi del test userò unatrasmissione dal titolo “Continuum”che, se non l'avete mai vista, è unmeraviglioso spettacolo difantascienza sulla rete Showcase fuoridal Canada. Userò questa trasmissioneper alcune ragioni. Primo, ci sono solo(al momento della scrittura) duetrasmissioni che corrispondono allastringa di ricerca “Continuum”, ciòrende facile il debug, e in secondoluogo c'è attualmente solo unastagione di 1 0 episodi con cui avere ache fare.

Dovreste avere un' idea sul cosa sista per cercare con le routine di analisi,così ho messo le chiamate con l'URL

Page 8: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #69 9 indice ^

HOWTO - PROGRAMMARE PYTHON Parte 40completo qui sotto per poterle testareprima di iniziare con la codifica.

Cercare per nome della trasmissione...http://services.tvrage.com/myfeeds/search.php?key=Itnl8IyY1 hsR9n0IP6zI&show=continuum

Recuperare le informazioni sulla serieusando lo ShowID (sid)http://services.tvrage.com/myfeeds/showinfo.php?key=Itnl8IyY1 hsR9n0IP6zI&sid=30789

Recuperare la lista degli episodi e leinformazioni usando lo showID (sid)http://services.tvrage.com/myfeeds/episode_list.php?key=Itnl8IyY1 hsR9n0IP6zI&sid=30789

Ora che abbiamo ottenuto tuttoquesto, iniziamo con il nostro codice.

Creeremo un file dal nome“tvrage.py”. Lo useremo per uno o duedei prossimi numeri.

Cominceremo con gli importmostrati in alto a destra.

Potete notare che stiamo perusare ElementTree per fare l'analisidel XML e urlib per le comunicazioniinternet. La libreria sys è usata persys.exit.

Imposteremo ora il ciclo principalein modo tale che possiamo testare lecose mano a mano che procediamo (inbasso a destra). Ricordate che questaè l'ultima cosa nel nostro file sorgente.

Come detto prima, le primequattro righe sono le nostre stringheparziali per costruire l'URL per lafunzione che vogliamo usare(GetEpisodeListString dovrebbe staretutto su una linea). Le ultime quattro

righe inizializzano le liste che useremopiù tardi.

Primo impostiamo la stringa chesarà usata come URL (in mezzo adestra). Quindi impostiamo il socket

con un timeout predefinito di 8secondi. Poi effettuiamo la chiamata aurllib.urlopen con il nostro URLgenerato e riceveremo (speriamo) ilnostro file XML nell'oggetto usock.Chiamiamo la configurazione per

#=========================================================# IMPORTS#=========================================================from xml.etree import ElementTree as ETimport urllibimport sys

#===========================================================# Main loop#===========================================================if __name__ == "__main__":

main()

Ora iniziamo la nostra classe. I l nome è “TvRage”. Creeremo inoltre la routine __init__.

class TvRage:def __init__(self):

self.ApiKey = "Itnl8IyY1hsR9n0IP6zI"self.FindSeriesString = "http://services.tvrage.com/myfeeds/search.php?key="self.GetShowInfoString = "http://services.tvrage.com/myfeeds/showinfo.php?key="self.GetEpisodeListString =

"http://services.tvrage.com/myfeeds/episode_list.php?key="self.ShowList = []self.ShowInfo = []self.EpisodeList = []self.EpisodeItem = []

def FindIdByName(self,showname,debug = 0):strng = self.FindSeriesString + self.ApiKey + "&show=" + shownameurllib.socket.setdefaulttimeout(8)usock = urllib.urlopen(strng)tree = ET.parse(usock).getroot()usock.close()foundcounter = 0self.showlist = []

Page 9: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #69 1 0 indice ^

HOWTO - PROGRAMMARE PYTHON Parte 40ElementTree così da poter analizzarele informazioni contenute nel XML (sevi perdete qui, per favore rileggete imiei articoli sull'XML (parte 1 0, 1 1 e 1 2che sono apparsi nei numeri 36,37,e 38di FCM)). Poi chiudiamo il socket einizializziamo il contatore per ilnumero di coincidenze trovate eripristiniamo la lista showlist a una listavuota.

Ora procederemo per passiattraverso le informazioni XML usandoil tag 'show' come genitore per quelloche vogliamo. Ricordate che leinformazioni restituite sono piuttostosomiglianti a quanto mostrato in alto adestra.

Andremo in ogni gruppo diinformazioni per il genitore 'show'analizzando le informazioni. In pratica,tutto quello di cui abbiamo realmentebisogno è il nome della trasmissione(<showname>) e lo showid (<showid>)mostrato in basso a sinistra, magestiremo tutti i risultati.

Discuterò il primo e voi capirete irimanenti. Mano a mano cheprocederemo nelle informazioni,cercheremo i tag (in basso a sinistra)che coincidono con quelli voluti. Se netroviamo qualcuno, gli assegniamouna variabile temporanea e lamettiamo dentro al dizionario comevalore con chiave corrisponde a ciò chestiamo inserendo. Nel caso visto sopra,stiamo cercando il tag 'showid' nei datiXML. Quando lo troviamo, loassegniamo come valore alla chiave'ID' del dizionario.

La porzione successiva (nellaprossima pagina in alto a destra) ha ache fare con il genere dellatrasmissione. Come potete vedere dalpezzettino di codice XML sopra,questa trasmissione ha quattrodifferenti generi in cui può esserecatalogata. Azione, Crimine,Drammatico e Fantascienza.Dobbiamo gestire ciascuno di essi.

Infine, incrementiamo la variabilefoundcounter e aggiungiamo questo

<Results><show>

<showid>30789</showid><name>Continuum</name><link>http://www.tvrage.com/Continuum</link><country>CA</country><started>2012</started><ended>0</ended><seasons>2</seasons><status>Returning Series</status><classification>Scripted</classification><genres>

<genre>Action</genre><genre>Crime</genre><genre>Drama</genre><genre>Sci-Fi</genre>

</genres></show>...

</Results>

for node in tree.findall('show'):showinfo = []genrestring = Nonedict = {}for n in node:

if n.tag == 'showid':showid = n.textdict['ID'] = showid

elif n.tag == 'name':showname = n.textdict['Name'] = showname

elif n.tag == 'link':showlink = n.textdict['Link'] = showlink

elif n.tag == 'country':showcountry = n.textdict['Country'] = showcountry

elif n.tag == 'started':showstarted = n.textdict['Started'] = showstarted

elif n.tag == 'ended':showended = n.textdict['Ended'] = showended

elif n.tag == 'seasons':showseasons = n.textdict['Seasons'] = showseasons

elif n.tag == 'status':showstatus = n.textdict['Status'] = showstatus

elif n.tag == 'classification':showclassification = n.textdict['Classification'] = showclassification

Page 10: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #69 1 1 indice ^

HOWTO - PROGRAMMARE PYTHON Parte 40dizionario nella lista 'showlist'. Quindirifacciamo il procedimento fino a chenon ci sono ulteriori dati XML. Unavolta che tutto è fatto, restituiamo lalista dei dizionari (in basso a destra).

La maggior parte del codice è autoesplicativo. Ci concentreremo sul ciclofor, utilizzato per stampare leinformazioni. Passiamo ciclicamenteattraverso ogni elemento della listadei dizionari e stampiamo unavariabile contatore, il nome dellatrasmissione (c['Name']) e l'id. Ilrisultato assomiglia a questo ...

Enter Series Name -> continuum2 Found----------------------1 - Continuum - 307892 - Continuum (Web series) -32083Enter Selection or 0 to exit ->

Per favore ricordate che la lista hacome base lo zero, così quandol'utente inserisce '1 ' sta in realtàchiedendo il dizionario numero 0.Facciamo questo perché'normalmente' la gente pensa che ilconteggio parta da '1 ' e non da zero. Equindi possiamo usare 0 per usciredalla routine, evitando che usino 'Q' o'q' o '-1 '.

Ora la routine Main che collega iltutto per noi.

Per oggi, inizieremo appena laroutine (in a mezzo a destra) e lacontinueremo la prossima volta.

La prossima volta aggiungeremo lealtre routine. Per adesso il codice puòessere trovato pressohttp://pastebin.com/6iw5NQrW

Arrivederci a presto.

Greg Walters è il proprietario dellaRainyDay Solutions, LLC, una società diconsulenza in Aurora, Colorado eprogramma dal 1 972. Ama la cucina, leescursioni, la musica e passare il tempocon la sua famiglia. Il suo sito web èwww.thedesignatedgeek.net.

elif n.tag == 'genres':for subelement in n:

if subelement.tag == 'genre':if subelement.text != None:

if genrestring == None:genrestring = subelement.text

else:genrestring += " | " + subelement.text

dict['Genres'] = genrestring

foundcounter += 1self.showlist.append(dict)

return self.showlist#========================================================

La prossima cosa che faremo sarà creare la routine che mostra tutti i nostri risultati.

def DisplayShowResult(self, ShowListDict):lcnt = len(ShowListDict)print "%d Found" % lcntprint "------------------------"cntr = 1for c in ShowListDict:

print "%d - %s - %s" % (cntr,c['Name'],c['ID'])cntr += 1

sel = raw_input("Enter Selection or 0 to exit -> ")return sel

def main():tr = TvRage()#--------------------# Find Series by name#--------------------nam = raw_input("Enter Series Name -> ")if nam != None:

sl = tr.FindIdByName(nam)which = tr.DisplayShowResult(sl)if which == 0:

sys.exit()else:

option = int(which)-1id = sl[option]['ID']print "ShowID selected was %s" % id

Page 11: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #70 8 indice ^

HHOOWW--TTOOScritto da Greg Walters PPrrooggrraammmmaarree iinn PPyytthhoonn :: PPaarrttee 4411

Lo scorsomese abbiamo iniziato lanostra versione a linea di comando di

una libreria perparlare con leAPI diTVRageweb. Questomesecontinueremo a incrementare questalibreria. Se non avete il codice dalmesescorso, perfavore prendetelo dapastebin(http://pastebin.com/6iw5NQrW) perchéaggiungeremo a quel codice.

Nello stato in cui abbiamo lasciato ilcodice, voi potreste eseguire ilprogramma e inserire nella finestra delterminale il nome di uno spettacolotelevisivo di cui volete delle informazioni.Ricordate, abbiamo usato la trasmissioneContinuum. Una volta premuto <Invio>, ilprogramma chiamerà le API edeffettuerà una ricerca pernomedellospettacolo e quindi restituirà una lista dinomi che corrispondono alla vostraimmissione. Dovete quindi scegliere dallalista inserendo un numero e ilprogramma dovrebbemostrarvi“ShowID selected was 30789". Oracreeremo il codice che userà quelloShowID perottenere informazioni sullaserie. Un'altra cosa da tenere in mente: leroutine di visualizzazione esistonopraticamente perprovare che la routinefunziona. L'obiettivo finale è creare una

libreria riusabile che può esserereimpiegata in qualcosa come unprogramma con interfaccia utente graficaGUI. Sentitevi liberi di modificare leroutine di visualizzazione se voletesfruttare di più le funzionalità autonomedella libreria.

L'ultima routine che abbiamo creatonella classe era “DisplayShowResult”.Appena dopo quella e prima della routine“main” ci metteremo la nostra successivaroutine. Le informazioni che restituirà (cisono altre informazioni, ma noi useremosolo quelle della lista qui sotto) saranno inun dizionario e conterranno (sedisponibili):• Show ID• ShowName• ShowLink•Origin Countryofnetwork• Numberofseasons• Series image• YearStarted• Date Started

• Date Ended• Status (cancelled - cancellato, returning -sta peressere riproposto, current - incorso, etc)• Classification (scripted - sceneggiato,reality, etc)• Series Summary• Genre(s)• Runtime in minutes• Nameofthe networkthatoriginallyaired the show(chi lo hamesso in onda

perprimo)• Networkcountry (pressapoco la stessacosa delPaese di Origine)• Air time• AirDay (della settimana)• TimeZone

Quellomostrato sopra è l'inizio delcodice.

Dovreste riconoscere la maggior

def GetShowInfo(self,showid,debug=0):showidstr = str(showid)strng = self.GetShowInfoString + self.ApiKey + "&sid=" + showidstrurllib.socket.setdefaulttimeout(8)usock = urllib.urlopen(strng)tree = ET.parse(usock).getroot()usock.close()dict = {}

for child in tree:if child.tag == 'showid':

dict['ID'] = child.textelif child.tag == 'showname':

dict['Name'] = child.textelif child.tag == 'showlink':

dict['Link'] = child.textelif child.tag == 'origin_country':

dict['Country'] = child.textelif child.tag == 'seasons':

dict['Seasons'] = child.textelif child.tag == 'image':

dict['Image'] = child.textelif child.tag == 'started':

dict['Started'] = child.textelif child.tag == 'startdate':

dict['StartDate'] = child.text

Page 12: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #70 9 indice ^

HOWTO - PROGRAMMARE IN PYTHON Parte 41

parte del codice dall'ultima volta. Non ècambiatomolto. Qui c'è dell'altro codice(mostrato sotto).

Comepotete vedere (sopra), non c'èniente di veramente nuovo anche inquesto pezzo di codice, se stateseguendo la serie di articoli. Stiamousando un ciclo forpercontrollareciascun tag nel file XMLperuno specificovalore. Se lo troviamo, lo assegniamo a unelemento deldizionario.

Ora le cose diventano un po' piùcomplicate. Controlleremo il tag “genres”(generi -N.d.T.). Questo ha dei tag figli aldi sotto con il nome di “genre”. Perognispettacolo fornito, ci possono esseremolteplici generi. Dobbiamo appendere igeneri a una stringamano amano chevengono su e separarli con un barraverticale e due spazi come questo “ | “(mostrato in alto a destra).

Ora torniamo al codice “normale”(mostrato in mezzo a sinistra) che avetegià visto: l'unica cosa un po' differente è il

tag "network", che ha un attributo"country". Prendiamo i dati dell'attributocercando "child.attrib['attributetag']"invece di "child.text".

Quella è la fine di questa routine. Ora(sotto) dobbiamo in qualchemodomostrare le informazioni ottenute percuiabbiamo lavorato duramente. Creeremouna routine chiamata “DisplayShowinfo”.

Ora, dobbiamo aggiornare la routine“main” (nella prossima pagina, mostratain alto a destra) persupportare le nostredue nuove routine. Vi sto dando l'interaroutine qui sotto, ma il nuovo codice èmostrato in neretto.

Nella prossima pagina, in basso asinistra, c'è il risultato prodotto da“DisplayShowInfo”, così come dovrebbeapparire assumendo che abbiate scelto

come spettacolo “Continuum”.

Perfavore notate che non stomostrando le informazioni relative al fusoorario, ma sentitevi liberi di aggiungerle,

elif child.tag == 'ended':dict['Ended'] = child.text

elif child.tag == 'status':dict['Status'] = child.text

elif child.tag == 'classification':dict['Classification'] = child.text

elif child.tag == 'summary':dict['Summary'] = child.text

elif child.tag == 'genres':genrestring = Nonefor subelement in child:

if subelement.tag == 'genre':if subelement.text != None:

if genrestring == None:genrestring = subelement.text

else:genrestring += " | " + subelement.text

dict['Genres'] = genrestring

elif child.tag == 'runtime':dict['Runtime'] = child.text

elif child.tag == 'network': # has attributedict['NetworkCountry'] = child.attrib['country']dict['Network'] = child.text

elif child.tag == 'airtime':dict['Airtime'] = child.text

elif child.tag == 'airday':dict['Airday'] = child.text

elif child.tag == 'timezone':dict['Timezone'] = child.text

return dict

def DisplayShowInfo(self,dict):print "Show: %s" % dict['Name']print "ID: %s Started: %s Ended: %s Start Date: %s Seasons: %s" %

(dict['ID'],dict['Started'],dict['Ended'],dict['StartDate'],dict['Seasons'])print "Link: %s" % dict['Link']print "Image: %s" % dict['Image']print "Country: %s Status: %s Classification: %s" %

(dict['Country'],dict['Status'],dict['Classification'])print "Runtime: %s Network: %s Airday: %s Airtime: %s" %

(dict['Runtime'],dict['Network'],dict['Airday'],dict['Airtime'])print "Genres: %s" % dict['Genres']print "Summary: \n%s" % dict['Summary']

Page 13: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #70 1 0 indice ^

HOWTO - PROGRAMMARE IN PYTHON Parte 41se preferite.

Poi abbiamobisogno di lavorare sulleroutine per la lista degli episodi dellaserie. La routine “che fa il lavoro” saràchiamata “GetEpisodeList” e fornirà leseguenti informazioni…• Season• EpisodeNumber• Season EpisodeNumber (il numero diepisodi della stagione)

• Production Number• AirDate• Link• Title• Summary• Rating• Screen Capture Image ofEpisode (sedisponibile)

Prima di partire con il codice,potrebbe essere utile rivisitare che cosa

restituisce la richiesta alle API della listadegli episodi. Somiglia a quellomostratonella prossima pagina in alto a destra.

Le informazioni perciascun episodiosono nel tag “episode”, che è un figlio di“Season”, che è un figlio di “EpisodeList”,che é un figlio di “Show”. Dobbiamoessere attenti a come analizziamo ciò.

Come la maggiorparte delle routine chequesta volta "fanno il lavoro", le primelinee (sotto) sono ora abbastanza facili dacomprendere.

Dobbiamoquindi cercare i tag“name” e “totalseasons”, sotto al tag“root” e al tag “Show”. Una volta cheabbiamo fatto con questi, cerchiamo i tag

def main():tr = TvRage()#--------------------# Find Series by name#--------------------nam = raw_input("Enter Series Name -> ")if nam != None:

sl = tr.FindIdByName(nam)which = tr.DisplayShowResult(sl)if which == 0:

sys.exit()else:

option = int(which)-1id = sl[option]['ID']print "ShowID selected was %s" % id

#------------------------------# Get Show Info#------------------------------showinfo = tr.GetShowInfo(id)#------------------------------# Display Show Info#------------------------------tr.DisplayShowInfo(showinfo)

ShowID selected was 30789Show: ContinuumID: 30789 Started: 2012 Ended: None Start Date:May/27/2012 Seasons: 2Link: http://www.tvrage.com/ContinuumImage: http://images.tvrage.com/shows/31/30789.jpgCountry: CA Status: Returning Series Classification:ScriptedRuntime: 60 Network: Showcase Airday: SundayAirtime: 21:00Genres: Action | Crime | Drama | Sci-FiSummary:Continuum is a one-hour police drama centered on KieraCameron, a regular cop from 65 years in the future whofinds herself trapped in present day Vancouver. She isalone, a stranger in a strange land, and has eight of themost ruthless criminals from the future, known as Liber8,loose in the city.

Lucky for Kiera, through the use of her CMR (cellularmemory recall), a futuristic liquid chip technologyimplanted in her brain, she connects with Alec Sadler, aseventeen-year-old tech genius. When Kiera calls and Alecanswers, a very unique partnership begins.

Kiera’s first desire is to get "home." But until shefigures out a way to do that, she must survive in ourtime period and use all the resources available to her totrack and capture the terrorists before they alterhistory enough to change the course of the future. Afterall, what’s the point of going back if the future isn’tthe one you left?

def GetEpisodeList(self,showid,debug=0):showidstr = str(showid)strng = self.GetEpisodeListString + self.ApiKey

+ "&sid=" + showidstrurllib.socket.setdefaulttimeout(8)usock = urllib.urlopen(strng)tree = ET.parse(usock).getroot()usock.close()for child in tree:

Page 14: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #70 1 1 indice ^

HOWTO - PROGRAMMARE IN PYTHON Parte 41

“EpisodeList” e “Season”. Notate che iltag “Season” ha un attributo. Potrestenotare (nel suddetto codice) che nonstiamo includendo neldizionario i dati di“Showname”o “Totalseasons”. Li stiamoassegnando a una variabile che saràrestituita, alla fine della routine, al codicechiamante.

Ora che abbiamoquesta porzione didati, diamoci da fare con le informazionispecifiche dell'episodio (mostrate sotto).

Quello che resta ora (in basso asinistra) è appendere le informazionispecifiche dell'episodio (che abbiamogiàmesso nel dizionario) nella nostra lista eproseguire. Una volta che abbiamo fatto

con tutti gli episodi, ritorniamo allaroutine chiamante e, come detto prima,restituiamo tre elementi di dati,“ShowName”, “TotalSeasons” e la lista didizionari.

Poi abbiamobisogno di creare lanostra routine di visualizzazione. Di

nuovo, è abbastanza facile. L'unica cosache potreste non riconoscere sono lelinee “ife.has_key(‘keynamehere’)“.Questo è un controllo peressere sicuriche ci siano veramente dei dati nellevariabili “Rating” e “Summary”.

Alcuni spettacoli non hanno queste

<Show><name>Continuum</name><totalseasons>2</totalseasons><Episodelist><Season no="1"><episode><epnum>1</epnum><seasonnum>01</seasonnum><prodnum/><airdate>2012-05-27</airdate><link>http://www.tvrage.com/Continuum/episodes/1065162187</link><title>A Stitch in Time</title><summary>Inspector Kiera Cameron loses everything she has and findsherself on a new mission when she and eight dangerousterrorists are transported from their time in 2077 back to2012 during the terrorist’s attempt to escape execution.She takes on a new identity and joins the VPD in order tostop the terrorists’ reign of violence. Along the way, shebefriends Alec Sadler, the 17 year old who will one daygrow up to create the technology her world is built upon.</summary><rating>8.8</rating><screencap>http://images.tvrage.com/screencaps/154/30789/1065162187.png</screencap></episode>

if child.tag == 'name':ShowName = child.text

elif child.tag == 'totalseasons':TotalSeasons = child.text

elif child.tag == 'Episodelist':for c in child:

if c.tag == 'Season':dict = {}seasonnum = c.attrib['no']for el in c:

if el.tag == 'episode':dict={}dict['Season'] = seasonnumfor ep in el:

if ep.tag == 'epnum':dict['EpisodeNumber'] = ep.text

elif ep.tag == 'seasonnum':dict['SeasonEpisodeNumber'] = ep.text

elif ep.tag == 'prodnum':dict['ProductionNumber'] = ep.text

elif ep.tag == 'airdate':dict['AirDate'] = ep.text

elif ep.tag == 'link':dict['Link'] = ep.text

elif ep.tag == 'title':dict['Title'] = ep.text

elif ep.tag == 'summary':dict['Summary'] = ep.text

elif ep.tag == 'rating':dict['Rating'] = ep.text

elif ep.tag == 'screencap':dict['ScreenCap'] = ep.text

self.EpisodeItem.append(dict)return ShowName,TotalSeasons,self.EpisodeItem

Page 15: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #70 1 2 indice ^

HOWTO - PROGRAMMARE IN PYTHON Parte 41informazioni, così dobbiamo includere ilcontrollo perrendere più carini i datistampati a schermo (mostrati in alto adestra).

Tutto quello che rimane è aggiornarela nostra routine “main” (prossimapagina, in alto a destra). Ancora una volta,sto perfornirvi la routine “main”completa con il nuovo codice ingrassetto.

Adesso, se salvate ed eseguite ilprogramma, verranno visualizzati irisultati di “GetEpisodeList” e di“DisplayEpisodeList”. Mostrato in basso adestra c'è un pezzetto delle informazionisull'Episodio.

Questo è tutto perquestomese.Come al solito, potete trovare il codicesorgente completo su pastebin, pressohttp://pastebin.com/kWSEfs2E. Speroche vi divertiate a giocare con la libreria.Ci sono ulteriori informazioni disponibilidalle API che potete includere. Perfavorericordate, TVRage forniscegratuitamente queste informazioni,quindi prendete in considerazione unadonazione peraiutare il loro sforzonell'aggiornamento delle API e pertuttoil loro duro lavoro.

Arrivederci alla prossima volta.Divertitevi.

def DisplayEpisodeList(self,SeriesName,SeasonCount,EpisodeList):print "--------------------------------------"print "Series Name: %s" % SeriesNameprint "Total number of seasons: %s" % SeasonCountprint "Total number of episodes: %d" % len(EpisodeList)print "--------------------------------------"for e in EpisodeList:

print "Season: %s" % e['Season']print " Season Episode Number: %s - Series Episode Number: %s" %

(e['SeasonEpisodeNumber'],e['EpisodeNumber'])print " Title: %s" % e['Title']if e.has_key('Rating'):

print " Airdate: %s Rating: %s" % (e['AirDate'],e['Rating'])else:

print " Airdate: %s Rating: NONE" % e['AirDate']if e.has_key('Summary'):

print " Summary: \n%s" % e['Summary']else:

print " Summary: NA"print "==========================="

print "------------ End of episode list ------------"

--------------------------------------Series Name: ContinuumTotal number of seasons: 2Total number of episodes: 10--------------------------------------Season: 1

Season Episode Number: 01 - Series Episode Number: 1Title: A Stitch in TimeAirdate: 2012-05-27 Rating: 8.8Summary:

Inspector Kiera Cameron loses everything she has and finds herself on a new mission whenshe and eight dangerous terrorists are transported from their time in 2077 back to 2012during the terrorist’s attempt to escape execution. She takes on a new identity andjoins the VPD in order to stop the terrorists’ reign of violence. Along the way, shebefriends Alec Sadler, the 17 year old who will one day grow up to create the technologyher world is built upon.===========================

Page 16: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #70 1 3 indice ^

Greg Walters è il proprietario dellaRainyDay Solutions, LLC, una società diconsulenza in Aurora, Colorado eprogramma dal 1 972. Ama cucinare, fareescursioni, ascoltare musica e passare iltempo con la sua famiglia. Il suo sito webè www.thedesignatedgeek.net.

HOWTO - PROGRAMMARE IN PYTHON Parte 41

def main():tr = TvRage()#--------------------# Find Series by name#--------------------nam = raw_input("Enter Series Name -> ")if nam != None:

sl = tr.FindIdByName(nam)which = tr.DisplayShowResult(sl)if which == 0:

sys.exit()else:

option = int(which)-1id = sl[option]['ID']print "ShowID selected was %s" % id

#------------------------------# Get Show Info#------------------------------showinfo = tr.GetShowInfo(id)#------------------------------# Display Show Info#------------------------------tr.DisplayShowInfo(showinfo)#-----------------------------# Get Episode List#-----------------------------SeriesName,TotalSeasons,episodelist = tr.GetEpisodeList(id)#-----------------------------# Display Episode List#-----------------------------tr.DisplayEpisodeList(SeriesName,TotalSeasons,episodelist)#-----------------------------

Page 17: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #71 8 indice ^

HHOOWW--TTOOScritto da Greg Walters PPrrooggrraammmmaarree II nn PPyytthhoonn :: PPaarrttee 4422

A ssumiamo che voi abbiate decisodi creare un centro multimediale

per la vostra stanza di famiglia. Aveteun computer dedicato per ilmeraviglioso programma XMBC.Avete speso dei giorni per estrarre ivostri film in DVD e le serie TV sulcomputer: avete fatto la ricerca enominato i file nel modo corretto. Madiciamo che una delle vostre seriepreferite sia NCIS e voi avete in DVDogni episodio che potete ottenere.Avete trovato un posto che forniscel'episodio corrente. Voi volete trovarequale sia il prossimo episodio equando sarà trasmesso. In più voleteuna lista di tutti gli episodi in TV perimpressionare i vostri amici.

Questo è il progetto che stiamoper iniziare questo mese. Il nostroprimo compito è scavare nella cartellache contiene i vostri spettacoli TV,estrarre il nome della serieincludendo il nome e il numero dellastagione e il numero dell'episodio.Tutte questa informazioni andrannoin un database per un facileimmagazzinamento.

Secondo XMBC, dovrestedenominare ciascuno dei vostri file di

episodio in questo modo:

Tv.Show.Name.SxxExx.Episodename here if you care.extension

Così,lasciateci usare il primoepisodio di NCIS come esempio. Ilnome del file per un file AVI dovrebbeessere:

NCIS.S01E01.Yankee White.avi

e l'ultimo episodio sarebbe:

NCIS.S10E17.Prime Suspect.avi

Se voi avete il nome di unospettacolo che ha più di una parola,potrebbe assomigliare a questo:

Doctor.Who.2005.S07E04.ThePower of Three.mp4

La struttura della directorydovrebbe essere come la seguente:

TVShows2 Broke Girls

Season 1Episode 1Episode 2...Season 2...

Doctor Who 2005Season 1

...Season 2...

e così via. Ora che sappiamo che cosastiamo cercando e dove sarà,procediamo.

Molto tempo fa, creammo unprogramma per fare un database deinostri file MP3. Credo sia stato nelnumero 35 e che fosse parte delnumero 9 di questa serie. Usammouna routine WalkThePath per cercarericorsivamente attraverso tutte lecartelle di un percorso iniziale e tirarefuori tutti i nomi di file che avevanouna estensione “.mp3”. Riutilizzeremomolto di quella routine e lamodificheremo per i nostri scopi. Inquesta versione stiamo cercando i filevideo che hanno una di questeestensioni:

.avi

.mkv

.m4v

.mp4

che sono estensioni molto comuniper i file video nel mondo dei mediadel pc.

Ora cominceremo con la prima

parte del nostro progetto: create unfile chiamato “tvfilesearch.py”.Assicuratevi di salvarlo quandoavremo finito questo mese perché cilavoreremo sopra il mese prossimo.

Cominciamo con i nostri import:

import osfrom os.path import join,getsize, existsimport sysimport apswimport re

Come potete vedere stiamoimportando le librerie os, sys e apsw.Le abbiamo già usate tutte inprecedenza. Stiamo inoltreimportando la libreria 're' persupportare le Espressioni Regolari.Toccheremo rapidamente questoargomento questa volta, ma lofaremo in modo più approfondito laprossima volta.

Ora cominciamo a fare le nostreroutine finali (pagina successiva).Tutto il nostro ulteriore codice andràtra gli import e queste due routinefinali.

Questa (pagina successiva, in alto adestra) è la nostra principale routine

Page 18: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #71 9 indice ^

HOWTO - PROGRAMMARE PYTHON Parte 42di lavoro. In questa noi creiamo laconnessione al database SQLitefornito da apsw. Quindi creiamo uncursore per interagire con questa.Quindi chiamiamo la routineMakeDatabase che creerà il databasese non esiste.

I miei file TV sono situati su duedischi rigidi. Così ho creato una listaper contenere i nomi dei percorsi. Sevoi avete una sola posizione diarchiviazione, potete cambiare le trelinee per renderle come le seguenti:

startfolder ="/filepath/folder/"

WalkThePath(startfolder)

Poi creiamo la nostra routinestandard “ if name”

#==========================if __name__ == '__main__':

main()

Ora che tutte che le cose pocointeressanti sono state fatte,possiamo muoverci verso la partesuccosa del nostro progetto.Cominceremo con la routineMakeDatabase (al centro). Mettetelagiusto dopo gli import.

Discutemmo questa routine primaquando trattammo lo scanner MP3,così vi rammento solo che in questaroutine abbiamo dei controlli per

vedere se la tabella esiste, altrimenti,se non esiste, la creiamo.

Ora creeremo la routine“WalkThePath” (la seconda dal basso)

Quando noi inseriamo la routine,

forniamo il percorso dei file all'internodei quali stiamo cercando. Puliamo lavariabile showname, che useremo piùtardi e apriamo un file per i log dierrore. Quindi lasciamo fare allaroutine le sue cose. Riceviamo diritorno dalla chiamata (os.walk) una 3-tupla( percorso della directory, nomidelle directory, nomi dei file). Ilpercorso della directory è una stringache è il percorso per la directory, inomi della directory è una lista dei

nomi delle subdirectory nel percorsoe i nomi dei file è una lista dei nomiche non sono directory. Controlliamoquindi attraverso la lista dei nomi deifile controllando per vedere se il

nome del file termina con una dellenostre estensioni obbiettivo.

for file in [f for f in filesif f.endswith(('.avi','mkv','mp4','m4v'))]:

#=========================================def main():

global connectionglobal cursor# Create the connection and cursor.connection = apsw.Connection("TvShows.db3")cursor = connection.cursor()MakeDataBase()

#=========================================# Set your video media paths#=========================================startfolder = ["/extramedia/tv_files/","/media/freeagnt/tv_files_2/"]for cntr in range(0,2):

WalkThePath(startfolder[cntr])# Close the cursor and the database

cursor.close()connection.close()print("Finished")

#=========================================def MakeDataBase():

# IF the table does not exist, this will create the table.# Otherwise, this will be ignored due to the 'IF NOT EXISTS' clausesql = 'CREATE TABLE IF NOT EXISTS TvShows (pkID INTEGER PRIMARY KEY, Series TEXT,

RootPath TEXT, Filename TEXT, Season TEXT, EPISODE TEXT);'cursor.execute(sql)

#=========================================def WalkThePath(filepath):

showname = ""# Open the error log fileefile = open('errors.log',"w")for root, dirs, files in

os.walk(filepath,topdown=True):

Page 19: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #71 1 0 indice ^

HOWTO - PROGRAMMARE PYTHON Parte 42

Ora suddividiamo il nomecompleto del file nella estensione enel nome del file (senza estensione).Poi chiamiamo la routineGetSeasonEpisode per tirare fuori leinformazioni Stagione/Episodio chesono dentro al nome del fileassumendo che siano correttamenteformattate.

OriginalFilename,ext =os.path.splitext(file)

fl = file

isok,data =GetSeasonEpisode(fl)

GetSeasonEpisode ritorna unboolean e una lista (in questo caso”data”) che contiene il nome dellaserie,la stagione, e i numeri degliepisodi. Se un nome di file non ha ilformato corretto, la variabilebooleana “isok” (in alto a destra) saràfalse.

Poi (al centro), controlleremo pervedere se il file sia nel database. Se ècosì, non vogliamo duplicarlo.Semplicemente controlliamo usandoil nome del file. Possiamo andare piùin profondità e assicurarsi che ilpercorso sia lo stesso ma per adessoquesto è sufficiente.

Se tutto funziona come dovrebbe,

la risposta dalla query dovrebbeessere o 1 o 0. Se è 0 allora non c'è escriveremo l'informazione neldatabase. Se c'è andiamo oltre.Notate i comandi Try Except sopra esotto. Se qualcosa va male, comequalche carattere che il database nongradisce, evitiamo che il programmaabortisca. Teniamo comunque traccia

nel log dell'errore in modo tale chepossiamo gestirlo più tardi.

Stiamo semplicemente inserendoun nuovo record nel database oscrivendo nel file degli errori.

# Close the log fileefile.close

# End of WalkThePath

Ora diamo una occhiata allaroutine GetSeasonEpisode.

#=========================================def GetSeasonEpisode(filename):

filename = filename.upper()resp =

re.search(r'(.*).S\d\dE\d\d(\.*)', filename, re.M|re.I)

if isok:showname = data[0]season = data[1]episode = data[2]print("Season {0} Episode {1}".format(season,episode))

else:print("No Season/EPisode")efile.writelines('---------------------------\n')efile.writelines('{0} has no series/episode information\n'.format(file))efile.writelines('---------------------------\n\n')

sqlquery = 'SELECT count(pkid) as rowcount from TvShows where Filename ="%s";' % fl

try:for x in cursor.execute(sqlquery):

rcntr = x[0]if rcntr == 0: # It's not there, so add it

try:sql = 'INSERT INTO TvShows (Series,RootPath,Filename,Season,Episode)

VALUES (?,?,?,?,?)'cursor.execute(sql,(showname,root,fl,season,episode))

except:print("Error")efile.writelines('---------------------------\n')efile.writelines('Error writing to database...\n')efile.writelines('Filename = {0}\n'.format(file))efile.writelines('---------------------------\n\n')

except:print("Error")

print('Series - {0} File - {1}'.format(showname,file))

Page 20: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #71 1 1 indice ^

HOWTO - PROGRAMMARE PYTHON Parte 42

La porzione re.search del codice èparte della re library. Usa una stringacome modello e, in questo caso, ilnome del file che vogliamo analizzare.I re.M|re.I sono i parametri che diconoche vogliamo usare una ricerca di tipomultilinea (re.M) combinato con unignora maiuscolo minuscolo (re.I).Come ho detto primaapprofondiremo le espressioniregolari il prossimo mese, dalmomento che la nostra routine unsolo tipo di stringa series|episode. Peril modello di ricerca stiamo cercandoper: “.S” seguito da due numeridecimali , seguito da una “E” inmaiuscolo, quindi due ulteriori cifre equindi un punto. Se il nostro nome difile è come “tvshow.S01 E03.avi”,questo troverà una corrispondenza.Comunque alcune personecodificheranno i loro show in moditipo “tvshow.s01 s03.avi”o“tvshow.1 03.avi”, diventa così moltopiù difficile da gestire. Modificheremoquesta routine il prossimo mese percoprire la maggioranza dellacasistiche. La “r” permette di usareuna stringa libera per una ricerca.

Proseguendo, la ricerca ritorna unoggetto in cui noi possiamo guardare.“resp” è una risposta che è vuota senon vi è alcuna corrispondenza e, inquesto caso, vengono restituiti due

gruppi di informazioni. Il primo ci darài caratteri fino alla corrispondenza,mentre il secondo include lacorrispondenza. Così nel casodescritto sopra, group(1 ) dovrebbeessere “tvshow”, il secondo gruppodovrebbe essere “tvshow.S01 E03”.Questo è specificato dalle parentesinella ricerca “(.*)” e “(\.*)”.

if resp:showname =

resp.group(1)

Prendiamo il nome dello show dalgruppo numero uno: poi prendiamo lalunghezza di questo in modo tale chepossiamo estrarre la stringa con laserie e l'episodio con un comandosubstring.

shownamelength =len(showname) + 1

se =filename[shownamelength:shownamelength+6]

season = se[1:3]episode = se[4:6]

Poi sostituiamo tutti i punti nelnome dello show con uno spazio peressere più “leggibile da un umano”.

showname =showname.replace("."," ")

Creiamo una lista per includere ilnome dello spettacolo, stagione edepisodio e per ritornarlo con il

booleano valorizzato a True per direche le cose sono andate bene.

ret =[showname,season,episode]

return True,ret

Altrimenti se non troviamo unacorrispondenza, creiamo la nostralista contenete nessun nome delloshow e due numeri -1 , questo faràritornare un valore booleano False.

else:ret = ["",-1,-1]return False,ret

Questo è tutto il codice. Adessoandiamo a vedere come dovrebbeapparire il risultato in uscita. Dandoper scontato che le strutture dei filesiano esattamente come le mie, alcunidei risultati sullo schermo dovrebbeapparire come questo ...

Season 02 Episode 04SELECT count(pkid) as rowcountfrom TvShows where Filename ="InSecurity.S02E04.avi";Series - INSECURITY File -InSecurity.S02E04.aviSeason 01 Episode 08SELECT count(pkid) as rowcountfrom TvShows where Filename ="Prime.Suspect.US.S01E08.Underwater.avi";Series - PRIME SUSPECT US File-Prime.Suspect.US.S01E08.Underwater.avi

e così via. Potete accorciare il risultato

in uscita per impedire allo schermo difarvi diventare pazzi se lo preferite.Come abbiamo detto prima, ciascunelemento che troviamo viene messodentro al database. Qualcosa comequesto:

pkID | Series | Root Path| Filename| Season | Episode

2526 | NCIS |/extramedia/tv_files/NCIS/Season7|NCIS.S07E04.Good.Cop.Bad.Cop.avi | 7 | 4

Come sempre il listato dell'interocodice è disponibile su PasteBin.com ahttp://pastebin.com/txmmagkL

La prossima volta parleremoulteriormente dei formatiSeason|Episode, e alcune altre coseper approfondire il nostroprogramma.

Arrivederci a presto.

Greg è il proprietario della RainyDaySolutions, LLC, una società di consulenzain Aurora, Colorado e programma dal1 972. Ama cucinare, fare escursioni,ascoltare musica e passare il tempo conla sua famiglia. Il suo sito web èwww.thedesignatedgeek.net

Page 21: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #72 8 indice ^

HHOOWW--TTOOScritto da Greg Walters PPrrooggrraammmmaarree iinn PPyytthhoonn :: PPaarrttee 4433

L a volta scorsa, abbiamo iniziato unprogetto che alla fine userà il

modulo TvRage che abbiamo creato ilmese prima di questo. Oracontinueremo il progetto. Questavolta aggiungeremo funzionalità alnostro programma: migliorando laroutine che analizza il nome del file eaggiungendo due campi (TvRageId eStatus) al database. Quindi, tuffiamocidentro.

Come primo passo, faremo deicambiamenti alle nostre linee diimportazione: Per quelli che si stannounendo adesso, includerò quelle dellavolta scorsa (mostrate in alto a destra).

Le linee dopo ' import re' sonoquelle nuove per questa volta.

La prossima cosa che faremo èriscrivere la routineGetSeasonEpisode. Stiamo perbuttare via quasi tutto ciò cheabbiamo fatto il mese scorso erenderlo più flessibile attraverso ipossibili schemi stagione/episodio . Inquesta iterazione saremo in grado disupportare i seguenti schemi ...

Series.S00E00

Series.s00e00

Series.S00E00.S00E01

Series.00x00

Series.S0000

Series.0x00

Sistemeremo inoltre i problemilegati a eventuali zero iniziali mancantiprima di scrivere nel database.

Il nostro primo modello cerca diprendere file con episodi multipli. Cisono vari nomi di schemi, ma quelloche supporteremo è simile a'S01 E03.S01 E04'. Usiamo comemodello la stringa"(.*)\.s(\d{1 ,2})e(\d{1 ,2})\.s(\d{1 ,2})e(\d{1 ,2})". Questo ritorna (speriamo)cinque gruppi composti da: nome dellaserie (S[1 ]), stagione(S[2]), episodionumero 1 (S[3]), stagione (S[4]) edepisodio numero 2 (S[5]). Ricordateche le parentesi creano ciascun gruppoper il ritorno. Nel caso sopra,raggruppiamo dal primo carattere finoa “.s”, quindi due numeri, saltiamo la“e”, quindi due numeri, e ripetiamo.Così il nome del file"Monk.S01 E05.S01 E06.avi" ritorna iseguenti gruppi ...

S[1] = Monk

S[2] = 01

S[3] = 05

S[4] = 01

S[5] = 06

Stiamo usando solo i gruppi S[1 ],S[2] e S[3] in questo codice, ma si puòvedere a cosa conducono. Se troviamouna corrispondenza, impostiamo unavariabile di nome “GoOn” a vero.Questo ci permette di sapere che cosafare dopo che siamo passati attraversole varie linee If.

Così, nella prossima pagina (in altoa destra) c'è il codice per la routineGetSeasonEpisode.

Quando arriviamo a questo punto,(prossima pagina, in basso a sinistra)prepariamo il nome dello spettacolorimuovendone tutti i punti dal nome,inserendo quindi le informazioni sullastagione e sull'episodio dai vari gruppie le restituiamo. Per le informazionisulla stagione, se abbiamo un modellotipo "S00E00", la stagione avrà unozero iniziale. Tuttavia, se il modello èsimile a “xxx”, allora la stagione sipresume essere il primo carattere e isuccessivi due sono l'episodio. Per farcapire dove vogliamo andare a parare,vogliamo rendere la stagione unnumero a due cifre con uno zeroiniziale, se necessario.

Successivamente, nella nostraroutine MakeDatabase, cambieremol'istruzione SQL di creazione per

import osfrom os.path import join, getsize, existsimport sysimport apswimport re#------------------------------# NEW LINES START HERE#------------------------------from xml.etree import ElementTree as ETimport urllibimport stringfrom TvRage import TvRage

Page 22: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #72 9 indice ^

HOWTO - PROGRAMMARE PYTHON Parte 43aggiungere i due nuovi campi(prossima pagina, in alto)

Di nuovo, l'unica cosa che ècambiata dalla scorsa volta sono leultime due definizioni di campi.

Nella nostra funzioneWalkThePath, gli unici cambiamentisono le linee che inserisconoeffettivamente nel database. Questoè per supportare le nuove strutture.Se vi ricordate dalla volta scorsa,passiamo a questa funzione la cartellache contiene i nostri file TV. Nel miocaso, ci sono due cartelle, così èimpostato dentro una lista e usiamoun ciclo for per passare ciascunelemento nella funzione. Procedendoattraverso la funzione, andiamo inogni directory cercando i file conestensione del tipo .avi, .mkv, .mp4 e.m4v. Quando troviamo un file checorrisponde, lo mandiamo alla

def GetSeasonEpisode(filename):GoOn = Falsefilename = filename.upper()

This is our first pattern check.#Should catch multi episode .S01E01.S01E02 type filenamesresp = re.search(r'(.*)\.s(\d{1,2})e(\d{1,2})\.s(\d{1,2})e(\d{1,2})',filename, re.I)if resp:

showname = resp.group(1)GoOn = True

else:

Our second pattern check looks for SddEdd or sddedd...# Should catch SddEdd or sddedd

resp = re.search(r'(.*).S(\d\d?)E(\d\d?)(\.*)', filename, re.I)if resp:

showname = resp.group(1)GoOn = True

else:

The next pattern looks for ddxdd.#check for ddxddresp = re.search(r'(.*)\.(\d{1,2})x(\d{1,2})(.*)', filename, re.I)if resp:

showname = resp.group(1)GoOn = True

else:

This pattern checks for Sdddd.#check for Sddddresp = re.search(r'(.*).S(\d\d)(.\d\d?)' , filename, re.I)if resp:

showname = resp.group(1)GoOn = True

else:

And finally we try for ddd# Should catch xxxresp = re.search(r'(.*)(\d)(.\d\d?)',filename,re.I)if resp:

showname = resp.group(1)GoOn = True

if GoOn:shownamelength = len(showname) + 1showname = showname.replace("."," ")season = resp.group(2)if len(season) == 1:

season = "0" + seasonepisode = resp.group(3)ret = [showname,season,episode]return True,ret

else:ret = ["",-1,-1]return False,ret

Page 23: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #72 1 0 indice ^

HOWTO - PROGRAMMARE PYTHON Parte 43

funzione GetSeasonEpisode.Verifichiamo quindi se lo abbiamo giàinserito nel database e, se non fatto, loaggiungiamo. Sto per darvi ( in alto adestra) solo parte della routine delloscorso mese.

Le due linee in nero sono quellenuove di questa volta.

Abbiamo già fatto metà strada. Cisono poi delle funzioni di supporto perlavorare con la nostra funzioneTvRage per riempire i campi deldatabase. La nostra prima funzioneviene eseguita dopo quella WalkThePath e accede al database, ottenendoil nome della serie e interrogando ilserver TvRage per il numeroidentificativo. Una volta ottenuto,aggiorniamo il database, usiamoquindi tale numero id per interrogareancora una volta il server TvRage perottenere lo stato attuale della serie.Questo stato può essere “NewSeries”,Returning Series”, “Canceled”,“Ended” e “On Haitus”. La motivazioneper cui vogliamo questa informazioneè che, quando andiamo a controllare i

nuovi episodi, non vogliamo perderetempo con delle serie che non avrannoaltri nuovi episodi perché sono statecancellate. Così ora abbiamo lo stato epossiamo scriverlo nel database(sopra).

Ci fermeremo qui col nostro codicee daremo una occhiata alla query SQLche stiamo usando. E' un pochinodifferente da tutto ciò che abbiamofatto prima. La stringa è:

SELECT DISTINCT series FROM

TvShows WHERE tvrageid = -1

Che dice, dammi giusto una istanzadel nome della serie, non importaquante ne ho, dove il campo tvrageid èuguale a "-1 ". Se, per esempio,abbiamo 1 03 episodi di DoctorWho2005, usando il Distinct otterrò solo unrecord, assumendo che non abbiamoancora ricevuto un TvRageID.

for x inSeriesCursor.execute(sqlstring):

seriesname = x[0]

searchname =string.capwords(x[0]," ")

Stiamo usando la funzionecapwords dalla libreria string percambiare il nome della serie (x[0]) al“corretto caso” dal formato tuttomaiuscolo con cui di solito salviamo ilnome dello spettacolo. Facciamoquesto perché TvRage si aspettaqualcosa di diverso dai dati tutti inmaiuscolo e non otterremmo i risultatiche stiamo cercando. Così il nome

def MakeDataBase():# IF the table does not exist, this will create the table.# Otherwise, this will be ignored due to the 'IF NOT EXISTS' clausesql = 'CREATE TABLE IF NOT EXISTS TvShows (pkID INTEGER PRIMARY KEY, Series TEXT, RootPath TEXT, Filename TEXT,

Season TEXT, Episode TEXT, tvrageid TEXT,status TEXT);'cursor.execute(sql)

sqlquery = 'SELECT count(pkid) as rowcount from TvShows where Filename ="%s";' % fl

try:for x in cursor.execute(sqlquery):

rcntr = x[0]if rcntr == 0: # It's not there, so add it

try:sql = 'INSERT INTO TvShows

(Series,RootPath,Filename,Season,Episode,tvrageid) VALUES (?,?,?,?,?,?)'cursor.execute(sql,(showname,root,fl,season,episode,-1))

except:

def WalkTheDatabase():tr = TvRage()SeriesCursor = connection.cursor()sqlstring = "SELECT DISTINCT series FROM TvShows WHERE tvrageid = -1"

Page 24: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #72 1 1 indice ^

HOWTO - PROGRAMMARE PYTHON Parte 43

della serie “THEMAN FROM UNCLE”sarà convertito in “The Man FromUncle”. Lo usiamo nella chiamata allanostra libreria Libreria FindIdByNamedi TvRage. Questo ci fornisce l'elencodi spettacoli che corrispondono e ce limostra in modo da scegliere ilmigliore. Una volta che ne prendiamouno, aggiorniamo il database con ilnumero id e quindi chiamiamo lafunzione GetShowStatus per ottenerelo stato attuale dello spettacolo daTvRage (in basso a destra).

La funzione UpdateDatabase (inalto) usa semplicemente il nome dellaserie come chiave per aggiornare tuttirecord con l'appropriato ID TvRage.

Anche GetShowStatus (sopra) è

molto semplice. Chiamiamo lafunzione GetShowInfo dalla libreriaTvRage passando l'id che abbiamoappena ricevuto a TvRage, perottenere le informazioni sulla serie. Sericordate, TvRage fornisce molteinformazioni sulla serie, ma tuttoquello che ci interessa adesso è lostato dello spettacolo. Dal momentoche tutto è ritornato in un dizionario,cerchiamo la chiave [“Status”]. Unavolta ottenuta, aggiorniamo il

database con tale chiave eprocediamo.

Abbiamo quasi finito con il nostrocodice. Alla fine aggiungiamo una lineaalla nostra funzione main del mese

print("Requesting information on " + searchname)sl = tr.FindIdByName(searchname)which = tr.DisplayShowResult(sl)if which == 0:

print("Nothing found for %s" % seriesname)else:

option = int(which)-1id = sl[option]['ID']UpdateDatabase(seriesname,id)GetShowStatus(seriesname,id)

def UpdateDatabase(seriesname,id):idcursor = connection.cursor()sqlstring = 'UPDATE tvshows SET tvrageid = ' + id + ' WHERE series = "' + seriesname + '"'try:

idcursor.execute(sqlstring)except:

print "error"

def GetShowStatus(seriesname,id):tr = TvRage()idcursor = connection.cursor()dict = tr.GetShowInfo(id)status = dict['Status']sqlstring = 'UPDATE tvshows SET status = "' + status + '" WHERE series = "' + seriesname + '"'try:

idcursor.execute(sqlstring)except:

print "Error"

startfolder = ["/extramedia/tv_files","/media/freeagnt/tv_files_2"]#for cntr in range(0,2):

#WalkThePath(startfolder[cntr])WalkTheDatabase()# Close the cursor and the databasecursor.close()connection.close()print("Finished")

Page 25: dl.fullcirclemagazine.orgdl.fullcirclemagazine.org/issuePY07_it.pdf · dl.fullcirclemagazine.org ... 7,+...

full circle magazine #72 1 2 indice ^

Greg Walters è il proprietario dellaRainyDay Solutions, LLC, una società diconsulenza in Aurora, Colorado eprogramma dal 1 972. Ama cucinare, fareescursioni, ascoltare musica e passare iltempo con la sua famiglia. Il suo sito webè www.thedesignatedgeek.net.

HOWTO - PROGRAMMARE PYTHON Parte 43scorso (in nero, sotto) per chiamare lafunzione “WalkTheDatabase” dopoche abbiamo finito di ottenere tutti inostri nomi di file. Di nuovo, sto perdarvi solo parte della funzione Main,giusto perché possiate trovare il postocorretto per piazzare la nuova linea.

Questo è tutto il nostro codice.Andiamomentalmente oltre a quelloche succede quando mandiamo inesecuzione il programma.

Primo, creiamo il database se nonesiste.

Quindi, passiamo attraverso ipercorsi predefiniti, cercando i file chehanno una delle seguenti estensioni:

.AVI, .MKV, .M4V, .MP4

Quando ne troviamo uno, loscorriamo e cerchiamo di analizzare ilnome del file cercando il nome di unaserie, il numero di stagione e il numerodi episodio. Prendiamo questainformazione e la mettiamo neldatabase, se non c'è ancora.

Una volta che abbiamo cercato ifile, interroghiamo il databasecercando i nomi delle serie che nonhanno un ID TvRage associato. Poiinterrogheremo le API TvRage echiederemo i file che corrispondono a

quell'ID. Ciascuna serie passeràattraverso questa fase ancora unavolta. La seguente schermata mostra,in questo caso, le opzioni per la serie tvMidsomerMurders.

Ho inserito (in questo caso) 1 , cheassocia queste serie con l'ID TvRage4466. Questo è inserito nel database eusato in seguito per richiedere lo statoattuale della serie, di nuovo daTvRage. In questo caso ci vienerestituito “Returning Serie”, che vienequindi inserito nel database eproseguiamo.

Dal momento che facciamol'esecuzione iniziale nel database, civorrà un certo tempo e richiederà lavostra attenzione, perché ogni singolaserie ha bisogno di chiedere che ilnumero ID corrisponda. La buonanotizia è che ciò deve essere fatto unasola volta. Se siete in qualche modo"normali" non vorrete aver a che farecon ciò. Io ho 1 57 differenti serie dafare, quindi ciò richiede un certotempo. Poiché sono stato attentonell'impostare i nomi dei file(controllando TvRage e TheTvDb.comper la corretta denominazione delnome della serie), la maggioranzadelle ricerche erano l'opzione #1 .

Giusto per conoscenza, oltre lametà delle serie che ho o sono finite o

sono state cancellate. Questodovrebbe dirvi qualcosa sul gruppo dietà in cui ricado.

Il codice completo è disponibile,come sempre, su PasteBin pressohttp://pastebin.com/MeuGyKpX

La prossima volta continueremocon l'integrazione con TvRage. Fino adallora vi auguro di trascorrere un buonmese!

Requesting information on Midsomer Murders5 Found------------------------1 - Midsomer Murders - 44662 - Motives and Murders - 313733 - See No Evil: The Moors Murders - 111994 - The Atlanta Child Murders - 264025 - Motives & Murders: Cracking the Case - 33322Enter Selection or 0 to exit ->