File size: 5,370 Bytes
4cef980 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | import random
from threading import Lock
from fake_useragent import settings
from fake_useragent.errors import FakeUserAgentError
from fake_useragent.log import logger
from fake_useragent.utils import load, load_cached, str_types, update
class FakeUserAgent:
def __init__(
self,
use_external_data=False,
cache_path=settings.DB,
fallback=None,
browsers=["chrome", "edge", "internet explorer", "firefox", "safari", "opera"],
verify_ssl=True,
safe_attrs=tuple(),
):
assert isinstance(
use_external_data, bool
), "use_external_data must be True or False"
self.use_external_data = use_external_data
assert isinstance(cache_path, str_types), "cache_path must be string or unicode"
self.cache_path = cache_path
if fallback is not None:
assert isinstance(fallback, str_types), "fallback must be string or unicode"
self.fallback = fallback
assert isinstance(browsers, (list, str)), "browsers must be list or string"
self.browsers = browsers
assert isinstance(verify_ssl, bool), "verify_ssl must be True or False"
self.verify_ssl = verify_ssl
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)
# initial empty data
self.data_browsers = {}
self.load()
def load(self):
try:
with self.load.lock:
if self.use_external_data:
# Use external resource to retrieve browser data
self.data_browsers = load_cached(
self.cache_path,
self.browsers,
verify_ssl=self.verify_ssl,
)
else:
# By default we will try to load our local file
self.data_browsers = load(
self.browsers,
verify_ssl=self.verify_ssl,
)
except FakeUserAgentError:
if self.fallback is None:
raise
else:
logger.warning(
"Error occurred during fetching data, "
"but was suppressed with fallback.",
)
load.lock = Lock()
def update(self, use_external_data=None):
with self.update.lock:
if use_external_data is not None:
assert isinstance(
use_external_data, bool
), "use_external_data must be True or False"
self.use_external_data = use_external_data
# Update tmp cache file from external data source
if self.use_external_data:
update(
self.cache_path,
self.browsers,
verify_ssl=self.verify_ssl,
)
self.load()
update.lock = Lock()
def __getitem__(self, attr):
return self.__getattr__(attr)
def __getattr__(self, attr):
if attr in self.safe_attrs:
return super(UserAgent, self).__getattr__(attr)
try:
for value, replacement in settings.REPLACEMENTS.items():
attr = attr.replace(value, replacement)
attr = attr.lower()
if attr == "random":
# Pick a random browser from the browsers argument list
browser_name = random.choice(self.browsers)
else:
browser_name = settings.SHORTCUTS.get(attr, attr)
# Pick a random user-agent string for a specific browser
return random.choice(self.data_browsers[browser_name])
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 ie(self):
return self.__getattr__("ie")
@property
def internetexplorer(self):
return self.ie
@property
def msie(self):
return self.ie
@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 opera(self):
return self.__getattr__("opera")
@property
def random(self):
return self.__getattr__("random")
# common alias
UserAgent = FakeUserAgent
|