본문 바로가기

python & django & scipy

[django - google drive api] google drive api로 shared drive(공유 드라이브) 접근하기

 

 

 

[pandas & django] gspread 사용하기

 

[pandas & django] gspread 사용하기

2022.12.23 - [python & django & pandas] - [pandas] google sheet 에서 데이터 가져오기 [pandas] google sheet 에서 데이터 가져오기 회사에서 google sheet 데이터를 받아온 후 그 데이터로 처리해야하는 일이 있었다. 인

darever.tistory.com

 

문제상황

저번까지는 구글 시트에 있는 데이터를 dataframe으로 뽑아서 다시 구글 시트로 돌려보내는 것 뿐이었지만 이번에는

 

 

일회성 작업

  1. google sheet에서 fdcs라는 field가 true인 상품에 대해
  2. 구글 공유 드라이브에 "{sku}_{상품이름}"으로 폴더 생성
  3. 기존 상품들의 이미지를 전부 다운로드 받고, 이미지 이름을 "100_0_{sku}_{상품이름}"으로 변경
  4. 각 이미지들을 webp로 변경하여,
  5. 이미지를 저장하고, 구글 폴더에도 옮긴다.

일회성 작업은 스크립팅으로 한번에 작업하기로 했다. 

  1. gspread로 fdcs 필드값이 true인 상품 목록 불러오기
  2. 로컬에 "{sku}_{상품이름}"으로 폴더 생성
  3. s3-bucket에 업로드된 이미지를 로컬에 다운로드 받아 "100_0_{sku}_{상품이름}"으로 변경하고 "{sku}_{상품이름}" 폴더에 저장
  4. 해당 이미지를 모두 webp로 변경
  5. 로컬에 있는 포더 구글 드라이브에 업로드

 

루틴 시스템 작업
  1. 구글 폴더에 올린 이미지들의 index를 받는 코드 작성 -> db에 있는지 없는지 파악
  2. 현재 db에 없는 이미지를 뽑는 작업
  3. 없으면 다운로드 후 DB에 저장

일단 일회성 작업을 위해 google drive api를 사용했다.  

루틴 시스템 액션을 정리해보았다. 

  • 어드민 사용자가 구글 공유 드라이브에 png 파일을 업로드 한다.
  • 서버는 db에 없는 파일을 탐색한다.
  • 구글 공유 드라이브에서 db에 없는 png 파일을 다운받아
  • webp로 변환하고
  • db에 저장한다.

필요없는 액션 정리

  • 변환한 webp 파일이 꼭 구글 드라이브에도 있어야 하나? -> X
    • 그럼 webp로 변환해서 구글 드라이브에 저장하는 작업(오래걸릴 것이라고 추정했음)이 사라짐

 

 

해결1. google drive api 사용하기

구글 공유 드라이브에 있는 파일의 리스트를 불러오고, 이미지를 저장하기 위해서 google drive api를 사용한다. 

 

gspread를 사용할 때 발행했던 google drive api credential을 이용해서 인증을 진행한다.

 

from google.oauth2 import service_account

credentials = service_account.Credentials.from_service_account_file('cred.json')

 

그 다음은 python용 google client api 라이브러리로 구글 드라이브에 접근할 수 있도록 한다.

from googleapiclient.discovery import build
service = build('drive', 'v3', credentials=credentials)

 

 

파일과 드라이브를 찾는 건 아래 문서를 참고하면 된다.

https://developers.google.com/drive/api/v3/reference/files/list

 

Files: list  |  Google Drive  |  Google Developers

Send feedback Files: list Stay organized with collections Save and categorize content based on your preferences. Note: Authorization optional. Lists or searches files. Try it now. This method accepts the q parameter, which is a search query combining one o

developers.google.com

 

특정 공유 드라이브를 지정하기 위해서는 driveId가 필요하다.

드라이브 리스트는 아래처럼 받아오면 된다. 

# q: 공유 드라이브를 검색하기 위한 쿼리 문자열
service.drives().list(q="name='mydrive'").execute()

response

{
    'kind': 'drive#driveList',
    'drives': [
    	{
        	'id': '****driveID****',
    		'name': 'mydrive',
    		'kind': 'drive#drive'
        }
    ]
}

찾는 드라이브의 id를 얻을 수 있다.

 

 

driveId를 얻었으니 이제 원하는 공유 드라이브에서 파일을 찾을 수 있다.

res = service.files().list(
    corpora='drive',
    driveId='****driveID****',
    includeItemsFromAllDrives=True,
    supportsAllDrives=True
).execute()

response

{
    'nextPageToken': '******',
    'kind': 'drive#fileList',
    'incompleteSearch': False,
    'files': [
    	{
            'kind': 'drive#file',
            'driveId': '****driveId****',
            'mimeType': 'application/vnd.google-apps.folder',
            'id': '****file1Id****',
            'name': 'file1.txt',
            'teamDriveId': '****driveId****'
        },
        {
            'kind': 'drive#file',
            'driveId': '****driveId****',
            'mimeType': 'application/vnd.google-apps.folder',
            'id': '****file2Id****',
            'name': 'file2.txt',
            'teamDriveId': '****driveId****'
        }
    ]
}

 

해결2. 로직 짜기

def update_product_images(self):

    self.google_drive_service = self.get_google_drive_service() # google drive api authenticate
	
    # 공유 드라이브 이미지 리스트 가져오기
    drive_images = self.get_drive_images()
    # DB에 있는 상품 가져오기
    product_image_objs = self.get_product_image_objs_by_sku(drive_images)
    # google drive에는 있지만 DB에 없는 이미지 가져오기
    images_not_in_db = self.images_not_in_db(drive_images, product_image_objs)
    # DB에 없는 이미지 구글 드라이브로부터 다운로드
    images_not_in_db_from_drive = self.download_images_from_drive(images_not_in_db)
    # 다운받은 이미지 webp 형식으로 저장해서 DB에 저장
    created_product_image_objs = self.update_product_images_on_webp(images_not_in_db_from_drive)

    return created_product_image_objs

 

결론

구글 공유 드라이브에 이미지를 업로드 하고 어드민 페이지에 들어와서 또 확인 작업을 해야한다는 게 내 생각엔 아직 복잡한 것 같아서 시간날 때 어드민 페이지에서 이미지 bulk로 업로드하고 관리할 수 있을지 생각해봐야겠다