This commit is contained in:
Karim shoair
2025-12-03 03:52:52 +02:00
committed by GitHub
6 changed files with 11 additions and 16 deletions
+2 -2
View File
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "scrapling" name = "scrapling"
# Static version instead of a dynamic version so we can get better layer caching while building docker, check the docker file to understand # Static version instead of a dynamic version so we can get better layer caching while building docker, check the docker file to understand
version = "0.3.10" version = "0.3.11"
description = "Scrapling is an undetectable, powerful, flexible, high-performance Python library that makes Web Scraping easy and effortless as it should be!" description = "Scrapling is an undetectable, powerful, flexible, high-performance Python library that makes Web Scraping easy and effortless as it should be!"
readme = {file = "docs/README.md", content-type = "text/markdown"} readme = {file = "docs/README.md", content-type = "text/markdown"}
license = {file = "LICENSE"} license = {file = "LICENSE"}
@@ -74,7 +74,7 @@ fetchers = [
"msgspec>=0.20.0", "msgspec>=0.20.0",
] ]
ai = [ ai = [
"mcp>=1.19.0", "mcp>=1.23.0",
"markdownify>=1.2.0", "markdownify>=1.2.0",
"scrapling[fetchers]", "scrapling[fetchers]",
] ]
+1 -1
View File
@@ -1,5 +1,5 @@
__author__ = "Karim Shoair (karim.shoair@pm.me)" __author__ = "Karim Shoair (karim.shoair@pm.me)"
__version__ = "0.3.10" __version__ = "0.3.11"
__copyright__ = "Copyright (c) 2024 Karim Shoair" __copyright__ = "Copyright (c) 2024 Karim Shoair"
from typing import Any, TYPE_CHECKING from typing import Any, TYPE_CHECKING
+5 -5
View File
@@ -314,7 +314,7 @@ class CurlParser:
return None return None
def _unpack_signature(func): def _unpack_signature(func, signature_name=None):
""" """
Unpack TypedDict from Unpack[TypedDict] annotations in **kwargs and reconstruct the signature. Unpack TypedDict from Unpack[TypedDict] annotations in **kwargs and reconstruct the signature.
@@ -322,7 +322,7 @@ def _unpack_signature(func):
""" """
try: try:
sig = signature(func) sig = signature(func)
func_name = getattr(func, "__name__", None) func_name = signature_name or getattr(func, "__name__", None)
# Check if this function has known parameters # Check if this function has known parameters
if func_name not in Signatures_map: if func_name not in Signatures_map:
@@ -467,7 +467,7 @@ Type 'exit' or press Ctrl+D to exit.
return result return result
def create_wrapper(self, func, get_signature=True): def create_wrapper(self, func, get_signature=True, signature_name=None):
"""Create a wrapper that preserves function signature but updates page""" """Create a wrapper that preserves function signature but updates page"""
@wraps(func) @wraps(func)
@@ -477,7 +477,7 @@ Type 'exit' or press Ctrl+D to exit.
if get_signature: if get_signature:
# Explicitly preserve and unpack signature for IPython introspection and autocompletion # Explicitly preserve and unpack signature for IPython introspection and autocompletion
wrapper.__signature__ = _unpack_signature(func) # pyright: ignore wrapper.__signature__ = _unpack_signature(func, signature_name) # pyright: ignore
else: else:
wrapper.__signature__ = signature(func) # pyright: ignore wrapper.__signature__ = signature(func) # pyright: ignore
@@ -492,7 +492,7 @@ Type 'exit' or press Ctrl+D to exit.
put = self.create_wrapper(self.__Fetcher.put) put = self.create_wrapper(self.__Fetcher.put)
delete = self.create_wrapper(self.__Fetcher.delete) delete = self.create_wrapper(self.__Fetcher.delete)
dynamic_fetch = self.create_wrapper(self.__DynamicFetcher.fetch) dynamic_fetch = self.create_wrapper(self.__DynamicFetcher.fetch)
stealthy_fetch = self.create_wrapper(self.__StealthyFetcher.fetch) stealthy_fetch = self.create_wrapper(self.__StealthyFetcher.fetch, signature_name="stealthy_fetch")
curl2fetcher = self.create_wrapper(self._curl_parser.convert2fetcher, get_signature=False) curl2fetcher = self.create_wrapper(self._curl_parser.convert2fetcher, get_signature=False)
# Create the namespace dictionary # Create the namespace dictionary
+2 -2
View File
@@ -105,7 +105,7 @@ class SyncSession:
"""Wait for the page to become idle (no network activity) even if there are never-ending requests.""" """Wait for the page to become idle (no network activity) even if there are never-ending requests."""
try: try:
page.wait_for_load_state("networkidle", timeout=timeout) page.wait_for_load_state("networkidle", timeout=timeout)
except PlaywrightError: except (PlaywrightError, Exception):
pass pass
def _wait_for_page_stability(self, page: Page | Frame, load_dom: bool, network_idle: bool): def _wait_for_page_stability(self, page: Page | Frame, load_dom: bool, network_idle: bool):
@@ -221,7 +221,7 @@ class AsyncSession:
"""Wait for the page to become idle (no network activity) even if there are never-ending requests.""" """Wait for the page to become idle (no network activity) even if there are never-ending requests."""
try: try:
await page.wait_for_load_state("networkidle", timeout=timeout) await page.wait_for_load_state("networkidle", timeout=timeout)
except PlaywrightError: except (PlaywrightError, Exception):
pass pass
async def _wait_for_page_stability(self, page: AsyncPage | AsyncFrame, load_dom: bool, network_idle: bool): async def _wait_for_page_stability(self, page: AsyncPage | AsyncFrame, load_dom: bool, network_idle: bool):
+1 -1
View File
@@ -1,6 +1,6 @@
[metadata] [metadata]
name = scrapling name = scrapling
version = 0.3.10 version = 0.3.11
author = Karim Shoair author = Karim Shoair
author_email = karim.shoair@pm.me author_email = karim.shoair@pm.me
description = Scrapling is an undetectable, powerful, flexible, high-performance Python library that makes Web Scraping easy and effortless as it should be! description = Scrapling is an undetectable, powerful, flexible, high-performance Python library that makes Web Scraping easy and effortless as it should be!
-5
View File
@@ -15,11 +15,6 @@ deps =
camoufox camoufox
-r{toxinidir}/tests/requirements.txt -r{toxinidir}/tests/requirements.txt
extras = ai,shell extras = ai,shell
commands_pre =
# Install browsers in the tox virtual environment
python -m playwright install chromium
python -m playwright install-deps chromium firefox
python -m camoufox fetch --browserforge
commands = commands =
# Run browser tests without parallelization (avoid browser conflicts) # Run browser tests without parallelization (avoid browser conflicts)
pytest --cov=scrapling --cov-report=xml -k "DynamicFetcher or StealthyFetcher" --verbose pytest --cov=scrapling --cov-report=xml -k "DynamicFetcher or StealthyFetcher" --verbose