apkpure.py 1.9 KB

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