kaliiiiiiiiii / Selenium-Profiles

undetected Selenium using chromedriver and emulation / device profiles
Other
290 stars 28 forks source link

Not compatible with threading #66

Closed pnthai88 closed 1 year ago

pnthai88 commented 1 year ago

Describe the bug When i start it with flask, do my jobs on it, close the browser, start a new one with custom parameters ig. (start with url, ... etc). Then start a new browser again it cause error

python-code

def create_driver(....):
          if chrome_method == "normal":
                      #.............
                      # The normal chrome is ok, no problem here
          elif chrome_method == "profile":            
                      # start chrome with selenium-profiles
                      # #chrome profiles
                      profile = None
                      if 'Windows' in user_agent:
                          profile = profiles.Windows() # or .Android .Windows
                      elif 'Android' in user_agent:
                          profile = profiles.Android()
                      #chrome_options.add_argument("--headless=new")
                      service = Service(ChromeDriverManager().install())
                      #service = Service(executable_path=executable_driver_location)
                      driver = Chrome(profile, options=chrome_options, base_drivers=(webdriver.Chrome,), service=service, uc_driver=uc_driver)  
                      return driver

@app.route('/start-testing', methods=['GET'])
def start_testing():
          driver = create_driver(....) # start with selenium-profiles parameters
          driver.get("https://abc.com ....")
          #.... tasks to do ....

error-message

Exception in thread Thread-48:
Traceback (most recent call last):
  File "C:\ProgramData\Anaconda3\lib\threading.py", line 926, in _bootstrap_inner
    self.run()
  File "C:\ProgramData\Anaconda3\lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File ".\ChromeManager.py", line 826, in take_screenshots
    screenshot_base64 = driver.get_screenshot_as_base64()
  File "C:\Users\...\selenium\webdriver\remote\webdriver.py", line 1370, in get_screenshot_as_base64
    return self.execute(Command.SCREENSHOT)['value']
  File "C:\Users\...\selenium\webdriver\remote\webdriver.py", line 430, in execute
    self.error_handler.check_response(response)
  File "C:\Users\...\selenium\webdriver\remote\errorhandler.py", line 247, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchWindowException: Message: no such window: target window already closed
from unknown error: web view not found
  (Session info: chrome=114.0.5735.199)
Stacktrace:
Backtrace:
        GetHandleVerifier [0x00B4A813+48355]
        (No symbol) [0x00ADC4B1]
        (No symbol) [0x009E5358]
        (No symbol) [0x009CD293]
        (No symbol) [0x00A2E37B]
        (No symbol) [0x00A3C473]
        (No symbol) [0x00A2A536]
        (No symbol) [0x00A082DC]
        (No symbol) [0x00A093DD]
        GetHandleVerifier [0x00DAAABD+2539405]
        GetHandleVerifier [0x00DEA78F+2800735]
        GetHandleVerifier [0x00DE456C+2775612]
        GetHandleVerifier [0x00BD51E0+616112]
        (No symbol) [0x00AE5F8C]
        (No symbol) [0x00AE2328]
        (No symbol) [0x00AE240B]
        (No symbol) [0x00AD4FF7]
        BaseThreadInitThunk [0x760C00C9+25]
        RtlGetAppContainerNamedObjectPath [0x76FC7B4E+286]
        RtlGetAppContainerNamedObjectPath [0x76FC7B1E+238]

stat: path should be string, bytes, os.PathLike or integer, not collections.defaultdict
An error occurred while configuring the WebDriver: stat: path should be string, bytes, os.PathLike or integer, not collections.defaultdict

Environment (please complete the following information):

kaliiiiiiiiii commented 1 year ago

@pnthai88 Not sure if the service argument works as intended. Can you try with the following shortly? Should be doing the same internally.

# ...
executable_driver_location = ChromeDriverManager().install()
driver = Chrome(profile, options=chrome_options, 
executable_path=executable_driver_location, uc_driver=uc_driver)  
return driver
# ...
pnthai88 commented 1 year ago

I tried with include the executable path and the error same.

except Exception as e:
        import traceback
        traceback.print_exc()
        print(f"An error occurred while configuring the WebDriver: {str(e)}")
Traceback (most recent call last):
  File ".\ChromeManager.py", line 286, in configure_driver
    driver = Chrome(profile, options=chrome_options, base_drivers=(webdriver.Chrome,), service=service, uc_driver=uc_driver)
  File "C:\ProgramData\Anaconda3\lib\site-packages\undetected_chromedriver\__init__.py", line 43, in __new__
    ChromeDriverManager(*args, **kwargs).install()
  File "C:\ProgramData\Anaconda3\lib\site-packages\undetected_chromedriver\__init__.py", line 189, in install
    if not os.path.exists(self.executable_path):
  File "C:\ProgramData\Anaconda3\lib\genericpath.py", line 19, in exists
    os.stat(path)
TypeError: stat: path should be string, bytes, os.PathLike or integer, not collections.defaultdict
An error occurred while configuring the WebDriver: stat: path should be string, bytes, os.PathLike or integer, not collections.defaultdict

