Overview
안드로이드 앱 설치를 바로 할 수 있는 APK(Android Application Package)파일을 자동으로 수집해주는 크롤러 입니다. 일상 생활에서 APK파일을 사용할 일은 거의 존재하지 않지만 다량의 앱실험을 위해서 제작하게 되었습니다. 현재 구글 플레이스토어에서 APK파일을 직접 다운받을 수 없습니다. 또한 APK파일을 다운 받을 수 있는 Google Play Store Unofficial API 가 존재 하지만 구글에서 공식적으로 지원하지 않는데다가 최근 오류로 인하여 안정적으로 APK파일을 다운받을 수 없어졌습니다. 따라서 API를 사용하지 않고 APK파일을 다운받을 수 있는 APKpure 사이트를 활용한 크롤러를 작성하게 되었습니다. 이런 크롤러가 필요한 대상들은모바일 관련 실험 및 논문을 작성하는 대학원생일것이라 예상합니다.
Architecture
APK를 크롤링하기 위해서 APK를 다운받을 수 있는 APKpure.com 페이지를 활용할 예정입니다.
APKpure 에서는 앱 검색을 패키지명 혹은 앱 이름으로 검색할 수 있습니다.
여기에서는 패키지 이름으로 검색을 할 것이므로 패키지 명을 수집하는 Google Play Store Crawler 와 패키지명을 사용하여 APKpure.com에서 APK를 다운받는 APK Downloader로 분류하였습니다.
Google Play Store Crawler
Google Play Store Crawler에서는 패키지 명을 크롤링 해야합니다.
그 전에 어떤 앱에 대한 패키지 명을 크롤링 할 것인지 대상을 정해야 합니다.
제가 원하는 것은 되도록 많은 앱을, 사용자들이 많이 사용하는 앱을 대상으로 진행하고 싶었기 때문에 인기차트에 존재하는 앱을 타겟으로 설정하였습니다.
하나의 카테고리 인기차트는 해당 카테고리에서 인기있는 앱 300개를 하나의 페이지에 보여줍니다.
카테고리별 인기차트는 동일한 url구조를 가지며 카테고리명으로만 구분하여 접근할 수 있습니다.
인기차트에서 앱을 선택하여 접근하면 url상단에 id를 키로하는 패키지명을 볼 수 있습니다.
해당 패키지명을 기반으로 APK를 검색해야 다운받을 수 있습니다.
앞서 진행해온 과정을 자동화 해주는 크롤러를 Python과 Selenium으로 구현합니다.
추가적인 정보를 구하기위해 패키지명 뿐만 아니라 앱 이름, 아이콘 리소스, 최신 업데이트 날짜, 카테고리를 같이 수집합니다.
APK Downloader
플레이 스토어에서 수집한 데이터들을 사용하여 APKpure.com에서 APK파일을 다운로드 합니다. 구글 플레이스토어의 url과 거의 동일한 형태로 id에 패키지명을 입력하고 검색하면 동일한 앱을 검색할 수 있고 APK파일을 바로 다운받을 수 있습니다. APK 다운로드 버튼을 누르면 새로운 페이지로 이동하면서 자동으로 APK파일의 다운로드가 진행됩니다.
파일 다운로드를 자동으로 요청하기 위해선 파일 요청 url을 파악해야 합니다.
대부분의 파일 요청 링크는 다운로드 버튼의 href 속성에 존재합니다.
APKpure에서는 재 다운로드 요청 버튼에 존재합니다.
브라우저의 개발자 도구를 통해 href 속성을 확인할 수 있습니다.
해당 링크를 Python의 request 라이브러리를 사용하면 파일을 다운받을 수 있습니다.
url에 요청을 보내 파일 다운받는 함수는 다음과 같습니다.
def __download_apk(self,package_name,download_url):
"""
(private)
HTTP request를 통해 APK파일을 다운받음
리퀘스트를 보내는 도중 에러가 발생하면 False반환
정상적으로 파일이 저장완료되면 True반환
package_name : 다운받으려는 패키지 이름
download_url : HTTP request를 날리는 url 이름
"""
file_name = str(package_name) + '.apk'
# timout 1분으로 설정하여 반응이 없는 것들은 예외처리
try:
r = requests.get(download_url, timeout=60)
# apk directory에 패키지이름.apk 형태로 저장
with open(self.apk_directory + file_name,'wb') as apk:
apk.write(r.content)
except requests.exceptions.Timeout as e:
print('time out')
return False
except Exception as e:
print(e)
return False
return True
Conclusion
위에서 설명한 순서대로 시스템을 설계하고 구현하여 다량의 APK파일을 다운받을 수 있습니다. 본 포스팅은 개발한 시스템을 소개하는 글로 기술적인 내용은 포함되어있지 않습니다. 소프트웨어를 사용하다가 기술적으로 문제가 생긴다면 issue 부탁드립니다!!