Commit Graph

262 Commits

Author SHA1 Message Date
Karim shoair 16852cb1ac style: Use shorter and more accurate naming for constants 2026-02-07 16:37:47 +02:00
Karim shoair 5ec929435b style: Fix all mypy errors and add type hints to untyped function bodies
**Resolved all 65 mypy errors across 14 files and added type annotations to all previously untyped function bodies. Final result: 0 errors with --check-untyped-defs enabled, all 454 tests pass.**

`scrapling/core/_types.py`

  - Removed broken Self = object fallback — now requires typing_extensions for Python < 3.11

`scrapling/core/storage.py`

  - Fixed str/bytes mismatch in _get_hash() — used separate _identifier_bytes variable instead of reassigning from str to bytes

`scrapling/core/custom_types.py`

  - split() return type: Union[List, "TextHandlers"] → list[Any] (avoids LSP violation with parent list[str])
  - format() kwargs: **kwargs: str → **kwargs: object (matches parent str.format signature)
  - AttributesHandler.__init__: Added mapping: Any = None, **kwargs: Any and -> None
  - json_string property: Added -> bytes return type

`scrapling/core/mixins.py`

  - Changed self: "Selector" to self: Any on all mixin methods (mypy can't handle forward-reference self types on non-subclass mixins)
  - Added Dict[str, int] annotation for counter variable
  - Removed unused TYPE_CHECKING / Selector imports

`scrapling/parser.py (~30 errors)`

  - Added body: str | bytes pre-annotation for dual-type if/elif assignment
  - Used Dict[str, Any] kwargs dict for HTMLParser(...) to bypass incomplete lxml stubs missing default_doctype
  - Changed base_url=url or None → base_url=url or "" (avoids str | None vs str | bytes)
  - bool(adaptive) to guarantee bool type for __adaptive_enabled
  - Declared __text: Optional[TextHandler], __tag: Optional[str], __attributes: Optional[AttributesHandler] at top of __init__
  - cast(List, ...) for all XPath() call results (_find_all_elements, _find_all_elements_with_spaces)
  - Added Dict[float, List[Any]] for score_table, Dict[str, Any] for attributes
  - Changed score, checks = 0, 0 → score: float = 0; checks: int = 0 (two locations)
  - Renamed target → target_element in save() to avoid variable redefinition with different types
  - Wrapped node_text.clean() / .lower() in TextHandler(...) to preserve type

`scrapling/engines/_browsers/_page.py`

  - Added PageInfo[SyncPage] | PageInfo[AsyncPage] union type annotation to page_info variable

`scrapling/engines/_browsers/_validators.py`

  - Convert method_kwargs (TypedDict) to plain Dict[str, Any] before dynamic key access

`scrapling/engines/_browsers/_base.py`

  - Added _config declaration to BaseSessionMixin
  - Used cast(StealthConfig, self._config) in __generate_stealth_options to access stealth-only attributes
  - Added Tuple[str, ...] annotation for flags
  - Removed redundant narrower StealthConfig type annotation on self._config in StealthySessionMixin.__validate__
  - Widened SyncSession and AsyncSession fields (playwright, context, browser) to Any to support both playwright and patchright types
  - Added -> None to both start() methods

`scrapling/engines/_browsers/_stealth.py`

  - Added Optional, ProxyType imports
  - Annotated proxy: Optional[ProxyType] in both sync/async fetch loops
  - Annotated outer_box: Any at first declaration, removed duplicate type annotations in subsequent branches
  - Added -> None to sync and async start()
  - Added config: Any parameter type to _initialize_context
  - Removed redundant self.context: AsyncBrowserContext re-annotations in conditional branches

`scrapling/engines/_browsers/_controllers.py`

  - Added Optional, ProxyType imports
  - Annotated proxy: Optional[ProxyType] in both sync/async fetch loops
  - Added -> None to async start()
  - Removed redundant self.context: AsyncBrowserContext re-annotations

`scrapling/spiders/request.py`

  - Added Optional import, typed _fp: Optional[bytes] = None
  - Removed redundant body: bytes re-annotation

`scrapling/spiders/session.py`

  - Used separate client variable instead of reassigning session = session._client (avoids type incompatibility and fixes a bug where session._make_request was called instead of client._make_request)
  - Added -> None to SessionManager.__init__

`scrapling/engines/toolbelt/convertor.py`

  - Added list[Response] annotation for history in both sync/async methods

`scrapling/engines/static.py`

  - FetcherClient.__init__ and AsyncFetcherClient.__init__: Added **kwargs: Any and -> None

`scrapling/core/shell.py`

  - Wrapped re_sub(...) result in TextHandler(...) to maintain correct type
  - Added -> None to CurlParser.__init__
  - Added full type signature to create_wrapper, replaced wrapper.__signature__ = ... with setattr(wrapper, "__signature__", ...) to satisfy mypy
  - Added Callable to imports
2026-02-07 16:30:00 +02:00
Karim shoair 66476d42be feat(browsers): Add option to block requests to specific domains 2026-02-07 01:26:21 +02:00
Karim shoair 05f62fba81 fix(response): Force the body of the response to always be bytes 2026-02-06 03:14:23 +02:00
Karim shoair f88502718f feat(proxy control): Force a proxy at request level at any given point
And merge request's meta with response's meta
2026-02-02 14:26:52 +02:00
Karim shoair ef8c5bc7d6 feat(spiders/fetchers): Adding proxy rotation logic and change retry logic
- User passes a single proxy to the browser session, and it will keep using the same context. Pass a proxy manager that automatically refreshes the IP with each proxy, and you get speed but sacrifice some stealth.

- User imports the proxy rotator class and passes proxies to it and a rotation strategy (Round robin by default). Then pass the instance to the session class, which will create a context and a tab for each proxy returned by the rotator. This way, you sacrifice speed a bit, but you get maximum stealth since each context is created with the proxy that will be used.

- Normal requests use what you pass without issues, of course.

- All errors are retried now, and proxies are rotated on retries automatically.
2026-02-02 00:16:22 +02:00
Karim shoair 65f1a23358 fix(browsers): Improve stealth and speed by adjusting flags 2026-01-29 00:58:04 +02:00
Karim shoair 0c3d359b46 fix(browsers): disable autoplay for all browsers 2026-01-29 00:57:30 +02:00
Karim shoair 90c52c45c7 feat(parser): replacing tldextract with tld library
This might break the adaptive data users have for websites BUT:
1. tld uses ~3.7x less memory during extraction operations (1.5 MB vs 5.7 MB).
2. tld uses ~56% less memory on import (5.2 MB vs 11.9 MB).
3. Zero dependencies (vs 3 for tldextract).

In return, it's 30ms slower for extracting 5000 URLs, which is negligible. Also, the type hints aren't always accurate, but it's fine; I corrected them.
2026-01-23 00:00:48 +02:00
Karim shoair 5aa178a76e style: update post requests type hints to be more accurate 2026-01-20 18:27:52 +02:00
Karim shoair bf5aa021d4 fix(browsers): solving an issues with leaving playwright loop open when cdp connection fails
This has been causing issues with tests for a long time, and now finally found the reason.
2026-01-18 16:46:48 +02:00
Karim shoair a17bb1d976 feat(browsers): Add option to retry tabs that gives errors 2026-01-11 23:40:26 +02:00
Karim shoair d5b9ed11b2 fix(browsers): Close pages that give error
This was causing the browser and the whole code to stand still.
2026-01-11 18:34:13 +02:00
Karim shoair dd5c30c521 feat(response): Option to set the referer as the previous response url. 2026-01-11 03:24:30 +02:00
Karim shoair 1443a469a3 fix: handle a bug with response follow referer flow argument 2026-01-11 03:22:51 +02:00
Karim shoair c5bc82deb8 fix(browsers): solve a bug with setting referer on the request level 2026-01-11 03:21:03 +02:00
Karim shoair 0634f5796c feat(spiders): Add follow function to the response 2026-01-10 20:39:43 +02:00
Karim shoair f80e8828f7 refactor: internal API changes 2026-01-08 01:53:48 +02:00
Karim shoair 08f3e6efad fix: add missing line 2026-01-08 01:01:00 +02:00
Karim shoair 6a73f9dcd7 refactor: internal API changes to be easily used as indicators for spiders 2026-01-08 00:52:06 +02:00
Karim shoair c8a2456b81 fix(StealthyFetcher): disable incognito mode to solve #123 2026-01-03 01:50:02 +02:00
Karim shoair 4947152be2 docs: change docstring style for some methods 2026-01-01 21:06:35 +02:00
Karim shoair f6f0ed4b37 fix(async stealth): wait the coroutine of the bounding box 2025-12-31 00:19:53 +02:00
Karim shoair 0c7e26ae5c fix(fingerprints): do not create google referer for IPs 2025-12-30 21:58:09 +02:00
Karim shoair ee13af9516 build: update deps
and docstrings
2025-12-29 16:08:51 +02:00
Karim shoair 5e3845f060 docs: shorten docstrings for some functions 2025-12-28 21:56:28 +02:00
Karim shoair 9bfe744840 fix: remove forgotten unused code 2025-12-28 00:14:47 +02:00
Karim shoair 1b838eabd0 fix: update the cookies type hint for the mcp server 2025-12-28 00:08:44 +02:00
Karim shoair 09bbd416b8 fix: remove old proxy logic
When I was caching it with the rest of the data
2025-12-28 00:02:50 +02:00
Karim shoair fb3a1b4c17 style: removing unused code 2025-12-27 20:50:08 +02:00
Karim shoair 842718ba94 fix: update shell signatures for the autocompletion
Added missing fields and reordered classes as well for easier comparisons
2025-12-27 14:30:48 +02:00
Karim shoair cfc667f7dc refactor(fetchers)!: Replace Camoufox with patchright and many optimizations
- DynamicFetcher became 20% faster
- StealthyFetcher became 99% faster
- Scrapling size decreased
- Code became ~400 lines shorter
- Most importantly, scrapling is more stable and reliable now.
- Less confusing for new users.
- More...
2025-12-26 03:21:13 +02:00
Karim shoair f9f34e6ee9 fix: improve the handling of useragent in chrome fetcher 2025-12-24 23:08:30 +02:00
Karim shoair 85b327a598 fix: Improve stealth of dynamic browser by pinning Chrome's UA version 2025-12-24 21:34:44 +02:00
Karim shoair ecb97d3fd6 docs: add docs for timezone_id argument 2025-12-18 01:16:22 +02:00
Karim shoair 39f544eae4 feat(dynamicSession): add the option to set timezone of the browser 2025-12-18 01:13:31 +02:00
Karim shoair b507e4d4a0 refactor(fetchers): rename internal api
To make it easier to use to use sessions outside `with` context
2025-12-17 01:27:40 +02:00
Karim shoair aed34e43b5 fix(fetchers): better handling for infinite network_idle 2025-12-03 03:11:30 +02:00
Karim shoair 04a612e64e docs: fix docstrings for all requests methods 2025-11-25 21:05:21 +02:00
Karim shoair 5376c97996 fix(fetcher): Remove non-keywords arguments 2025-11-25 20:25:09 +02:00
Karim shoair f0b01fc253 refactor(browser fetchers): Make all the type hints dynamic + Faster validation
Made the code shorter by an additional ~200 lines and easier to maintain in return for making the arguments autocompletion bad for shells that don't check for dynamic type hints like IPython.
2025-11-25 20:18:36 +02:00
Karim shoair 9e85311ff6 fix(validators): Fix overriding session values with request ones 2025-11-25 19:48:09 +02:00
Karim shoair 74f24d60f6 fix(fetcher): Replace vars logic with one that doesn't require dict attribute 2025-11-24 13:04:12 +02:00
Karim shoair c487faf4fd pref(requests): Optimizing memory by specifiying slots 2025-11-23 21:50:54 +02:00
Karim shoair 357b170e1c refactor(requests): Make all the type hints dynamic
Made the code shorter by about ~500 lines and easier to maintain in return for making the arguments autocompletion bad for shells that don't check for dynamic type hints like IPython.
2025-11-23 20:48:51 +02:00
Karim shoair 3565f9d500 feat(fetcher): Make impersonate able to randomize fingerprint 2025-11-16 16:33:58 +02:00
Karim shoair c8b9a04e87 docs: making some adjustments 2025-11-14 02:22:59 +02:00
Karim shoair d018d6e438 fix: fixing the response logic 2025-11-10 03:03:05 +02:00
Karim shoair ff19dd5bf5 feat: replace raw_response property with smart content detection 2025-11-10 02:39:45 +02:00
Karim shoair df073c4680 fix: added raw_response to separate collected response from rendered response 2025-11-08 20:09:40 +02:00