2010-07-20 24 views
24

È possibile produrre un esempio Python di come scaricare un foglio di calcolo di Google Documenti in base all'ID della chiave e del foglio di lavoro (gid)? Non possoScaricare un foglio di calcolo da Google Documenti utilizzando Python

Ho ripulito le versioni 1, 2 e 3 dell'API. Non ho fortuna, non riesco a capire la loro API di feed di tipo ATOM compilata, il metodo privato gdata.docs.service.DocsService._DownloadFile dice che non sono autorizzato, e non voglio scrivere un intero sistema di autenticazione di Google Login me stesso. Sto per pugnalarmi in faccia a causa della frustrazione.

Ho un paio di fogli di calcolo e voglio accedervi in ​​questo modo:

username = '[email protected]' 
password = getpass.getpass() 

def get_spreadsheet(key, gid=0): 
    ... (help!) ... 

for row in get_spreadsheet('5a3c7f7dcee4b4f'): 
    cell1, cell2, cell3 = row 
    ... 

Si prega di salvare la faccia.


Update 1: ho provato quanto segue, ma nessuna combinazione di Download() o Export() sembra funzionare. (Documenti per DocsServicehere)

import gdata.docs.service 
import getpass 
import os 
import tempfile 
import csv 

def get_csv(file_path): 
    return csv.reader(file(file_path).readlines()) 

def get_spreadsheet(key, gid=0): 
    gd_client = gdata.docs.service.DocsService() 
    gd_client.email = '[email protected]' 
    gd_client.password = getpass.getpass() 
    gd_client.ssl = False 
    gd_client.source = "My Fancy Spreadsheet Downloader" 
    gd_client.ProgrammaticLogin() 

    file_path = tempfile.mktemp(suffix='.csv') 
    uri = 'http://docs.google.com/feeds/documents/private/full/%s' % key 
    try: 
    entry = gd_client.GetDocumentListEntry(uri) 

    # XXXX - The following dies with RequestError "Unauthorized" 
    gd_client.Download(entry, file_path) 

    return get_csv(file_path) 
    finally: 
    try: 
     os.remove(file_path) 
    except OSError: 
     pass 
+1

