Android를 개발하다 보면 목적에 따라서 APK를 다운로드해야 하는 경우가 있습니다. Google Play Store에서는 APK 자체를 다운로드할 수 있는 방법은 없고, APK Mirror 사이트를 통해서 다운로드할 수 있습니다. 일반 사용자인 경우에는 Android로 기반의 내비게이션에 APK를 다운로드하고 SD 카드로 복사하여 설치 가능합니다.
본 포스팅에서는 다운로드하고자 하는 APK 의 package name의 list를 기반으로 Python의 selenium과 chrome webdriver를 사용해서 '자동'으로 apk를 다운로드합니다. 이 방법은 APK 뿐 만 아니라 다른 Web site에서 특정 파일을 다운로드하는데 활용될 수 있습니다. 참고로, 다운로드한 apk를 상업적인 목적이나 추가 배포하는 것은 저작권에 문제의 소지가 있을 수 있으니 주의해주세요.
1. Python Selenium 소개
Selenium은 웹 브라우져를 컨트롤하여 웹 UI 를 Automation 하는 도구 중의 하나입니다. 쉽게 설명하면 Broswer 기반의 Macro 프로그램을 개발할 수 있는 python package입니다. Selenium Client는 WebDriver라는 공통 인터페이스(Common interface)와 각 브라우저 타입별(Chrome, FireFox 등)로 하나씩 있는 Browser Driver로 구성되어 있습니다. Selenium 개념은 아래 동영상을 참고하세요.
2. Python Selenium 설치
$ sudo pip3 install selenium
3. Web Driver 설치
Web driver를 설치는 아래 다운로드 사이트에 가능합니다. 본 포스팅은 chrome 84 버전을 기준으로 설명 및 테스트하였습니다.
- Firefox : https://github.com/mozilla/geckodriver/releases
- Chrome : https://sites.google.com/a/chromium.org/chromedriver/downloads
- Edge : https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
3.1 Chrome 버전 확인
Web driver를 다운로드 시 브라우저와 버전에 맞는 실행 파일을 다운로드하기 위해서 버전을 확인이 필요합니다. Chrome 버전은 아래 명령어 확인하거나, Chrome 설정 메뉴에서 확인이 가능합니다.
$ google-chrome --version
→ Google Chrome 84.0.4147.105
Chrome 브라우저에서 chrome://settings/help 에서 버전 확인
3.2. Chorme 자동 업데이트 중지 (출처)
Chrome 자동으로 업데이트를 진행합니다. 서버에서 크롤링하는 경우에 Chrome 버전이 올라가면 Web drive도 같이 업데이트해야 합니다. Chrome 버전을 그대로 유지하는 방법은 아래와 같습니다.
- Chrome 브라우저를 설치하기 전에 빈 저장소를 만듭니다.
$ sudo touch /etc/default/google-chrome - /etc/default/google-chrome에 다음 행을 추가합니다.
repo_add_once=false
3.3. Chrome driver를 설치
앞에서 Chrome 버전에 맞는 web driver을 다운로드합니다. 84 버전과 85 버전은 아래 사이트에 다운도르 가능합니다.
- 84 버전: https://chromedriver.storage.googleapis.com/index.html?path=84.0.4147.30/
- 85 버전: https://chromedriver.storage.googleapis.com/index.html?path=85.0.4183.38/
Chrome 84 버전인 경우에는 chromedriver_linux64.zip을 압축 풀면 chromedriver 실행 파일이 있고, PATH가 지정된 폴더($ echo $PATH 확인 가능)로 copy 합니다.
$ sudo mv chromedriver /usr/bin/ (or ~/.local/bin)
4. Selenium에서 Chrome drive를 사용해서 크롤링
Web driver를 다운로드하고 파이썬에서 Selenium와 옵션을 설정하는 단계입니다.
4.1. Apk mirror 사이트 접속
Android에서 APK mirror 사이트 중에서 apkpure 사이트를 사용합니다. APK pure site인 경우에는 APK의 package name조합으로 URL이 구성되어 있습니다. Android App의 package name은 Google 사이트에 앱을 검색하면 쉽게 확인 가능합니다.
URL: https://m.apkpure.com/kr/google-play-store/[apk's pacakge name] /download?from=details'
# webdriver 얻어오고 URL에 접속함
browser = webdriver.Chrome()
apk_mirror_url = 'https://m.apkpure.com/kr/google-play-store/{}/download?from=details'.format(apk)
# APK mirror 사이트에 접속
browser.get(apk_mirror_url)
# apk download 시간
time.sleep(30)
4.2. 안전하지 않은 콘텐츠 다운로드 팝업 제거와 다운로드 폴더 지정
4.1까지의 python code만으로도 Chrome이 실행되고, URL에 접속하지만 APK 다운로드되면 "안전하지 않은 콘텐츠입니다. 정말 다운로드하실 것인가? "라는 팝업을 표시하고 사용자의 입력을 기다립니다. 이 문제를 해결하기 위해서는 Chrome 브라우저의 옵션을 설정해야 합니다. Web drive에서 Chrome 실행 다운로드 팝업 옵션을 제거하는 옵션을 설정합니다.
APK를 다운로드 폴더를 옵션을 통해서 설정할 수 있습니다. 디폴트 값은 ~/Downloads에 저장되나 크롤링에서 저장한 apk와 실제 사용자 계정에서 다운로드한 내용과 구분하기 위해서 크롤링의 다운로드 폴더를 지정합니다. Apk Pure Web 사이트는 로그인이 필요 없지만, 로그인이 필요한 Web site 인 경우에는 profile 옵션을 저장할 수 있도록 profile 폴더를 지정합니다.
option = Options()
#profile 폴더 설정
option.add_argument("user-data-dir="+profile_dir)
# 안전하지 않은 콘텐츠 다운로드 팝업 표시하지 않음
# 다운로드 폴더 지정
option.add_experimental_option("prefs", {
"download.default_directory": download_dir,
"download.prompt_for_download": False,
"download.directory_upgrade": True,
"safebrowsing.enabled": True
})
4.3. 백그라운드 다운로드
크롤링 동작을 확인하기 위해서는 눈으로 Chrome에서 동작을 확인하는 것이 확실하나, 서버에서 운영하는 경우 백그라운드에서 UI 없이 크롤링이 가능해야 합니다. 백그라운드로 동작시키기 위해서는 headless 옵션을 사용합니다.
option = Options()
# Chrome UI 없이 다운로드
option.add_argument('headless')
# webdriver 옵션 지정
browser = webdriver.Chrome(options=option)
5. Python Source Code 및 실행 결과
실제 구동하는 Python script은 아래 Git Hub 사이트에 올라가 있습니다. Chorme 84 버전과 Python 3.8 버전으로 확인했습니다.
- Source code 다운로드: https://github.com/kibua20/devDocs/tree/master/apk_downloader
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import os
import time
def main():
apklist = [
'com.android.vending',
'com.google.android.apps.docs.editors.docs',
'com.google.android.apps.youtube.music',
'com.google.android.videos'
]
apk_download (apklist)
def apk_download(apklist):
# download 와 profile path 지정
download_dir = os.path.join(os.getcwd(), 'download')
profile_dir = os.path.join(os.getcwd(), 'profile')
option = Options()
option.add_argument("disable-infobars")
option.add_argument("disable-extensions")
#option.add_argument("start-maximized")
option.add_argument('disable-gpu')
#option.add_argument('headless')
option.add_argument("user-data-dir="+profile_dir)
option.add_experimental_option("prefs", {
"download.default_directory": download_dir,
"download.prompt_for_download": False,
"download.directory_upgrade": True,
"safebrowsing.enabled": True
})
# webdriver 얻어옴
browser = webdriver.Chrome(options=option)
# apk list 에서 apk download 시도함
for apk in apklist:
apk_mirror_url = 'https://m.apkpure.com/kr/google-play-store/{}/download?from=details'.format(apk)
print ('Download apk', apk)
browser.get(apk_mirror_url)
time.sleep(10)
# chrome에서 다운로드 완료 할때 까지 충분한 시간을 기다림
time.sleep(30)
# chrome 종료
browser.quit()
print ('Finish')
if __name__ == "__main__":
main()
실행 결과는 아래와 같습니다. ./profile 폴더에 Chrome 옵션 파일을 생성되고, ./download 폴더에서 package name으로 지정한 apk 파일이 다운로드됩니다.
관련 글
[모바일 SW 개발/Python] - Python: OSError: [Errno 98] Address already in use (Flask)
[모바일 SW 개발/Python] - Python code 숨기는 방법: PyInstaller로 실행 파일 만들기
[모바일 SW 개발/Python] - Python 여러 버전 설치 방법 (3.x and 3.y 동시 설치)
[모바일 SW 개발/Python] - Python 폴더 및 파일 처리 함수 모음
[개발환경] - 네이버 동영상 다운로드 방법 (동영상과 설명 포함)
[모바일 SW 개발/Android] - Android 소스 최적화 (100GB에서 65GB로 줄이기)
[모바일 SW 개발/Android] - Android 11 기능 소개
[모바일 SW 개발/Android] - Android 11 (R-OS) Emulator에 설치하기
[모바일 SW 개발/Android] - Android Studio 4.0 사용하기
댓글