apkpure.py 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import datetime
  2. import io
  3. from pathlib import Path
  4. import re
  5. import shutil
  6. import time
  7. import zipfile
  8. from selenium import webdriver
  9. class DownloadError(Exception):
  10. pass
  11. def apk_from_xapk(xapk_data, app_id):
  12. """This is necessary because on apkpure.com uses a custom package format xapk for some apps."""
  13. with io.BytesIO(xapk_data) as stream:
  14. with zipfile.ZipFile(stream) as zip:
  15. with zip.open(f"{app_id}.apk", 'r') as f:
  16. return f.read()
  17. def get(app_id):
  18. options = webdriver.FirefoxOptions()
  19. options.add_argument("--headless")
  20. profile = webdriver.FirefoxProfile()
  21. profile.set_preference("browser.download.folderList", 2)
  22. profile.set_preference("browser.helperApps.alwaysAsk.force", False)
  23. profile.set_preference("browser.download.manager.showWhenStarting",False)
  24. profile.set_preference("browser.download.dir", "/tmp/tempapk/")
  25. profile.set_preference("browser.helperApps.neverAsk.saveToDisk", "application/vnd.android.package-archive, application/xapk-package-archive" )
  26. try:
  27. shutil.rmtree('/tmp/tempapk/')
  28. except FileNotFoundError:
  29. pass
  30. with webdriver.Firefox(options=options, firefox_profile=profile) as driver:
  31. driver.get(f"https://apkpure.com/_/{app_id}/download?from=details")
  32. dl_page = driver.page_source
  33. t = datetime.datetime.now()
  34. while True:
  35. p = Path('/tmp/tempapk/')
  36. try:
  37. p = list(p.iterdir())
  38. except FileNotFoundError:
  39. raise DownloadError
  40. if len(p) == 1:
  41. break
  42. elif datetime.datetime.now()-t > datetime.timedelta(seconds=60):
  43. raise DownloadError
  44. time.sleep(1)
  45. with open(p[0], 'rb') as f:
  46. apk_data = f.read()
  47. shutil.rmtree('/tmp/tempapk/')
  48. # check if xapk
  49. match = re.search(r'_v.+_apkpure.com.(x?)apk', dl_page)
  50. xapk = bool(match.groups()[0])
  51. if xapk:
  52. apk_data = apk_from_xapk(apk_data, app_id)
  53. return apk_data