Potrebbe [questo] (http://stackoverflow.com/questions/2925985/syntaxerror-using-gdata-python-client-to-access-google-book-search-data-api/3013945#3013945) essere il tuo problema? – sje397

+0

Provato - grazie! Sembra aiutarmi a superare i problemi di accesso. –

risposta

17

Nel caso qualcuno si imbatte in questa ricerca di una soluzione rapida, ecco another (currently) working solution che non ri LY sulla libreria client GData:

#!/usr/bin/python 

import re, urllib, urllib2 

class Spreadsheet(object): 
    def __init__(self, key): 
     super(Spreadsheet, self).__init__() 
     self.key = key 

class Client(object): 
    def __init__(self, email, password): 
     super(Client, self).__init__() 
     self.email = email 
     self.password = password 

    def _get_auth_token(self, email, password, source, service): 
     url = "https://www.google.com/accounts/ClientLogin" 
     params = { 
      "Email": email, "Passwd": password, 
      "service": service, 
      "accountType": "HOSTED_OR_GOOGLE", 
      "source": source 
     } 
     req = urllib2.Request(url, urllib.urlencode(params)) 
     return re.findall(r"Auth=(.*)", urllib2.urlopen(req).read())[0] 

    def get_auth_token(self): 
     source = type(self).__name__ 
     return self._get_auth_token(self.email, self.password, source, service="wise") 

    def download(self, spreadsheet, gid=0, format="csv"): 
     url_format = "https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key=%s&exportFormat=%s&gid=%i" 
     headers = { 
      "Authorization": "GoogleLogin auth=" + self.get_auth_token(), 
      "GData-Version": "3.0" 
     } 
     req = urllib2.Request(url_format % (spreadsheet.key, format, gid), headers=headers) 
     return urllib2.urlopen(req) 

if __name__ == "__main__": 
    import getpass 
    import csv 

    email = "" # (your email here) 
    password = getpass.getpass() 
    spreadsheet_id = "" # (spreadsheet id here) 

    # Create client and spreadsheet objects 
    gs = Client(email, password) 
    ss = Spreadsheet(spreadsheet_id) 

    # Request a file-like object containing the spreadsheet's contents 
    csv_file = gs.download(ss) 

    # Parse as CSV and print the rows 
    for row in csv.reader(csv_file): 
     print ", ".join(row) 
+1

fantastico, un bell'esempio riutilizzabile! – MrColes

+0

Questa dovrebbe essere la soluzione scelta. Rimuovere la dipendenza da gdata è un vantaggio enorme e lo hai persino impacchettato in modo da poterlo utilizzare sia come app per console sia come libreria. Ho aggiunto la gestione delle eccezioni attorno alla richiesta get_auth_token ma solo così ho potuto generare un messaggio significativo quando si incontra una password errata. –

+0

Esiste un motivo per eseguire il looping dell'oggetto 'csv_file'? Perché non solo 'print csv_file.read()' - csv in, csv out! – Spacedman

0

Questa non è una risposta completa, ma Andreas Kahler scritto su una soluzione interessante CMS utilizzando Google Documenti + Google App Engline + Python. Non avendo esperienza nella zona, non riesco a vedere esattamente quale parte del codice potrebbe esserti utile, ma controlla. So che si interfaccia con un account Google Docs e suona con i file, quindi ho la sensazione che riconoscerai cosa sta succedendo. Dovrebbe almeno indirizzarti nella giusta direzione.

Google AppEngine + Google Docs + Some Python = Simple CMS

15

si potrebbe provare a utilizzare il metodo AuthSub descritto nella sezione Exporting Spreadsheets della documentazione.

Ottenere un token di accesso separato per il servizio di fogli di lavoro e sostituirlo per l'esportazione. L'aggiunta di questo al codice get_spreadsheet ha funzionato per me:

import gdata.spreadsheet.service 

def get_spreadsheet(key, gid=0): 
    # ... 
    spreadsheets_client = gdata.spreadsheet.service.SpreadsheetsService() 
    spreadsheets_client.email = gd_client.email 
    spreadsheets_client.password = gd_client.password 
    spreadsheets_client.source = "My Fancy Spreadsheet Downloader" 
    spreadsheets_client.ProgrammaticLogin() 

    # ... 
    entry = gd_client.GetDocumentListEntry(uri) 
    docs_auth_token = gd_client.GetClientLoginToken() 
    gd_client.SetClientLoginToken(spreadsheets_client.GetClientLoginToken()) 
    gd_client.Export(entry, file_path) 
    gd_client.SetClientLoginToken(docs_auth_token) # reset the DocList auth token 

Avviso Ho anche usato Export, come Download sembra dare solo file PDF.

+6

OMGITWORKS! ROUND OF APPLAUSE! OVAZIONE! SIGILLO CERTIFICABILE DI KICKASSEDNESS! Grazie Signore! Ti concedo la generosa munificenza di non meno di 50 punti di overflow dello stack! Prendili, signore - Prendili e VIVI LA VITA COME DOVREBBE ESSERE VITA! –

+0

Se potessi aggiungere un premio, lo farei anch'io. Questo mi ha appena salvato la vita al lavoro. GRAZIE MILLE! – Mizmor

+2

Una [soluzione migliore] (http://stackoverflow.com/a/18296318/462302) è ora disponibile poiché questa risposta è stata inizialmente accettata. – aculich

3

Questo non funziona più come di GData 2.0.1.4:

gd_client.SetClientLoginToken(spreadsheets_client.GetClientLoginToken()) 

Invece, si hanno a che fare:

gd_client.SetClientLoginToken(gdata.gauth.ClientLoginToken(spreadsheets_client.GetClientLoginToken())) 
+0

puoi andare dall'altra parte? accedi con gd_client e poi passa al client del foglio elettronico un token? – michael

2

Il seguente codice funziona nel mio caso (Ubuntu 10.4, Python 2.6. 5 GData 2.0.14)

import gdata.docs.service 
import gdata.spreadsheet.service 
gd_client = gdata.docs.service.DocsService() 
gd_client.ClientLogin(email,password) 
spreadsheets_client = gdata.spreadsheet.service.SpreadsheetsService() 
spreadsheets_client.ClientLogin(email,password) 
#... 
file_path = file_path.strip()+".xls" 
docs_token = gd_client.auth_token 
gd_client.SetClientLoginToken(spreadsheets_client.GetClientLoginToken()) 
gd_client.Export(entry, file_path) 
gd_client.auth_token = docs_token 
24

La biblioteca https://github.com/burnash/gspread è un modo più nuovo più semplice per interagire con Google Spreadsheets, piuttosto che le vecchie risposte a questa che suggeriscono la libreria gdata che non è solo troppo di basso livello, ma è anche eccessivamente complicato.

Sarà inoltre necessario per creare e scaricare (in formato JSON) una chiave Account servizio: https://console.developers.google.com/apis/credentials/serviceaccountkey

Ecco un esempio di come usarlo:

import csv 
import gspread 
from oauth2client.service_account import ServiceAccountCredentials 

scope = ['https://spreadsheets.google.com/feeds'] 
credentials = ServiceAccountCredentials.from_json_keyfile_name('credentials.json', scope) 

docid = "0zjVQXjJixf-SdGpLKnJtcmQhNjVUTk1hNTRpc0x5b9c" 

client = gspread.authorize(credentials) 
spreadsheet = client.open_by_key(docid) 
for i, worksheet in enumerate(spreadsheet.worksheets()): 
    filename = docid + '-worksheet' + str(i) + '.csv' 
    with open(filename, 'wb') as f: 
     writer = csv.writer(f) 
     writer.writerows(worksheet.get_all_values()) 
+0

Appena verificato. Sembra buono e lo contrassegnerò come predefinito. Eccezionale! –

+2

Ho appena usato anche questo, grandi cose! ps - puoi cambiare il metodo per usare il nome del doc invece della chiave che è carina. –

+1

E questo carica solo tutti i fogli di lavoro. È possibile caricare il foglio di lavoro con gid, non con indice o nome? – d12frosted

0

Gspread è davvero un grande miglioramento rispetto GoogleCL e Gdata (entrambi i quali ho usato e per fortuna si sono ritirati a favore di Gspread). Credo che questo codice è ancora più veloce rispetto alla precedente risposta per ottenere il contenuto del foglio:

username = '[email protected]' 
password = 'sdfsdfsadfsdw' 
sheetname = "Sheety Sheet" 

client = gspread.login(username, password) 
spreadsheet = client.open(sheetname) 

worksheet = spreadsheet.sheet1 
contents = [] 
for rows in worksheet.get_all_values(): 
    contents.append(rows) 
1

Ho semplificato @ risposta di Cameron ancora di più, rimuovendo l'orientamento agli oggetti inutili. Questo rende il codice più piccolo e più facile da capire. Ho anche modificato l'url, che potrebbe funzionare meglio.

#!/usr/bin/python 
import re, urllib, urllib2 

def get_auth_token(email, password): 
    url = "https://www.google.com/accounts/ClientLogin" 
    params = { 
     "Email": email, "Passwd": password, 
     "service": 'wise', 
     "accountType": "HOSTED_OR_GOOGLE", 
     "source": 'Client' 
    } 
    req = urllib2.Request(url, urllib.urlencode(params)) 
    return re.findall(r"Auth=(.*)", urllib2.urlopen(req).read())[0] 

def download(spreadsheet, worksheet, email, password, format="csv"): 
    url_format = 'https://docs.google.com/spreadsheets/d/%s/export?exportFormat=%s#gid=%s' 

    headers = { 
     "Authorization": "GoogleLogin auth=" + get_auth_token(email, password), 
     "GData-Version": "3.0" 
    } 
    req = urllib2.Request(url_format % (spreadsheet, format, worksheet), headers=headers) 
    return urllib2.urlopen(req) 


if __name__ == "__main__": 
    import getpass 
    import csv 

    spreadsheet_id = ""    # (spreadsheet id here) 
    worksheet_id = ''    # (gid here) 
    email = ""      # (your email here) 
    password = getpass.getpass() 

    # Request a file-like object containing the spreadsheet's contents 
    csv_file = download(spreadsheet_id, worksheet_id, email, password) 

    # Parse as CSV and print the rows 
    for row in csv.reader(csv_file): 
     print ", ".join(row) 
+0

Questa soluzione è obsoleta e non funzionerà, come tutte le risposte qui è necessario utilizzare oauth2.0 – Richard

3

(luglio 2016) riformulare con la terminologia corrente: "Come faccio a scaricare un foglio di Google in formato CSV da Google Unità utilizzando Python?". (Google Docs ora si riferisce solo al programma di elaborazione testi/editor di testo basato su cloud che non fornisce accesso ai fogli di lavoro di Fogli Google.)

Prima di tutto, tutte le altre risposte sono obsolete o lo saranno, sia perché utilizzano il vecchio GData (" Google Data") Protocol, ClientLogin o AuthSub, ognuno dei quali sono state ritirate. lo stesso vale per tutto il codice o le librerie che utilizzano il v3 di Google Fogli API o più anziani.

moderna accesso alle API di Google si verifica utilizzando chiavi API o Autorizzazione OAuth2, principalmente con Google APIs Client Libraries, incluso the one for Python. (E no, non è necessario creare un intero sistema di autenticazione solo per accedere alle API ... vedere il blogpost sotto)

Per eseguire l'attività richiesta in/dall'OP, è possibile utilizzare lo Google Drive API, eventualmente per richiedere il download di Fogli specifici, quindi eseguire le esportazioni effettive. Poiché è probabile un'operazione comune, ho scritto un blogpost condividendo un frammento di codice che fa questo per te. Se desideri proseguire ancora, ho un altro paio di posts insieme a un video che illustra come caricare file e scaricare file da Google Drive.

Nota che c'è anche un più nuovo Google Sheets API v4, ma è soprattutto per le operazioni di foglio di calcolo orientata, cioè, l'inserimento dei dati, la lettura di file di fogli di calcolo, la formattazione delle celle, la creazione di grafici, l'aggiunta di tabelle pivot, ecc, non basati su file domande come esportazione in cui l'API di Drive è quella corretta da utilizzare.

Per vedere un esempio di esportazione di un foglio di Google come CSV da Drive, vedere this blog post che ho scritto; per ulteriori informazioni sull'utilizzo di Fogli Google con Python, vedere this answer I wrote per una domanda simile.

0

(16 dicembre) Provate un'altra libreria che ho scritto: pygsheets. È simile a gspread, ma usa google api v4. Ha un metodo export per esportare il foglio di calcolo.

import pygsheets 

gc = pygsheets.authorize() 

# Open spreadsheet and then workseet 
sh = gc.open('my new ssheet') 
wks = sh.sheet1 

#export as csv 
wks.export(pygsheets.ExportType.CSV)