4 Commits
1.0.5 ... 1.0.7

Author SHA1 Message Date
=
b726f2f668 1.0.7 2025-07-06 18:52:41 +02:00
=
feebd85591 added impersonate browser rotation and ssl verification option 2025-07-06 18:47:03 +02:00
etienne-hd
76dda0cb76 1.0.6 2025-07-01 14:21:14 +02:00
etienne-hd
2888942ecc fix: error when searching with url due to the zipcode 2025-07-01 14:19:08 +02:00
5 changed files with 55 additions and 14 deletions

View File

@@ -1,3 +1,13 @@
## 1.0.7
### Added
* Automatic rotation of browser impersonation when `impersonate` argument in `Client` is set to None.
* Ability to choose which browser to impersonate via the `impersonate` argument in `Client`.
* Option to disable SSL verification for requests by setting `request_verify` to `False` in `Client`.
## 1.0.6
### Fixed
* "Unknown location type" error when searching with a URL containing a zipcode.
## 1.0.5
### Fixed
* 404 error when fetching a pro user who doesn't have a public page

View File

@@ -1,6 +1,6 @@
[project]
name = "lbc"
version = "1.0.5"
version = "1.0.7"
description = "Unofficial client for Leboncoin API"
readme = "README.md"
license = {text = "MIT"}

View File

@@ -4,10 +4,23 @@ from .exceptions import DatadomeError, RequestError
from .utils import build_search_payload_with_args, build_search_payload_with_url
from typing import Optional, List, Union
from curl_cffi import BrowserTypeLiteral
class Client(Session):
def __init__(self, proxy: Optional[Proxy] = None):
super().__init__(proxy=proxy)
def __init__(self, proxy: Optional[Proxy] = None, impersonate: BrowserTypeLiteral = None, request_verify: bool = True):
"""
Initializes a Leboncoin Client instance with optional proxy, browser impersonation, and SSL verification settings.
If no `impersonate` value is provided, a random browser type will be selected among common options.
Args:
proxy (Optional[Proxy], optional): Proxy configuration to use for the client. If provided, it will be applied to all requests. Defaults to None.
impersonate (BrowserTypeLiteral, optional): Browser type to impersonate for requests (e.g., "firefox", "chrome", "edge", "safari", "safari_ios", "chrome_android"). If None, a random browser type will be chosen.
request_verify (bool, optional): Whether to verify SSL certificates when sending requests. Set to False to disable SSL verification (not recommended for production). Defaults to True.
"""
super().__init__(proxy=proxy, impersonate=impersonate)
self.request_verify = request_verify
def _fetch(self, method: str, url: str, payload: Optional[dict] = None, timeout: int = 30) -> Union[dict, None]:
"""
@@ -30,7 +43,8 @@ class Client(Session):
method=method,
url=url,
json=payload,
timeout=timeout
timeout=timeout,
verify=self.request_verify,
)
if response.ok:
return response.json()

View File

@@ -1,25 +1,42 @@
from .models import Proxy
from curl_cffi import requests
from curl_cffi import requests, BrowserTypeLiteral
from typing import Optional
import random
class Session:
def __init__(self, proxy: Optional[Proxy] = None):
self._session = self._init_session(proxy=proxy)
def __init__(self, proxy: Optional[Proxy] = None, impersonate: BrowserTypeLiteral = None):
self._session = self._init_session(proxy=proxy, impersonate=impersonate)
self._proxy = proxy
self._impersonate = impersonate
def _init_session(self, proxy: Optional[Proxy] = None) -> requests.Session:
def _init_session(self, proxy: Optional[Proxy] = None, impersonate: BrowserTypeLiteral = None) -> requests.Session:
"""
Initializes an HTTP session with optional proxy and browser impersonation.
Initializes an HTTP session with optional proxy configuration and browser impersonation.
If no `impersonate` value is provided, a random browser type will be selected among common options.
Args:
proxy (Optional[Proxy], optional): Proxy configuration to use for the session. If provided, it will be applied to both HTTP and HTTPS traffic.
proxy (Optional[Proxy], optional): Proxy configuration to use for the session. If provided, it will be applied to both HTTP and HTTPS traffic. Defaults to None.
impersonate (BrowserTypeLiteral, optional): Browser type to impersonate for requests (e.g., "firefox", "chrome", "edge", "safari", "safari_ios", "chrome_android"). If None, a random browser type will be chosen.
Returns:
requests.Session: A configured session instance ready to send requests.
"""
if impersonate == None: # Pick a random browser client
impersonate: BrowserTypeLiteral = random.choice(
[
"chrome",
"edge",
"safari",
"safari_ios",
"chrome_android",
"firefox"
]
)
session = requests.Session(
impersonate="firefox",
impersonate=impersonate,
)
session.headers.update(

View File

@@ -55,7 +55,7 @@ def build_search_payload_with_url(
location_parts = location.split("__") # City ['Paris', '48.86023250788424_2.339006433295173_9256'], Department ['d_69'], Region ['r_18'] or Place ['p_give a star if you like it!', '0.1234567891234_-0.1234567891234567_5000_5500']
prefix_parts = location_parts[0].split("_")
if len(prefix_parts) == 2: # Department ['d', '1'], Region ['r', '1'], or Place ['p', 'give a star if you like it!']
if len(prefix_parts[0]) == 1: # Department ['d', '1'], Region ['r', '1'], or Place ['p', 'give a star if you like it!']
location_id = prefix_parts[1] # Department '1', Region '1' or Place 'give a star if you like it!'
match prefix_parts[0]:
case "d": # Department
@@ -90,7 +90,7 @@ def build_search_payload_with_url(
payload["filters"]["location"]["locations"].append(
{
"locationType": "city",
"city": location_parts[0],
#"city": location_parts[0],
"area": build_area(area_values)
}
)