Как сохранить файл 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", так как думал, что, возможно, запросы, воспринимаемые как скрипты (поскольку идентификационная информация отсутствует) могут игнорироваться, но это не имеет значения.
2 ответа
Google отвечает на первоначальный запрос серией переадресаций 302 с настройками файлов cookie. Если вы не сохраняете и не отправляете файлы cookie между запросами, он перенаправляет вас на страницу входа.
Итак, проблема не в заголовке User-Agent, а в том, что по умолчанию urllib.request.urlopen
не хранит куки, но будет следовать перенаправлениям 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 Drive API.
Так почему же Drive API? Разве это не должно быть что-то для Sheets API вместо этого? Итак, API Sheets предназначен для функциональных возможностей, ориентированных на электронные таблицы, т. Е. Для форматирования данных, изменения размера столбцов, создания диаграмм, проверки ячеек и т. Д., В то время как Drive API предназначен для функциональных возможностей, ориентированных на файлы, т. Е. Для импорта / экспорта, копирования, переименования, и т.п.
Ниже приведено полное решение cmd-line. (Если вы не используете Python, вы можете использовать его в качестве псевдокода и выбрать любой язык, поддерживаемый клиентскими библиотеками API Google.) Для фрагмента кода предположим, что самый последний лист называется 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')
Если ваш лист большой, вам, возможно, придется экспортировать его порциями - см. Эту страницу, чтобы узнать, как это сделать. Если вы, как правило, плохо знакомы с API Google, у меня есть (несколько устаревшее, но) удобное вводное видео для вас. (После этого есть 2 видео, которые тоже могут быть полезны.)