Last active
September 30, 2024 13:36
-
-
Save arulrajnet/2424bc1ffc40324f3786 to your computer and use it in GitHub Desktop.
Python Script to download the Chrome Extensions (CRX) file directly from the google chrome web store.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
""" | |
Python Script to download the Chrome Extensions (CRX) file directly from the google chrome web store. | |
Referred from http://chrome-extension-downloader.com/how-does-it-work.php | |
""" | |
from __future__ import division | |
import argparse | |
import requests | |
try: | |
import urlparse | |
except ImportError: | |
import urllib.parse as urlparse | |
import sys | |
__author__ = 'arul' | |
class ChromeAppDownloader(): | |
CRX_URL = "https://clients2.google.com/service/update2/crx?" \ | |
"response=redirect&prodversion=38.0&x=id%3D~~~~%26installsource%3Dondemand%26uc" | |
USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36" | |
global headers | |
headers = { | |
"User-Agent": USER_AGENT, | |
"Referer": "https://chrome.google.com", | |
} | |
def __init__(self): | |
pass | |
def download(self, _download_url_, _file_name_): | |
""" | |
Download the given URL into given filename. | |
:param _download_url_: | |
:param _file_name_: | |
:return: | |
""" | |
try: | |
# Download as Stream | |
r = requests.get(url=_download_url_, headers=headers, stream=True) | |
redirects = r.history | |
_fname_ = None | |
if len(redirects) > 0: | |
redirect_header = redirects[-1].headers | |
if "location" in redirect_header: | |
loc = redirect_header["location"] | |
uparse = urlparse.urlparse(loc) | |
splits = uparse.path.split("/") | |
_fname_ = splits[-1] | |
if _fname_: | |
_file_name_ = _fname_.replace("extension", _file_name_) | |
else: | |
_file_name_ += ".crx" | |
r_headers = r.headers | |
content_length = None | |
if "content-length" in r_headers: | |
content_length = int(r_headers["content-length"]) | |
if content_length: | |
print("Downloading %s. File Size %s " % (_file_name_, self.byte_to_human(content_length))) | |
else: | |
print("Downloading %s " % _file_name_) | |
chunk_size = 16 * 1024 | |
dowloaded_bytes = 0 | |
with open(_file_name_, 'wb') as fd: | |
for chunk in r.iter_content(chunk_size): | |
fd.write(chunk) | |
dowloaded_bytes += len(chunk) | |
sys.stdout.write("\r" + self.byte_to_human(dowloaded_bytes)) | |
sys.stdout.flush() | |
except Exception as e: | |
raise ValueError("Error in downloading %s " % _download_url_, e) | |
def parse(self, chrome_store_url): | |
""" | |
Validate the given input is chrome store URL or not. | |
Returning app ID and app Name from the URL | |
:param chrome_store_url: | |
:return: | |
""" | |
try: | |
# Try to validate the URL | |
uparse = urlparse.urlparse(chrome_store_url) | |
if uparse.netloc != "chrome.google.com": | |
raise ValueError("Not a valid URL %s" % chrome_store_url) | |
splits = uparse.path.split("/") | |
if not (len(splits) == 4 and uparse.path.startswith("/webstore/detail/")): | |
raise ValueError("Not a valid URL %s" % chrome_store_url) | |
except Exception as e: | |
pass | |
return splits[-1], splits[-2] | |
def byte_to_human(self, len_in_byte): | |
""" | |
Converts byte into human readable format. | |
:param len_in_byte: | |
:return: | |
""" | |
in_kb = len_in_byte / 1024 | |
in_mb = in_kb / 1024 | |
in_gb = in_mb / 1024 | |
if in_kb < 1024: | |
return "%.2f KB" % in_kb | |
if in_mb < 1024: | |
return "%.2f MB" % in_mb | |
if in_gb > 1: | |
return "%.2f GB" % in_gb | |
if __name__ == '__main__': | |
# Getting webstore URL from User | |
parser = argparse.ArgumentParser(description='Download CRX file from Google Chrome Webstore.') | |
parser.add_argument('-u', '--url', help='URL of the chrome store', required=True) | |
args = parser.parse_args() | |
downloader = ChromeAppDownloader() | |
try: | |
file_name = None | |
# Validating and building app ID, file name for the given URL | |
chrome_app_id, file_name = downloader.parse(chrome_store_url=args.url) | |
if chrome_app_id: | |
download_url = downloader.CRX_URL.replace("~~~~", chrome_app_id) | |
# Downloading the CRX file | |
downloader.download(download_url, file_name) | |
except Exception as e: | |
print(e) |
not work
local variable 'splits' referenced before assignment
not work
local variable 'splits' referenced before assignment
@TechComet Issue fixed.
not work
downloads file with 0 bytes size
P.S.
Problem resolved by https://github.com/tonystark93/crx-download
Changing these constants works for me
CRX_URL = "https://clients2.google.com/service/update2/crx?response=redirect&prodversion=98.0.4758.102&acceptformat=crx2,crx3&x=id%3D~~~~%26uc&nacl_arch=x86-64"
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36"
However, the downloaded crx seems to include signature which needs to be removed before it can be extracted.
@TechComet Issue fixed.
It still doesn't work with Python 3.13
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
it still works ignoring the # if not (len(splits) == 4 and uparse.path.startswith("/webstore/detail/")):
assertion.