undetected-chromedriver
undetected-chromedriver copied to clipboard
fix executable_path for custom chromedriver
browser_executable_path isn't necessary here, because it is defined by binary_location in options argument.
In other hand, chromedriver executable path is missing for patcher. There is no way to set custom chromedriver path. Without executable_path, undetected_chromedriver will alway download chromedriver from its repo and then patch it also.
@smartwifivn sometimes this could cause an error like this
It's actually because of the function
find_chrome_executable()
doesn't return the right path as shown on the screenshot below and then causes the chrome.exe nonfoundable. it is probably because it's on Python 32 bit rather than 64 bit. I will do a double-check with it.
The temp solution is to send directly the chrome path like this:
exe_path = os.path.normpath("C:\Program Files\Google\Chrome\Application\chrome.exe")
driver = uc.Chrome(browser_executable_path = exe_path)
@BenoitYU From v2, browser excutable path can be passed like this:
chrome_exe_path = "your_chrome_path"
options = uc.ChromeOptions()
options.binary_location = chrome_exe_path
driver = uc.Chrome(
options=options,
)
So the browser_executable_path isn't necessary. Have a look at the current init.py file at line 312-315:
if not options.binary_location:
options.binary_location = (
browser_executable_path or find_chrome_executable()
)
If options.binary_location is set, then browser_executable_path will be meaningless.
I vote for this PR too. The executable_path
is a must have in my case.
Without it the chromedriver is downloaded during each app start which
- transfers lot of data
- slows down significantly the app startup time (in my case it is really important)
- downloads wrong chromedriver version when new chrome is released, which breaks the app without prior warning
- it is not a good practice to download part of the application in runtime - I would like to prepare all necessary components during deployment (in my case inside docker container).
So please, put the executable_path
back.
Thanks in advance and also big thanks for whole this project!!!
I vote for this PR too. The
executable_path
is a must have in my case. Without it the chromedriver is downloaded during each app start which
- transfers lot of data
- slows down significantly the app startup time (in my case it is really important)
- downloads wrong chromedriver version when new chrome is released, which breaks the app without prior warning
- it is not a good practice to download part of the application in runtime - I would like to prepare all necessary components during deployment (in my case inside docker container).
So please, put the
executable_path
back.Thanks in advance and also big thanks for whole this project!!!
One more problem is urlretrieve function doesn't have timeout option, your program should hang forever while downloading chromedriver
In support of this change... When running with multiprocessing each process downloads chromedriver, which is not only highly inefficient, but also results in this error:
OSError: [Errno 26] Text file busy: '/root/.local/share/undetected_chromedriver/chromedriver'
Can this be merged soon, or shall we be patching on our own?
Would love to get some traction on this PR, or just any way to avoid redownloading chromedriver.
I think this is a good idea and proposed the very same approach in #496, with the added capability of specifying that the binary be patched and used from a mkdtemp
directory.
it would be great if this project integrated features from this module ( https://pypi.org/project/chromedriver-autoinstaller/ ).this would make it easier since now the module just blindly downloads the latest version but if it had features like the chromedriver-autoinstaller it would be able to download the driver according to the currently installed version of chrome rather than the latest
If you dont want to redownload every time, use
Chrome(driver_executable_path="your/driver/path/chromedriver")
and if you want specific version @eNcacz
Chrome(version_main=101)
If you dont want to redownload every time, use
Chrome(driver_executable_path="your/driver/path/chromedriver")
and if you want specific version @eNcacz
Chrome(version_main=101)
It doesn't look like the "driver_executable_path" solution works for me, on Linux.
I had the same experience on ubuntu: I did specify the executable_path but only specifying the version helped (once you are using the last minor of the specified major). Thanks for the suggestions.
@rbecerril could you show a snippet? I have the following line:
uc.Chrome(options=chrome_options,version_main=101, driver_executable_path="/home/mike/.local/share/undetected_chromedriver/chromedriver", use_subprocess=True)
And it's still downloading the driver every single time. Am I missing something? @ultrafunkamsterdam
sure, I use a patch:
""" a patch to chromedriver is needed to be able to set the path of the executable """
def force_patcher_to_use(directory):
executable_path = os.path.join(directory, "chromedriver")
""" monkey patch the Patcher class """
class PatcherWithForcedExecutablePath(uc_patcher):
def __init__(self, *args, **kwargs):
kwargs["executable_path"] = executable_path
super().__init__(*args, **kwargs)
uc.Patcher = PatcherWithForcedExecutablePath
return executable_path
uc.Chrome.__init__(self, options=options,
executable_path=force_patcher_to_use(self.user_data_path),
version_main=chromium_version)
I am using chromium_version = 99, so I do not think it updates
sure, I use a patch:
""" a patch to chromedriver is needed to be able to set the path of the executable """ def force_patcher_to_use(directory): executable_path = os.path.join(directory, "chromedriver") """ monkey patch the Patcher class """ class PatcherWithForcedExecutablePath(uc_patcher): def __init__(self, *args, **kwargs): kwargs["executable_path"] = executable_path super().__init__(*args, **kwargs) uc.Patcher = PatcherWithForcedExecutablePath return executable_path uc.Chrome.__init__(self, options=options, executable_path=force_patcher_to_use(self.user_data_path), version_main=chromium_version)
I am using chromium_version = 99, so I do not think it updates
Would this code go in the patcher.py file, and then I would reinstall the package? Sorry for my ignorance on this, this will be a huge help.
EDIT: After looking more into it, it looks like I just add that def to my code, and change my uc.Chrome lines to include that function. However, it gives me a problem with the "uc_patcher" variable, saying that it's not defined. Do I have to do something with that?
EDIT2: Glad everyone can see me learning on the fly here, ha. Changing "uc_patcher" to "uc.Patcher" works, now I just have a permissions issue to fix, its resulting in the following error: "PermissionError: [Errno 13] Permission denied: '/usr/bin/chromedriver'"
EDIT3: The conclusion to the trilogy...by creating a copy of the webdriver executable and moving it to a directory in my local user folder, it looks like the permission issue gets solved and everything runs.