Slow is better than NOTHING

리눅스/Ubuntu16.04

Python을 활용한 구글드라이브 파일 원격 다운로드

Jeff_Kang 2023. 1. 3. 20:25
반응형

 

본 포스트에서는 구글 드라이브 (Google Drive) 에 있는 파일을 Python 코드를 통해 다운로드하는 방법을 소개합니다. 예제 코드도 함께 제공됩니다. 

gdown 을 활용한 구글 드라이브 파일 원격 다운로드

파일을 원격에서 접근하기 위한 다음과 같은 사전 작업이 필요합니다.

  1. gdown 설치

    자세한 내용은 링크를 참조바랍니다.
pip install gdown

# to upgrade
pip install --upgrade gdown
  1. 파일 권한 변경
    파일 우클릭 --> Get Link --> Restricted 에서 Anyone with the link 로 파일 권한 변경

다음과 같은 권한 설정이 된 파일만이 gdown 을 통해 접근이 가능합니다.


사전 작업이 모두 완료되었다면, 파일 우클릭을 통해 파일의 공유 link를 가져옵니다. 예를 들어, 아래와 같은 공유 링크가 있다고 가정하겠습니다.

# example of the share link
https://drive.google.com/file/d/1PAuhzIGWh_FRHLM8jj-utTZRVY5q5v/view?usp=share_link

google drive는 https://drive.google.com/file/d 라는 prefix 와 파일을 식별할 수 있는 1PAuhzIGWh_FRHLM8jj-utTZRVY5q5v 라는 unique id 가 할당되고 링크의 종류에 따라 /view?usp=share_link 또는 edit?usp=share_link 등과 같은 suffix가 붙기도합니다.

gdown 을 통해 파일을 식별하기 위해서는 해당 파일을 식별할 수 있는 unique id 를 적절히 넘겨주어야 합니다. gdown 은 download라는 함수를 이용해 url과 output filename을 인자로 받아 특정 url에 접근하여 지정된 path에 output을 저장합니다. 구글 드라이브에서 직접 copy해온 링크를 그대로 붙여넣을 경우 download는 동작하지만 정상적인 파일이 다운로드되지 않을 것입니다.

# gdown.download(downloadable_url, output_filename)
link = "https://drive.google.com/file/d/1PAuhzIGWh_FRHLM8jj-utTZRVY5q5v/view?usp=share_link"
output_filename = "example"
gdown.download(link, output_filename) # doesn't work

이는 gdown이 인식할 수 있는 downlodable url 은 아래와 같은 포맷을 따라야합니다. https://drive.google.com/uc?id= 라는 suffix뒤에 1PAuhzIGWh_FRHLM8jj-utTZRVY5q5v 라는 unique_file_id 가 붙습니다.

def make_download_url(file_id):
    """Make downlodable URL from gdrive"""
    return "https://drive.google.com/uc?id=" + file_id

즉, 요약하자면 

  1. 구글 드라이브에서 파일의 권한을 Anyone with the link로 변경 후 공유 링크를 가져온다

  2. unique id 를 추출한다.

  3. URL 포맷 변환 후 gdown.download를 활용해 원격 파일 다운로드를 한다.

위 3가지 프로세스를 파이썬 스크립트로 만든것은 아래와 같습니다.

import re
import gdown
from urllib.parse import urlparse

def get_gdrive_file_id(url):
    """Extracting file id from shared link of google drive"""
    parts = urlparse(url)

    if re.match(r"(drive|docs)[.]google[.]com", parts.netloc) is None:
        return None

    match = re.match(r"/file/d/(?P<id>[^/]*)", parts.path)
    if match is None:
        return None

    return match.group("id")

def make_download_url(file_id):
    """Make downlodable URL from gdrive"""
    return "https://drive.google.com/uc?id=" + file_id

gdrive_file_link = 'https://drive.google.com/file/d/1PAuhzIGWh_FRHLM8jj-utTZRVY5q5v/view?usp=share_link'
unique_file_id = get_gdrive_file_id(gdrive_file_link) # Extracting unique file id from the link
downlodable_url = make_download_url(unique_file_id)

gdown.download(downlodable_url, "output") # Downloading the file through python

가끔 대용량 파일을 다운로드하거나 불안정한 네트워크로 인해 정상적으로 파일이 다운로드가 완료된 것인지 확인하기 힘든 경우가 있습니다. 이럴 경우 원본 파일의 md5sum hash값을 이용해 다운로드가 적절하게 된 것인지 확인하는 아래와 같은 로직을 추가할 수 있습니다. 적절하게 다운로드가 되었는지 체크 하기 위해 원본 파일의 md5sum 값이 필요합니다. 

import hashlib
import sys

def compute_md5(file, chunk_size=1024 * 1024):
    """Computing md5sum value"""
    mdf5sum = hashlib.md5(**dict(usedforsecurity=False) if sys.version_info >= (3, 9) else dict())
    with open(file, "rb") as f:
        for chunk in iter(lambda: f.read(chunk_size), b""):
            mdf5sum.update(chunk)

    return mdf5sum.hexdigest()

def check_md5sum(file, md5sum):
    """Check whether downloaded file has correct md5sum value"""
    return md5sum == compute_md5(file)

output_file = "output"
md5sum_value = compute_md5(output_file)
ground_truth_md5sum = '32cd9b4e6355fb05a1a6b66352119e47'
check_md5sum(md5sum_value, ground_truth_md5sum) # True or False

 


MD5SUM 체크 로직까지 추가한 전체 스크립트는 아래를 참조하시기 바랍니다. 

import re
import sys
import gdown
import hashlib

from urllib.parse import urlparse

def get_gdrive_file_id(url):
    """Extracting file id from shared link of google drive"""
    parts = urlparse(url)

    if re.match(r"(drive|docs)[.]google[.]com", parts.netloc) is None:
        return None

    match = re.match(r"/file/d/(?P<id>[^/]*)", parts.path)
    if match is None:
        return None

    return match.group("id")

def make_download_url(file_id):
    """Make downlodable URL from gdrive"""
    return "https://drive.google.com/uc?id=" + file_id


def compute_md5(file, chunk_size=1024 * 1024):
    """Computing md5sum value"""
    mdf5sum = hashlib.md5(**dict(usedforsecurity=False) if sys.version_info >= (3, 9) else dict())
    with open(file, "rb") as f:
        for chunk in iter(lambda: f.read(chunk_size), b""):
            mdf5sum.update(chunk)

    return mdf5sum.hexdigest()

def check_md5sum(file, md5sum):
    """Check whether downloaded file has correct md5sum value"""
    return md5sum == compute_md5(file)

if __name__ == "__main__":
    # Processing inputs of gdown.download
    gdrive_file_link = 'https://drive.google.com/file/d/1PAuhzIGWh_FRHLM8jj-utTZRVY5q5v/view?usp=share_link'
    unique_file_id = get_gdrive_file_id(gdrive_file_link) # Extracting unique file id from the link
    downlodable_url = make_download_url(unique_file_id)
    output_file = "output"

    # download the file
    gdown.download(downlodable_url, output_file) # Downloading the file through python

    # check whether the file has downloaded well
    md5sum_value = compute_md5(output_file)
    ground_truth_md5sum = '32cd9b4e6355fb05a1a6b66352119e47'

    if check_md5sum(md5sum_value, ground_truth_md5sum) # True or False
      print("Download has been completed")
    else:
      print("Download has been failed")

 

이상으로 Python 을 활용한 구글 드라이브 파일 원격 다운로드 하는 방법을 소개했습니다.  

도움이 되셨다면, 공감 버튼 부탁드립니다 :)

반응형