As i see the problem is at undetected_chromedriver plugin

import undetected_chromedriver as uc_webdriver

// your work is awesome!

kaliiiiiiiiii commented 1 year ago

I tried with include the executable path and the error same.

except Exception as e:
        import traceback
        traceback.print_exc()
        print(f"An error occurred while configuring the WebDriver: {str(e)}")
Traceback (most recent call last):
  File ".\ChromeManager.py", line 286, in configure_driver
    driver = Chrome(profile, options=chrome_options, base_drivers=(webdriver.Chrome,), service=service, uc_driver=uc_driver)
  File "C:\ProgramData\Anaconda3\lib\site-packages\undetected_chromedriver\__init__.py", line 43, in __new__
    ChromeDriverManager(*args, **kwargs).install()
  File "C:\ProgramData\Anaconda3\lib\site-packages\undetected_chromedriver\__init__.py", line 189, in install
    if not os.path.exists(self.executable_path):
  File "C:\ProgramData\Anaconda3\lib\genericpath.py", line 19, in exists
    os.stat(path)
TypeError: stat: path should be string, bytes, os.PathLike or integer, not collections.defaultdict
An error occurred while configuring the WebDriver: stat: path should be string, bytes, os.PathLike or integer, not collections.defaultdict

oh wait a minute, are you sure that Chrome (File ".\ChromeManager.py", line 286, in configure_driver) refers to selenium_profiles.webdriver.Chrome and not undetected_chromedriver.webdriver.Chrome ?

According to the stack, it seems to me like you're passing the profile as path in undetected_chromedriver.webdriver.Chrome.

// your work is awesome!

Thank you!

pnthai88 commented 1 year ago

i print parameters

