Как сохранить файл Google Sheets в формате CSV из Python 3 (или 2)?


Я ищу простой способ сохранить csv-файл, полученный из опубликованного документа Google Sheets? Поскольку он опубликован, он доступен по прямой ссылке (специально измененной в приведенном ниже примере).

Все мои браузеры будут предлагать мне сохранить файл csv, как только я запущу ссылку.

Ни то, ни другое:

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)

, ни:

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

Печатайте что угодно, кроме html-контента.

(попробовал 2-ю версию после прочтения этого другого поста: Скачать google docs публичная электронная таблица в csv с python .)

Есть идеи, что я делаю не так? Я вышел из своего аккаунта Google, если это что-то значит, но это работает с любого браузера, который я пробовал. Насколько я понял, API Google Docs еще не портирован на Python 3, и, учитывая "игрушечный" масштаб моего маленького проекта для личного использования, было бы даже не слишком разумно использовать его с самого начала, если бы я мог обойти его.

Во 2-й попытке я оставил "User-Agent", так как я я думал, что, возможно, запросы, считающиеся исходящими из скриптов (b/c отсутствует идентификационная информация), могут быть проигнорированы, но это не имело значения.

2 5

2 ответа:

Google отвечает на первоначальный запрос серией переадресаций 302 файлов cookie. Если вы не сохраняете и не пересылаете файлы cookie между запросами, он перенаправляет вас на страницу входа в систему.

Таким образом, проблема не в заголовке User-Agent, а в том, что по умолчанию urllib.request.urlopen не хранит файлы cookie, но будет следовать перенаправлениям HTTP 302.

Следующий код прекрасно работает на общедоступной электронной таблице, доступной в месте, указанном 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')

Показав вам, как это сделать в vanilla python, я теперь скажу, что правильный способ™ сделать это-использовать самый-превосходный библиотека запросов. Это так очень хорошо документировано и делает эти виды задач невероятно приятными для выполнения.

Например, получить то же самое csv_content, что и выше, используя библиотеку requests, так же просто, как:

>>> import requests
>>> csv_content = requests.get(DOC_URL).text
Эта единственная строка более ясно выражает ваше намерение. Это легче писать и легче читать. Сделайте себе - и всем, кто разделяет вашу кодовую базу-одолжение и просто используйте requests.

Хотя библиотека requests является золотым стандартом для HTTP-запросов от Python, Этот стиль загрузки (хотя он еще не устарел), скорее всего, не будет длиться, особенно в отношении использования ссылок, управления файлами cookie и перенаправлениями и т. д. Одна из причин, по которой Не предпочитают ссылки, заключается в том, что это менее безопасно и обычно такой доступ должен требовать авторизации. Вместо этого, в настоящее время общепринятым способом экспорта Google Sheets в формате CSV является Использование диска Google API .

Так почему же Drive API? Разве это не должно быть что-то для API листов вместо этого? Ну, API листов предназначен дляэлектронной таблицы -ориентированной функциональности, то есть форматирования данных, изменения размера столбцов, создания диаграмм, проверки ячеек и т. д., в то время как API диска предназначен для file-ориентированной функциональности, т. е. импорта/экспорта, копирования, переименования и т. д.

Ниже приводитсяполное решение командной строки . (Если вы не используете Python, вы можете использовать его как псевдокод и выбрать любой язык, поддерживаемый API-интерфейсов клиентских библиотек.) Для фрагмента кода предположим, что самый текущий лист с именем inventory (более старые файлы с этим именем игнорируются) и DRIVE является конечной точкой службы 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')

Если ваш лист Большой, вам, возможно, придется экспортировать его кусками-смотрите эту страницу о том, как сделать это. Если вы вообще новичок в Google API, у меня есть (несколько устаревшее, но) удобное для пользователя вступительное видео для вас. (Там есть 2 видео после этого, которые, возможно, тоже полезны.)