5

Sto cercando un modo semplice per salvare un file csv proveniente da un documento di Fogli Google pubblicato? Dal momento che è pubblicato, è accessibile tramite un collegamento diretto (modificato di proposito nell'esempio sotto).Come si salva un file Fogli Google come CSV da Python 3 (o 2)?

Tutti i miei browser mi chiederanno di salvare il file csv non appena lancio il collegamento.

Né:

DOC_URL = 'https://docs.google.com/spreadsheet/ccc?key=0AoOWveO-dNo5dFNrWThhYmdYW9UT1lQQkE&output=csv'  

f = urllib.request.urlopen(DOC_URL) 
cont = f.read(SIZE) 
f.close() 
cont = str(cont, 'utf-8') 
print(cont) 

, nè:

req = urllib.request.Request(DOC_URL) 
req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.13 (KHTML, like Gecko) Chrome/24.0.1284.0 Safari/537.13') 
f = urllib.request.urlopen(req) 
print(f.read().decode('utf-8')) 

stampa tutt'altro che contenuti HTML.

(provato la seconda versione dopo aver letto questo altro post: Download google docs public spreadsheet to csv with python.)

Qualche idea su quello che sto facendo male? Sono disconnesso dal mio account Google, se questo vale tutto, ma funziona da qualsiasi browser che ho provato. Per quanto ho capito, l'API di Google Docs non è ancora stata trasferita su Python 3 e vista la grandezza "giocattolo" del mio piccolo progetto per uso personale, non sarebbe nemmeno troppo logico utilizzarlo fin dall'inizio, se Posso aggirarlo.

Nel 2 ° tentativo, ho lasciato l''User-Agent', poiché stavo pensando che forse le richieste pensate come provenienti dagli script (b/c non sono presenti informazioni di identificazione) potrebbero essere ignorate, ma non ha reso una differenza.

risposta

4

Google risponde alla richiesta iniziale con una serie di reindirizzamenti 302 di impostazione dei cookie. Se non archivi e reinvia i cookie tra le richieste, ti reindirizza alla pagina di accesso.

Quindi, il problema non è con l'intestazione User-Agent, è il fatto che per impostazione predefinita, urllib.request.urlopen non memorizza i cookie, ma seguirà i reindirizzamenti HTTP 302.

Il seguente codice funziona bene su un foglio di calcolo a disposizione del pubblico presso la posizione specificata da DOC_URL:

>>> from http.cookiejar import CookieJar 
>>> from urllib.request import build_opener, HTTPCookieProcessor 
>>> opener = build_opener(HTTPCookieProcessor(CookieJar())) 
>>> resp = opener.open(DOC_URL) 
>>> # should really parse resp.getheader('content-type') for encoding. 
>>> csv_content = resp.read().decode('utf-8') 

Dopo avervi mostrato come farlo in python vaniglia, io ora dire che il Right Way ™ è quello di utilizzare il più eccellente requests library. È extremely well documented e rende questo tipo di attività incredibilmente piacevole da completare.

Per esempio, per ottenere lo stesso csv_content come sopra utilizzando la libreria requests è semplice come:

>>> import requests 
>>> csv_content = requests.get(DOC_URL).text 

Quella singola linea esprime il vostro intento in modo più chiaro. È più facile da scrivere e più facile da leggere. Fai un favore a te stesso e a chiunque altro condivida la tua base di codice e usa semplicemente requests.

+0

Grazie per la risposta, lo apprezzo davvero! –

2

Mentre la biblioteca requests è il gold standard per le richieste HTTP da Python, questo stile di download è (mentre non è ancora deprecato) non sono suscettibili di durare nel tempo, con particolare riferimento all'uso di collegamenti, gestione dei cookie & redirect, eccUno dei motivi per cui lo non è i collegamenti preferenziali è che è meno sicuro e generalmente tale accesso dovrebbe richiedere l'autorizzazione. Invece, il modo attualmente accettato di esportare Fogli Google come CSV è di utilizzando il Google Drive API.

Quindi perché l'API di Drive? Questo non dovrebbe essere qualcosa per lo Sheets API? Bene, l'API Sheets è per foglio di calcolo funzionalità orientata, vale a dire, formattazione dei dati, ridimensionamento di colonne, creazione di grafici, convalida di celle, ecc., Mentre l'API di Drive è per file funzionalità orientata, vale a dire, importazione/esportazione, copia, rinomina, ecc.

Di seguito è un complete cmd-line solution. (Se non si utilizza Python, è possibile utilizzarlo come pseudocodice e scegliere qualsiasi lingua supportata dallo Google APIs Client Libraries.) Per lo snippet di codice, si presuma il foglio più recente denominato inventory (i file più vecchi con quel nome vengono ignorati) e DRIVE è il API del servizio endpoint:

FILENAME = 'inventory' 
SRC_MIMETYPE = 'application/vnd.google-apps.spreadsheet' 
DST_MIMETYPE = 'text/csv' 

# query for latest file named FILENAME 
files = DRIVE.files().list(
    q='name="%s" and mimeType="%s"' % (FILENAME, SRC_MIMETYPE), 
    orderBy='modifiedTime desc,name').execute().get('files', []) 

# if found, export Sheets file as CSV 
if files: 
    fn = '%s.csv' % os.path.splitext(files[0]['name'].replace(' ', '_'))[0] 
    print('Exporting "%s" as "%s"... ' % (files[0]['name'], fn), end='') 
    data = DRIVE.files().export(fileId=files[0]['id'], mimeType=DST_MIMETYPE).execute() 

    # if non-empty file 
    if data: 
     with open(fn, 'wb') as f: 
      f.write(data) 
     print('DONE') 

Se la vostra scheda è di grandi dimensioni, potrebbe essere necessario esportarlo in pezzi - vedi this page su come fare che. Se in genere sei nuovo alle API di Google, ho un (un po 'datato ma) user-friendly intro video per te. (Ci sono anche 2 video che potrebbero essere utili.)