Python: загрузка файлов с Google Drive с помощью URL
Я пытаюсь загрузить файлы с Google Drive, и все, что у меня есть, это URL-адрес диска.
Я читал о API Google, который говорит о некоторых drive_service и MedioIO, который также требует некоторых учетных данных (в основном, json file / oauth). Но я не могу понять, как это работает.
Кроме того, попытался urllib2 urlretrieve, но мой случай, чтобы получить файлы с диска. Пробовал "wget" тоже, но бесполезно.
Попробовал pydrive библиотеку. Он имеет хорошие функции загрузки на диск, но нет вариантов загрузки.
Любая помощь будет оценена. Благодарю.
15 ответов
Если под "URL-адресом диска" вы подразумеваете общую ссылку на файл на Google Диске, то может помочь следующее:
import requests
def download_file_from_google_drive(id, destination):
URL = "https://docs.google.com/uc?export=download"
session = requests.Session()
response = session.get(URL, params = { 'id' : id }, stream = True)
token = get_confirm_token(response)
if token:
params = { 'id' : id, 'confirm' : token }
response = session.get(URL, params = params, stream = True)
save_response_content(response, destination)
def get_confirm_token(response):
for key, value in response.cookies.items():
if key.startswith('download_warning'):
return value
return None
def save_response_content(response, destination):
CHUNK_SIZE = 32768
with open(destination, "wb") as f:
for chunk in response.iter_content(CHUNK_SIZE):
if chunk: # filter out keep-alive new chunks
f.write(chunk)
if __name__ == "__main__":
file_id = 'TAKE ID FROM SHAREABLE LINK'
destination = 'DESTINATION FILE ON YOUR DISK'
download_file_from_google_drive(file_id, destination)
Однако в snipped не используется ни pydrive, ни Google Drive SDK. Он использует модуль запросов (который, так или иначе, является альтернативой urllib2).
При загрузке больших файлов с Google Диска одного запроса GET недостаточно. Нужен второй - см. Большой файл wget/curl с Google Drive.
Я рекомендую пакет gdown:
import gdown
url = 'https://drive.google.com/uc?id=0B9P1L--7Wd2vU3VUVlFnbTgtS2c'
output = 'spam.txt'
gdown.download(url, output, quiet=False)
Много раз сталкиваясь с подобными потребностями, я сделал очень простой урок GoogleDriveDownloader
начиная с фрагмента @user115202 выше. Вы можете найти исходный код здесь.
Вы также можете установить его через pip:
pip install googledrivedownloader
Тогда использование так же просто, как:
from google_drive_downloader import GoogleDriveDownloader as gdd
gdd.download_file_from_google_drive(file_id='1iytA1n2z4go3uVCwE__vIKouTKyIDjEq',
dest_path='./data/mnist.zip',
unzip=True)
Этот фрагмент загрузит архив, размещенный на Google Диске. В этом случае 1iytA1n2z4go3uVCwE__vIKouTKyIDjEq
является идентификатором ссылки общего доступа, полученной с Google Диска.
Вот простой способ сделать это без сторонних библиотек и учетной записи службы.
pip install google-api-core
а также google-api-python-client
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseDownload
from google.oauth2 import service_account
import io
credz = {} #put json credentials her from service account or the like
# More info: https://cloud.google.com/docs/authentication
credentials = service_account.Credentials.from_service_account_info(credz)
drive_service = build('drive', 'v3', credentials=credentials)
file_id = '0BwwA4oUTeiV1UVNwOHItT0xfa2M'
request = drive_service.files().get_media(fileId=file_id)
#fh = io.BytesIO() # this can be used to keep in memory
fh = io.FileIO('file.tar.gz', 'wb') # this can be used to write to disk
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
print("Download %d%%." % int(status.progress() * 100))
PyDrive
позволяет скачать файл с функцией GetContentFile()
, Вы можете найти документацию по функции здесь.
Смотрите пример ниже:
# Initialize GoogleDriveFile instance with file id.
file_obj = drive.CreateFile({'id': '<your file ID here>'})
file_obj.GetContentFile('cats.png') # Download file as 'cats.png'.
Этот код предполагает, что у вас есть аутентифицированный drive
объект, документы по этому можно найти здесь и здесь.
В общем случае это делается так:
from pydrive.auth import GoogleAuth
gauth = GoogleAuth()
# Create local webserver which automatically handles authentication.
gauth.LocalWebserverAuth()
# Create GoogleDrive instance with authenticated GoogleAuth instance.
drive = GoogleDrive(gauth)
Информация о тихой аутентификации на сервере может быть найдена здесь и включает в себя написание settings.yaml
(пример: здесь), в котором вы сохраняете детали аутентификации.
Вообще говоря, URL-адрес общего файла с Google Диска выглядит так
https://drive.google.com/file/d/1HV6vf8pB-EYnjcJcH65eGZVMa2v2tcMh/view?usp=sharing
где 1HV6vf8pB-EYnjcJcH65eGZVMa2v2tcMh
соответствует fileID.
Следовательно, вы можете просто создать функцию для получения идентификатора файла из URL-адреса, например, где url = https://drive.google.com/file/d/1HV6vf8pB-EYnjcJcH65eGZVMa2v2tcMh/view?usp=sharing
,
def url_to_id(url):
x = url.split("/")
return x[5]
Печать x даст
['https:', '', 'drive.google.com', 'file', 'd', '1HV6vf8pB-EYnjcJcH65eGZVMa2v2tcMh', 'view?usp=sharing']
Итак, поскольку мы хотим вернуть шестое значение массива, мы используем x[5]
.
import requests
def download_file_from_google_drive(id, destination):
URL = "https://docs.google.com/uc?export=download"
session = requests.Session()
response = session.get(URL, params = { 'id' : id , 'confirm': 1 }, stream = True)
token = get_confirm_token(response)
if token:
params = { 'id' : id, 'confirm' : token }
response = session.get(URL, params = params, stream = True)
save_response_content(response, destination)
def get_confirm_token(response):
for key, value in response.cookies.items():
if key.startswith('download_warning'):
return value
return None
def save_response_content(response, destination):
CHUNK_SIZE = 32768
with open(destination, "wb") as f:
for chunk in response.iter_content(CHUNK_SIZE):
if chunk: # filter out keep-alive new chunks
f.write(chunk)
if __name__ == "__main__":
file_id = 'TAKE ID FROM SHAREABLE LINK'
destination = 'DESTINATION FILE ON YOUR DISK'
download_file_from_google_drive(file_id, destination)
Просто повторяю принятый ответ, но добавляюconfirm=1
параметр, поэтому он всегда загружается, даже если файл слишком большой
Это также было описано выше,
from pydrive.auth import GoogleAuth
gauth = GoogleAuth()
gauth.LocalWebserverAuth()
drive = GoogleDrive(gauth)
Это создает свой собственный сервер тоже делать грязную работу аутентификации
file_obj = drive.CreateFile({'id': '<Put the file ID here>'})
file_obj.GetContentFile('Demo.txt')
Это загружает файл
# Importing [PyDrive][1] OAuth
from pydrive.auth import GoogleAuth
def download_tracking_file_by_id(file_id, download_dir):
gauth = GoogleAuth(settings_file='../settings.yaml')
# Try to load saved client credentials
gauth.LoadCredentialsFile("../credentials.json")
if gauth.credentials is None:
# Authenticate if they're not there
gauth.LocalWebserverAuth()
elif gauth.access_token_expired:
# Refresh them if expired
gauth.Refresh()
else:
# Initialize the saved creds
gauth.Authorize()
# Save the current credentials to a file
gauth.SaveCredentialsFile("../credentials.json")
drive = GoogleDrive(gauth)
logger.debug("Trying to download file_id " + str(file_id))
file6 = drive.CreateFile({'id': file_id})
file6.GetContentFile(download_dir+'mapmob.zip')
zipfile.ZipFile(download_dir + 'test.zip').extractall(UNZIP_DIR)
tracking_data_location = download_dir + 'test.json'
return tracking_data_location
Вышеуказанная функция загружает файл с заданным идентификатором file_id в указанную папку загрузок. Теперь остается вопрос, как получить file_id? Просто разделите URL по id =, чтобы получить file_id.
file_id = url.split("id=")[1]
Я пытался использовать Google Colaboratory: https://colab.research.google.com/
Предположим, ваша ссылка для общего доступа https://docs.google.com/spreadsheets/d/12hiI0NK7M0KEfscMfyBaLT9gxcZMleeu/edit?usp=sharing&amp;ouid=102608702203033509854&amp;rtpof=true&amp;sd=true
все, что вам нужно, это идентификатор 12hiI0NK7M0KEfscMfyBaLT9gxcZMleeu.
команда в ячейке
!gdown 12hiI0NK7M0KEfscMfyBaLT9gxcZMleeu
запустите ячейку, и вы увидите, что файл загружен в /content/Amazon_Reviews.xlsx
Примечание: нужно знать, как использовать Google colab
Для тех, кого интересует ссылка для загрузки через HTTP, Google API и большинство клиентов предоставляютwebContentLink
поле, содержащее его (обратите внимание на права доступа к файлу для его использования)
Исправлена версия на 2023 год + генератор отслеживания прогресса
import requests
def download_file_from_google_drive(file_id, destination, chunk_size=32768):
url = "https://docs.google.com/uc?export=download"
session = requests.Session()
params = {'id': file_id, 'confirm': 1}
response = session.get(url, params=params, stream=True)
for i, chunk_size_ in save_response_content(response, destination, chunk_size):
yield i, chunk_size_
def get_confirm_token(response):
for key, value in response.cookies.items():
if key.startswith('download_warning'):
return value
return None
def save_response_content(response, destination, chunk_size):
with open(destination, "wb") as f:
for i, chunk in enumerate(response.iter_content(chunk_size)):
if chunk: # filter out keep-alive new chunks
f.write(chunk)
yield i, chunk_size
if __name__ == '__main__':
file_id = '...'
destination = '...'
for i, chunk_size in download_file_from_google_drive(file_id, destination):
print(i, chunk_size)
Я использовал принятое решение в течение длительного периода, но теперь Google изменил ответ с предупреждением о загрузке, поэтому оно больше не работает.
Сейчас я использую API, поскольку это более безопасный способ гарантировать, что он не остановится внезапно, но я также мог бы заставить его работать, анализируя HTML-код ответа в поисках URL-адреса загрузки, как показано ниже:
import requests
from html.parser import HTMLParser
class MyHTMLParser(HTMLParser):
def __init__(self):
super().__init__()
self.action = None
def handle_starttag(self, tag, attrs):
if tag == "form":
for name, value in attrs:
if name == "id" and value == "download-form":
for name, value in attrs:
if name == "action":
self.action = value
DOWNLOAD_URL = 'https://docs.google.com/uc?export=download'
session = requests.Session()
response = session.get(file_url, params={'id': id}, stream=True)
content_type = response.headers['content-type']
if content_type == 'text/html; charset=utf-8':
parser = MyHTMLParser()
parser.feed(response.text)
download_url = parser.action
response = session.post(download_url, stream=True)
file = response.content
Этот пример основан на аналоге RayB, но хранит файл в памяти и немного проще, и вы можете вставить его в colab, и он работает.
import googleapiclient.discovery
import oauth2client.client
from google.colab import auth
auth.authenticate_user()
def download_gdrive(id):
creds = oauth2client.client.GoogleCredentials.get_application_default()
service = googleapiclient.discovery.build('drive', 'v3', credentials=creds)
return service.files().get_media(fileId=id).execute()
a = download_gdrive("1F-yaQB8fdsfsdafm2l8WFjhEiYSHZrCcr")
Вы можете установить https://pypi.org/project/googleDriveFileDownloader/
pip install googleDriveFileDownloader
И загрузите файл, вот пример кода для загрузки
from googleDriveFileDownloader import googleDriveFileDownloader
a = googleDriveFileDownloader()
a.downloadFile("https://drive.google.com/uc?id=1O4x8rwGJAh8gRo8sjm0kuKFf6vCEm93G&export=download")