¿Cómo se guarda un archivo de Google Sheets como CSV de Python 3 (o 2)?

¿Busco una forma sencilla de guardar un archivo csv que se origina en un documento publicado de Google Sheets? Desde su publicación, es accesible a través de un enlace directo (modificado a propósito en el siguiente ejemplo).

Todos mis navegadores me pedirán que guarde el archivo csv tan pronto como inicie el enlace.

Ninguno:

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) 

, ni:

 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')) 

Imprime cualquier cosa excepto contenido html.

(Probé la segunda versión después de leer esta otra publicación: descargue la hoja de cálculo pública de Google Docs a csv con Python ).

¿Alguna idea de lo que estoy haciendo mal? Me desconecté de mi cuenta de Google, si eso vale para algo, pero esto funciona desde cualquier navegador que haya probado. Por lo que entendí, la API de Google Docs aún no se ha portado en Python 3 y, dada la magnitud de “juguete” de mi pequeño proyecto para uso personal, no tendría mucho sentido usarlo desde el principio, si Puedo sortearlo.

En el segundo bash, dejé el ‘User-Agent’, ya que estaba pensando que tal vez las peticiones de pensamiento provenientes de scripts (b / c no hay información de identificación presente) podrían ignorarse, pero no hizo una diferencia.

Google responde a la solicitud inicial con una serie de redireccionamientos 302 de configuración de cookies. Si no almacena y vuelve a enviar las cookies entre solicitudes, le redirige a la página de inicio de sesión.

Entonces, el problema no está en el encabezado User-Agent, es el hecho de que, de forma predeterminada, urllib.request.urlopen no almacena cookies, pero seguirá los redireccionamientos de HTTP 302.

El siguiente código funciona bien en una hoja de cálculo pública disponible en la ubicación especificada por 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') 

Después de mostrarle cómo hacerlo en Python de vainilla, ahora diré que la forma correcta de hacerlo es usar la biblioteca de solicitudes más excelente. Está extremadamente bien documentado y hace que este tipo de tareas sean increíblemente agradables de completar.

Por ejemplo, obtener el mismo csv_content que arriba usando la biblioteca de requests es tan simple como:

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

Esa única línea expresa tu intención más claramente. Es más fácil de escribir y más fácil de leer. Hágalo usted mismo (y a cualquier otra persona que comparta su código base) un favor y solo use las requests .

Si bien la biblioteca de requests es el estándar de oro para las solicitudes HTTP de Python, este estilo de descarga (aunque todavía no está obsoleto) no es probable que dure, refiriéndose específicamente al uso de enlaces, la administración de cookies y las redirecciones, etc. Una de las razones de no preferir los enlaces es que es menos seguro y, en general, tal acceso debe requerir autorización. En cambio, la forma actualmente aceptada de exportar Google Sheets como CSV es mediante el uso de la API de Google Drive .

Entonces, ¿por qué la API de Drive? ¿No se supone que esto es algo para la API Sheets ? Bueno, la API Sheets es para la funcionalidad orientada a la hoja de cálculo , es decir, formato de datos, cambio de tamaño de la columna, creación de gráficos, validación de celdas, etc., mientras que la API Drive es para la funcionalidad orientada al archivo , es decir, importar / exportar, copiar, renombrar, etc.

A continuación se muestra una solución completa de la línea cmd . (Si no usa Python, puede usarlo como pseudocódigo y elegir cualquier idioma compatible con las bibliotecas cliente de las API de Google ). Para el fragmento de código, suponga que la hoja más reciente se llama inventory (los archivos más antiguos con ese nombre se ignoran) y DRIVE es el punto final del servicio API:

 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') 

Si su Hoja es grande, puede que tenga que exportarla en trozos; consulte esta página para saber cómo hacerlo. Si generalmente eres nuevo en las API de Google, tengo un video de introducción (algo anticuado pero) fácil de usar para ti. (Hay 2 videos después de eso que pueden ser útiles también).