executable_driver_location = C:\Users\...\chrome\chromedriver_gggg.exe (it's valid)

profile = profiles.Android() =
defaultdict(<function return_profile.<locals>.<lambda> at 0x000002BA33AA9B88>, {
    'options': {'gpu': False, 'window_size': {'x': 384, 'y': 700}},
    'cdp': {
        'touch': True,
        'maxtouchpoints': 10,
        'cores': 8,
        'patch_version': True,
        'emulation': {
            'mobile': True,
            'width': 384,
            'height': 700,
            'deviceScaleFactor': 4,
            'screenOrientation': {'type': 'portraitPrimary', 'angle': 0}
        },
        'useragent': {
            'platform': 'Linux aarch64',
            'acceptLanguage': 'en-US',
            'userAgent': 'Mozilla/5.0 (Linux; Android 11; HD1913) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Mobile
Safari/537.36',
            'userAgentMetadata': {
                'brands': [
                    {'brand': 'Google Chrome', 'version': '105'},
                    {'brand': 'Not)A;Brand', 'version': '8'},
                    {'brand': 'Chromium', 'version': '105'}
                ],
                'fullVersionList': [
                    {'brand': 'Google Chrome', 'version': '105.0.5195.136'},
                    {'brand': 'Not)A;Brand', 'version': '8.0.0.0'},
                    {'brand': 'Chromium', 'version': '105.0.5195.136'}
                ],
                'fullVersion': '105.0.5195.136',
                'platform': 'Android',
                'platformVersion': '11.0.0',
                'architecture': '',
                'model': 'HD1913',
                'mobile': True,
                'bitness': '',
                'wow64': False
            }
        }
    }
})
Traceback (most recent call last):
  File ".\ChromeManager.py", line 272, in configure_driver
    driver = Chrome(profile, options=chrome_options, base_drivers=(webdriver.Chrome,), service=service, uc_driver=uc_driver, seleniumwire_options=False)
  File "C:\ProgramData\Anaconda3\lib\site-packages\undetected_chromedriver\__init__.py", line 43, in __new__
    ChromeDriverManager(*args, **kwargs).install()
  File "C:\ProgramData\Anaconda3\lib\site-packages\undetected_chromedriver\__init__.py", line 189, in install
    if not os.path.exists(self.executable_path):
  File "C:\ProgramData\Anaconda3\lib\genericpath.py", line 19, in exists
    os.stat(path)
TypeError: stat: path should be string, bytes, os.PathLike or integer, not collections.defaultdict
An error occurred while configuring the WebDriver: stat: path should be string, bytes, os.PathLike or integer, not collections.defaultdict

i changed the import

#from selenium_stealth import stealth
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager

import selenium_profiles
print(f"selenium_profiles.__version__ == {selenium_profiles.__version__}")
from selenium_profiles.webdriver import Chrome
from selenium_profiles.profiles import profiles

        if chrome_method == "normal":
            from selenium.webdriver.chrome.options import Options
            chrome_options = Options()
        elif chrome_method == "profile":
            from seleniumwire import webdriver as seleniumwirewebdriver
            chrome_options = seleniumwirewebdriver.ChromeOptions()

       if chrome_method == "normal":
            # the normal configuration work fine
       elif chrome_method == "profile":            
            profile = None
            if 'Windows' in user_agent:
                profile = profiles.Windows() # or .Android .Windows
            elif 'Android' in user_agent:
                profile = profiles.Android()
            service = Service(executable_path=executable_driver_location)
            from seleniumwire import webdriver as seleniumwirewebdriver
            driver = Chrome(profile, options=chrome_options, base_drivers=(seleniumwirewebdriver.Chrome,), service=service, uc_driver=uc_driver, seleniumwire_options=False)

but the problem still happen, very strange

Traceback (most recent call last):
  File ".\ChromeManager.py", line 277, in configure_driver
    driver = Chrome(profile, options=chrome_options, base_drivers=(seleniumwirewebdriver.Chrome,), service=service, uc_driver=uc_driver, seleniumwire_options=False)
  File "C:\ProgramData\Anaconda3\lib\site-packages\undetected_chromedriver\__init__.py", line 43, in __new__
    ChromeDriverManager(*args, **kwargs).install()
  File "C:\ProgramData\Anaconda3\lib\site-packages\undetected_chromedriver\__init__.py", line 189, in install
    if not os.path.exists(self.executable_path):
  File "C:\ProgramData\Anaconda3\lib\genericpath.py", line 19, in exists
    os.stat(path)
TypeError: stat: path should be string, bytes, os.PathLike or integer, not collections.defaultdict
An error occurred while configuring the WebDriver: stat: path should be string, bytes, os.PathLike or integer, not collections.defaultdict
Saving all_data... from len of USER-LIST 71
Traceback (most recent call last):
  File ".\ChromeManager.py", line 277, in configure_driver
    driver = Chrome(profile, options=chrome_options, base_drivers=(seleniumwirewebdriver.Chrome,), service=service, uc_driver=uc_driver, seleniumwire_options=False)
  File "C:\ProgramData\Anaconda3\lib\site-packages\undetected_chromedriver\__init__.py", line 43, in __new__
    ChromeDriverManager(*args, **kwargs).install()
  File "C:\ProgramData\Anaconda3\lib\site-packages\undetected_chromedriver\__init__.py", line 189, in install
    if not os.path.exists(self.executable_path):
  File "C:\ProgramData\Anaconda3\lib\genericpath.py", line 19, in exists
    os.stat(path)
TypeError: stat: path should be string, bytes, os.PathLike or integer, not collections.defaultdict
An error occurred while configuring the WebDriver: stat: path should be string, bytes, os.PathLike or integer, not collections.defaultdict

here is the simple code that cause same problem

from flask import Flask, request
from selenium_profiles.webdriver import Chrome
from selenium_profiles.profiles import profiles
from seleniumwire import webdriver
import time

app = Flask(__name__)

@app.route('/start', methods=['GET'])
def start():
    profile = profiles.Android() # or .Android
    options = webdriver.ChromeOptions()
    driver = Chrome(profile, options=options, base_drivers=(webdriver.Chrome,),
                    uc_driver=True
                    )
    # get url
    url = request.args.get('url')
    driver.get(url)

    time.sleep(100)

    return "hello"

if __name__ == '__main__':
    app.run(debug=False)

[2023-07-07 17:45:08,594] ERROR in app: Exception on /start [GET]
Traceback (most recent call last):
  File "C:\Users\thaip\AppData\Roaming\Python\Python37\site-packages\flask\app.py", line 2529, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\thaip\AppData\Roaming\Python\Python37\site-packages\flask\app.py", line 1825, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\thaip\AppData\Roaming\Python\Python37\site-packages\flask\app.py", line 1823, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\thaip\AppData\Roaming\Python\Python37\site-packages\flask\app.py", line 1799, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
  File ".\test.py", line 14, in start
    uc_driver=True
  File "C:\ProgramData\Anaconda3\lib\site-packages\undetected_chromedriver\__init__.py", line 43, in __new__
    ChromeDriverManager(*args, **kwargs).install()
  File "C:\ProgramData\Anaconda3\lib\site-packages\undetected_chromedriver\__init__.py", line 189, in 
install
    if not os.path.exists(self.executable_path):
  File "C:\ProgramData\Anaconda3\lib\genericpath.py", line 19, in exists
    os.stat(path)
TypeError: stat: path should be string, bytes, os.PathLike or integer, not collections.defaultdict    
127.0.0.1 - - [07/Jul/2023 17:45:08] "GET /start?url=google.com HTTP/1.1" 500 -

image

pnthai88 commented 1 year ago

Ah... the problem is ...

Successfully uninstalled undetected-chromedriver-2.1.1

the fix

Installing collected packages: undetected_chromedriver
Successfully installed undetected_chromedriver-3.5.0
kaliiiiiiiiii commented 1 year ago

Ah... the problem is ...

Successfully uninstalled undetected-chromedriver-2.1.1

the fix

Installing collected packages: undetected_chromedriver
Successfully installed undetected_chromedriver-3.5.0

huh that's weird, no idea why this occurs tbh.

Note here: as you're importing from seleniumwire import webdriver and then specifying base_drivers=(seleniumwirewebdriver.Chrome,), you're automatically using seleniumwire (internally equivalent to seleniumwire_options=True)

closing this issue as it seems like a bug within undetected-chromedriver