import random from fake_useragent import settings from fake_useragent.errors import FakeUserAgentError from fake_useragent.log import logger from fake_useragent.utils import load, str_types class FakeUserAgent: def __init__( # noqa: PLR0913 self, browsers=["chrome", "edge", "firefox", "safari"], os=["windows", "macos", "linux", "android", "ios"], min_version=0.0, min_percentage=0.0, platforms=["pc", "mobile", "tablet"], fallback=( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0" ), safe_attrs=tuple(), ): # Check inputs assert isinstance(browsers, (list, str)), "browsers must be list or string" if isinstance(browsers, str): browsers = [browsers] self.browsers = browsers assert isinstance(os, (list, str)), "OS must be list or string" if isinstance(os, str): os = [os] # OS replacement (windows -> [win10, win7]) self.os = [] for os_name in os: if os_name in settings.OS_REPLACEMENTS: self.os.extend(settings.OS_REPLACEMENTS[os_name]) else: self.os.append(os_name) assert isinstance( min_percentage, (float, int) ), "Minimum usage percentage must be float or int" if isinstance(min_percentage, int): min_percentage = float(min_percentage) self.min_percentage = min_percentage assert isinstance( min_version, (float, int) ), "Minimum version must be float or int" if isinstance(min_version, int): min_version = float(min_version) self.min_version = min_version assert isinstance(platforms, (list, str)), "platforms must be list or string" if isinstance(platforms, str): platforms = [platforms] self.platforms = platforms assert isinstance(fallback, str), "fallback must be string" self.fallback = fallback assert isinstance( safe_attrs, (list, set, tuple) ), "safe_attrs must be list\\tuple\\set of strings or unicode" if safe_attrs: str_types_safe_attrs = [isinstance(attr, str_types) for attr in safe_attrs] assert all( str_types_safe_attrs ), "safe_attrs must be list\\tuple\\set of strings or unicode" self.safe_attrs = set(safe_attrs) # Next, load our local data file into memory (browsers.json) self.data_browsers = load() # This method will return a filtered list of user agents. # The request parameter can be used to specify a browser. def _filter_useragents(self, request=None): # filter based on browser, os, platform and version. filtered_useragents = list( filter( lambda x: x["browser"] in self.browsers and x["os"] in self.os and x["type"] in self.platforms and x["version"] >= self.min_version and x["percent"] >= self.min_percentage, self.data_browsers, ) ) # filter based on a specific browser request if request: filtered_useragents = list( filter(lambda x: x["browser"] == request, filtered_useragents) ) return filtered_useragents # This method will return an object # Usage: ua.getBrowser('firefox') def getBrowser(self, request): try: # Handle request value for value, replacement in settings.REPLACEMENTS.items(): request = request.replace(value, replacement) request = request.lower() request = settings.SHORTCUTS.get(request, request) if request == "random": # Filter the browser list based on the browsers array using lambda # And based on OS list # And percentage is bigger then min percentage # And convert the iterator back to a list filtered_browsers = self._filter_useragents() else: # Or when random isn't select, we filter the browsers array based on the 'request' using lamba # And based on OS list # And percentage is bigger then min percentage # And convert the iterator back to a list filtered_browsers = self._filter_useragents(request=request) # Pick a random browser user-agent from the filtered browsers # And return the full dict return random.choice(filtered_browsers) # noqa: S311 except (KeyError, IndexError): if self.fallback is None: raise FakeUserAgentError( f"Error occurred during getting browser: {request}" ) # noqa else: logger.warning( f"Error occurred during getting browser: {request}, " "but was suppressed with fallback.", ) # Return fallback object return { "useragent": self.fallback, "system": "Chrome 122.0 Win10", "browser": "chrome", "version": 122.0, "os": "win10", } # This method will use the method below, returning a string # Usage: ua['random'] def __getitem__(self, attr): return self.__getattr__(attr) # This method will returns a string # Usage: ua.random def __getattr__(self, attr): if attr in self.safe_attrs: return super(UserAgent, self).__getattribute__(attr) try: # Handle input value for value, replacement in settings.REPLACEMENTS.items(): attr = attr.replace(value, replacement) attr = attr.lower() attr = settings.SHORTCUTS.get(attr, attr) if attr == "random": # Filter the browser list based on the browsers array using lambda # And based on OS list # And percentage is bigger then min percentage # And convert the iterator back to a list filtered_browsers = self._filter_useragents() else: # Or when random isn't select, we filter the browsers array based on the 'attr' using lamba # And based on OS list # And percentage is bigger then min percentage # And convert the iterator back to a list filtered_browsers = self._filter_useragents(request=attr) # Pick a random browser user-agent from the filtered browsers # And return the useragent string. return random.choice(filtered_browsers).get("useragent") # noqa: S311 except (KeyError, IndexError): if self.fallback is None: raise FakeUserAgentError( f"Error occurred during getting browser: {attr}" ) # noqa else: logger.warning( f"Error occurred during getting browser: {attr}, " "but was suppressed with fallback.", ) return self.fallback @property def chrome(self): return self.__getattr__("chrome") @property def googlechrome(self): return self.chrome @property def edge(self): return self.__getattr__("edge") @property def firefox(self): return self.__getattr__("firefox") @property def ff(self): return self.firefox @property def safari(self): return self.__getattr__("safari") @property def random(self): return self.__getattr__("random") # The following 'get' methods return an object rather than only the UA string @property def getFirefox(self): return self.getBrowser("firefox") @property def getChrome(self): return self.getBrowser("chrome") @property def getEdge(self): return self.getBrowser("edge") @property def getSafari(self): return self.getBrowser("safari") @property def getRandom(self): return self.getBrowser("random") # common alias UserAgent = FakeUserAgent