Commit Graph
100 Commits
Author SHA1 Message Date
Karim shoair 4e3829fced style: expose ProxyRotator class to the public API 2026-02-10 21:20:07 +02:00
Karim shoair 8df74dc57b docs: updating http requests page and some corrections 2026-02-10 19:07:09 +02:00
Karim shoair f25fe64d3c docs: updating fetcher choosing page and some corrections 2026-02-10 19:01:50 +02:00
Karim shoair 87b99a407b docs: updating adaptive page and some corrections 2026-02-10 19:00:36 +02:00
Karim shoair 11bd4e4295 docs: updating main classes page and some corrections 2026-02-10 18:58:58 +02:00
Karim shoair 44e2c42eaf docs: updating selection page and some corrections 2026-02-10 18:42:37 +02:00
Karim shoair 989fdca201 docs: updating benchmarks page 2026-02-10 18:28:23 +02:00
Karim shoair a5abf1f3ba docs: updating overview page and some corrections 2026-02-10 18:25:31 +02:00
Karim shoair 8505c4a91c docs: possible fix for RTD zensical build 2026-02-09 01:50:22 +02:00
Karim shoair 33eb2ff56b docs: possible fix for RTD zensical build 2026-02-09 01:41:50 +02:00
Karim shoair 9b46cb35ab docs: possible fix for RTD zensical build 2026-02-09 01:16:04 +02:00
Karim shoair dc071ee6b8 docs: possible fix for RTD zensical build 2026-02-09 01:10:00 +02:00
Karim shoair 8ed71e4864 V4 (#130) 2026-02-09 00:55:21 +02:00
Karim shoair e688093974 docs: update the translated readme files with the new content 2026-02-09 00:46:58 +02:00
Karim shoair 3dc4bdcb4a docs: small adjustments to the readme file 2026-02-09 00:36:52 +02:00
Karim shoair 2a4d008927 docs: full update for main readme 2026-02-09 00:28:24 +02:00
Karim shoair 1f9eb17414 ops: update benchmarks script 2026-02-08 23:33:30 +02:00
Karim shoair 0c86d70307 docs: update the website main page 2026-02-08 23:33:10 +02:00
Karim shoair ca46070a1b docs: Improve README.md description formatting
Reformatted the description of Scrapling for clarity and readability.
2026-02-08 22:43:00 +02:00
Karim shoair 8d82d3c90d docs: update readme file 2026-02-08 22:39:50 +02:00
Karim shoair 9a108160c2 docs: move translated README files to docs folder again 2026-02-08 22:18:36 +02:00
Karim shoair 12b731b14b docs: move readme files to the root directory 2026-02-08 21:04:15 +02:00
Karim shoair 09cd5e6183 docs(readme): update translation links 2026-02-08 20:54:26 +02:00
Karim shoair 2ae11d21da docs: full switch from mkdocs to zensical 2026-02-08 20:46:38 +02:00
Karim shoair db41a6c4b6 docs: update pages with the new media for testing zensical 2026-02-08 20:46:14 +02:00
Karim shoair 0e2e9fb2ed docs: moving readme files to be outside of the website build 2026-02-08 20:45:03 +02:00
Karim shoair 219db79195 docs: update logo and media 2026-02-08 20:44:04 +02:00
Karim shoair 3eaa7ffc25 ops: exclude site directory from git 2026-02-08 20:42:35 +02:00
Karim shoair b1ce0b414b ops: Add mypy and pyright to the code quality workflow 2026-02-07 17:28:44 +02:00
Karim shoair 16852cb1ac style: Use shorter and more accurate naming for constants 2026-02-07 16:37:47 +02:00
Karim shoair ec7c7f8153 Merge branch 'main' into v4 2026-02-07 16:30:37 +02:00
Karim shoair e777342741 build: pump up version and deps 2026-02-07 16:30:32 +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 5f557a7f9f test: add tests for the new feature 2026-02-07 01:28:58 +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 d00c34ee7f style(parser): Improve the type hint for find_by_text and find_by_regex 2026-02-06 03:19:00 +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 9acc8194c5 test: update the tests accordingly 2026-02-06 02:45:13 +02:00
Karim shoair aa7a95fb70 feat(parser)!: Make all selection return selector objects by default
- The strings/Texthandlers are only returned by `get`/`getall`/`extract`/`extract_first`. This makes the type checking/autocompletion experience consistent.
- Removed `css_first` and `xpath_first` since it doesn't make sense to leave them now.
- Made the type hints more accurate in multiple places.
2026-02-06 02:43:51 +02:00
Karim shoair d8fe909c8b docs: make translation urls absolute
For PyPI, Docker, and other external websites featuring this
2026-02-05 02:44:12 +02:00
Karim shoair 151e4e7a7c docs: adding new sponsor 2026-02-05 02:39:51 +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 6e0277f23b test: add new tests for the proxy rotation logic 2026-02-02 00:16:40 +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 5dbbd84b3d fix(requests): return the cached fingerprint on second call 2026-01-20 20:28:13 +02:00
Karim shoair d90189e675 test: update tests accordingly 2026-01-20 20:22:47 +02:00
Karim shoair 122923c80e feat(spiders/requests): Use a reliable method for fingerprint generation 2026-01-20 20:21:42 +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 d0f52c3855 test: remove the tests for the removed html_utils module 2026-01-20 16:37:17 +02:00
Karim shoair 95955af3be build: Add w3lib to deps 2026-01-20 16:36:34 +02:00
Karim shoair 0ec78e2335 test: update tests accordingly 2026-01-19 16:40:18 +02:00
Karim shoair 6947066761 feat(spiders): Make graceful shutdown always enabled 2026-01-19 16:40:02 +02:00
Karim shoair 94bc759c6a test: updates tests to include new logic 2026-01-19 16:13:29 +02:00
Karim shoair 25850db92c fix(spiders): handle errors with manual pause during stream mode 2026-01-19 16:13:03 +02:00
Karim shoair fbc8be5bcc fix(spiders): fix a bug with session stats counter 2026-01-19 16:00:06 +02:00
Karim shoair 4ecf8a64d3 fix(spiders): Fix for when the pausing system has large queue 2026-01-19 15:04:40 +02:00
Karim shoair cf0de7ea6d Merge branch 'main' into v4 2026-01-19 14:47:59 +02:00
Karim shoair 9229cef895 docs: adding new sponsor 2026-01-19 14:12:32 +02:00
Karim shoair d247b5b691 test: add tests for the spiders system
It's generated by Opus on Claude Code. It's very good as per my review and instructions, but I will have another look later.
2026-01-19 03:46:00 +02:00
Karim shoair 0d003f62e3 ops: update bandit checklist 2026-01-19 03:45:39 +02:00
Karim shoair 1f0f86e3a2 feat(spiders): Add pause/resume system for crawls 2026-01-19 03:43:10 +02:00
Karim shoair acdb39988c ops: update bandit checklist 2026-01-19 03:40:57 +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 02c9dffc77 style(spiders): make parse function abstract 2026-01-18 00:01:04 +02:00
Karim shoair afe6b2e97b feat(spiders): Change items hook to make it for processing items + add a stat for this 2026-01-17 20:52:49 +02:00
Karim shoair 41c7a7e793 fix(spiders engine): Improve logging 2026-01-17 19:57:04 +02:00
Karim shoair dac854a129 fix(parser): handle responses with empty body
It makes root's value None
2026-01-13 02:35:26 +02:00
Karim shoair 35d570120a feat(spiders): Add option to logging format and date format 2026-01-12 17:11:52 +02:00
Karim shoair 3466bcab2c feat: add hook to run after collecting an item 2026-01-12 15:58:33 +02:00
Karim shoair e0f94cf7d0 feat(spiders): Add a stream mode to collect items in realtime 2026-01-12 15:53:29 +02:00
Karim shoair 927cfd85ff feat(spiders): The option to start sessions lazily 2026-01-12 02:09:50 +02:00
Karim shoair f2c6216968 style: remove unwanted import from spiders main init file 2026-01-12 01:21:26 +02:00
Karim shoair 72c3c2792a feat(spiders): add simple export system for the results 2026-01-12 01:21:05 +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 5a11c2466b fix: make retry_blocked_request take the response as well 2026-01-11 22:54:17 +02:00
Karim shoair 736873a7c6 feat(spiders): Add logic to detect blocked requests and retry them 2026-01-11 21:56:57 +02:00
Karim shoair 774364b6d3 style(spiders): make the usage of uvloop optional 2026-01-11 19:57:03 +02:00
Karim shoair 0bfdab7158 feat: spiders use uvloop/winloop when available 2026-01-11 18:39:42 +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 32f4f2adf4 build: Add AnyIO to the dependencies 2026-01-11 17:01:33 +02:00
Karim shoair 059a708b6d feat(spiders system): a prototype of the new spiders system
- A modern spider design that uses AnyIO and asyncio, yet it's very similar to Scrapy spiders API because it's the easiest design for users, and to make it easier for new users.
- Spiders can have multiple sessions per crawl, and users decide which session to use with each request.
- A scheduler system that uses heapq logic.
- The user can set the number of concurrent requests for a spider globally or per domain.
- The user can set a download delay to control the speed of the spider more.
- There's a global function that can be overridden to handle errors for all requests. (Similar to errback in scrapy).
- There's a spider argument to set the allowed domains for the spider to stay in.
- Each spider has a very detailed crawl stats that can be accessed right away from the code after the crawl finishes. Same case with scraped items.
- The whole spider as written as any other script and you just run it. No command-line arguments, and no need to run it from the terminal through the library like other known alternatives.
- Each spider has its own logger that forces sessions to use it.
- Each spider has functions to override that run before start and after close.
- There's a spider argument to set the logging level and another one to make the spider write to a log file.

- This is only the start. A lot more features are coming in the way.
2026-01-11 16:53:18 +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 aa4817f349 feat: Change logger to be flexible enough for the spiders classes 2026-01-11 03:22:20 +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 8e36962177 ops: add local Claude files to gitignore 2026-01-10 20:41:23 +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 3a360acced build: pump version up temporary 2026-01-08 01:37:47 +02:00
Karim shoair 08f3e6efad fix: add missing line 2026-01-08 01:01:00 +02:00
Karim shoair 6553d90e0f ops: update workflows to run for this branch 2026-01-08 00:53:29 +02:00
Karim shoair 9eb5f68fcb test: update tests accordingly 2026-01-08 00:52:35 +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 de79fe80bb v0.3.14 2026-01-03 22:29:20 +02:00
Karim shoair 2f87507afe test: update database test to suite windows 2026-01-03 22:02:03 +02:00
Karim shoair f99baf65f7 test: remove the check for incognito 2026-01-03 01:50:46 +02:00
Karim shoair c8a2456b81 fix(StealthyFetcher): disable incognito mode to solve #123 2026-01-03 01:50:02 +02:00