Added: dynamic mobile User-Agent generation

This commit is contained in:
etienne-hd
2025-12-24 15:37:35 +01:00
parent 4e69194821
commit 8d4d2da64f
3 changed files with 26 additions and 6 deletions

View File

@@ -18,5 +18,4 @@ class AdMixin:
Ad: An `Ad` object containing the parsed ad information.
"""
body = self._fetch(method="GET", url=f"https://api.leboncoin.fr/api/adfinder/v1/classified/{ad_id}", timeout=self.timeout, max_retries=self.max_retries)
return Ad._build(raw=body, client=self)

View File

@@ -1,8 +1,9 @@
from ..model import Proxy
from curl_cffi import requests, BrowserTypeLiteral
from typing import Optional
import random
import uuid
from ..model import Proxy
class SessionMixin:
def __init__(self, proxy: Optional[Proxy] = None, impersonate: BrowserTypeLiteral = None, request_verify: bool = True, **kwargs):
@@ -11,6 +12,27 @@ class SessionMixin:
self._impersonate = impersonate
super().__init__(**kwargs)
def _generate_user_agent(self) -> str:
# LBC;iOS;26.2;iPhone;phone;01234567-89AB-CDEF-0123-456789ABCDEF;wifi;101.44.0
# LBC;Android;11;Android SDK built for arm64;phone;0123456789ABCDEF;wifi;100.85.2
# LBC;<OS>;<OS_VERSION>;<MODEL>;phone;<DEVICE_ID>;wifi;<APP_VERSION>
os = random.choice(["iOS", "Android"])
if os == "iOS":
os_version = random.choice(["18.0", "18.1", "18.2", "18.3", "18.4", "18.5", "18.6", "18.7", "18.7.3",
"26.0", "26.1", "26.2"])
model = "iPhone"
device_id = str(uuid.uuid4())
app_version = random.choice(["101.45.0", "101.44.0", "101.43.1", "101.43.0", "101.42.1", "101.42.0", "101.41.0", "101.40.0", "101.39.0", "101.38.0"])
else:
os_version = random.choice(["11", "12", "13", "14", "15"])
model = random.choice(["SM-G991B", "SM-G996B", "SM-G998B", "SM-S911B", "SM-S916B", "SM-S918B", "SM-A505F", "SM-A546B", "SM-A137F", "SM-M336B",
"Pixel 5", "Pixel 6", "Pixel 6a", "Pixel 7", "Pixel 7 Pro", "Pixel 8", "Pixel 8 Pro",
"Mi 10", "Mi 11", "Mi 11 Lite", "Redmi Note 10", "Redmi Note 11", "Redmi Note 12", "POCO F3", "POCO F4", "POCO X3 Pro",
"ONEPLUS A6003", "ONEPLUS A6013", "ONEPLUS A5000", "ONEPLUS A5010", "OnePlus 8", "OnePlus 9", "OnePlus 10 Pro", "OnePlus Nord"])
device_id = uuid.uuid4().hex[:16]
app_version = random.choice(["100.85.2", "100.84.1", "100.83.1", "100.82.0", "100.81.1"])
return f"LBC;{os};{os_version};{model};phone;{device_id};wifi;{app_version}"
def _init_session(self, proxy: Optional[Proxy] = None, impersonate: BrowserTypeLiteral = None, request_verify: bool = True) -> requests.Session:
"""
Initializes an HTTP session with optional proxy configuration and browser impersonation.
@@ -28,8 +50,6 @@ class SessionMixin:
if impersonate == None: # Pick a random browser client
impersonate: BrowserTypeLiteral = random.choice(
[
"chrome",
"edge",
"safari",
"safari_ios",
"chrome_android",
@@ -43,11 +63,13 @@ class SessionMixin:
session.headers.update(
{
'User-Agent': self._generate_user_agent(),
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-site',
}
)
print(session.headers["User-Agent"], impersonate)
if proxy:
session.proxies = {
"http": proxy.url,

View File

@@ -23,5 +23,4 @@ class UserMixin:
pro_data = self._fetch(method="GET", url=f"https://api.leboncoin.fr/api/onlinestores/v2/users/{user_id}?fields=all", timeout=self.timeout, max_retries=self.max_retries)
except NotFoundError:
pass # Some professional users may not have a Leboncoin page.
return User._build(user_data=user_data, pro_data=pro_data)