Karim shoair commited on
Commit ·
c0f5705
1
Parent(s): bbd0c34
feat(spiders): Add follow function to the response
Browse files
scrapling/core/_types.py
CHANGED
|
@@ -12,6 +12,7 @@ from typing import (
|
|
| 12 |
Callable,
|
| 13 |
Dict,
|
| 14 |
Generator,
|
|
|
|
| 15 |
Generic,
|
| 16 |
Iterable,
|
| 17 |
List,
|
|
|
|
| 12 |
Callable,
|
| 13 |
Dict,
|
| 14 |
Generator,
|
| 15 |
+
AsyncGenerator,
|
| 16 |
Generic,
|
| 17 |
Iterable,
|
| 18 |
List,
|
scrapling/engines/toolbelt/custom.py
CHANGED
|
@@ -10,12 +10,19 @@ from scrapling.core._types import (
|
|
| 10 |
Dict,
|
| 11 |
cast,
|
| 12 |
List,
|
| 13 |
-
Optional,
|
| 14 |
Tuple,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
)
|
| 16 |
from scrapling.core.custom_types import MappingProxyType
|
| 17 |
from scrapling.parser import Selector, SQLiteStorageSystem
|
| 18 |
|
|
|
|
|
|
|
|
|
|
| 19 |
|
| 20 |
class Response(Selector):
|
| 21 |
"""This class is returned by all engines as a way to unify the response type between different libraries."""
|
|
@@ -50,6 +57,52 @@ class Response(Selector):
|
|
| 50 |
# For easier debugging while working from a Python shell
|
| 51 |
log.info(f"Fetched ({status}) <{method} {url}> (referer: {request_headers.get('referer')})")
|
| 52 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
|
| 54 |
class BaseFetcher:
|
| 55 |
__slots__ = ()
|
|
|
|
| 10 |
Dict,
|
| 11 |
cast,
|
| 12 |
List,
|
|
|
|
| 13 |
Tuple,
|
| 14 |
+
Union,
|
| 15 |
+
Optional,
|
| 16 |
+
Callable,
|
| 17 |
+
TYPE_CHECKING,
|
| 18 |
+
AsyncGenerator,
|
| 19 |
)
|
| 20 |
from scrapling.core.custom_types import MappingProxyType
|
| 21 |
from scrapling.parser import Selector, SQLiteStorageSystem
|
| 22 |
|
| 23 |
+
if TYPE_CHECKING:
|
| 24 |
+
from scrapling.spiders import Request
|
| 25 |
+
|
| 26 |
|
| 27 |
class Response(Selector):
|
| 28 |
"""This class is returned by all engines as a way to unify the response type between different libraries."""
|
|
|
|
| 57 |
# For easier debugging while working from a Python shell
|
| 58 |
log.info(f"Fetched ({status}) <{method} {url}> (referer: {request_headers.get('referer')})")
|
| 59 |
|
| 60 |
+
self.meta: Dict[str, Any] = {}
|
| 61 |
+
self.request: Optional["Request"] = None # Will be set by crawler
|
| 62 |
+
|
| 63 |
+
def follow(
|
| 64 |
+
self,
|
| 65 |
+
url: str,
|
| 66 |
+
sid: str = "",
|
| 67 |
+
callback: Callable[["Response"], AsyncGenerator[Union[Dict[str, Any], "Request", None], None]] | None = None,
|
| 68 |
+
priority: int | None = None,
|
| 69 |
+
dont_filter: bool = False,
|
| 70 |
+
meta: dict[str, Any] | None = None,
|
| 71 |
+
**kwargs: Any,
|
| 72 |
+
) -> Any:
|
| 73 |
+
"""Create a Request to follow a URL.
|
| 74 |
+
|
| 75 |
+
This is a helper method for spiders to easily follow links found in pages.
|
| 76 |
+
|
| 77 |
+
**IMPORTANT**: The below arguments if left empty, the corresponding value from the previous request will be used. The only exception is `dont_filter`.
|
| 78 |
+
|
| 79 |
+
:param url: The URL to follow (can be relative, will be joined with current URL)
|
| 80 |
+
:param sid: The session id to use
|
| 81 |
+
:param callback: Spider callback method to use
|
| 82 |
+
:param priority: The priority number to use, the higher the number, the higher priority to be processed first.
|
| 83 |
+
:param dont_filter: If this request has been done before, disable the filter to allow it again.
|
| 84 |
+
:param meta: Additional meta data to included in the request
|
| 85 |
+
:param kwargs: Additional Request arguments
|
| 86 |
+
:return: Request object ready to be yielded
|
| 87 |
+
"""
|
| 88 |
+
from scrapling.spiders import Request
|
| 89 |
+
|
| 90 |
+
if not self.request or not isinstance(self.request, Request):
|
| 91 |
+
raise TypeError("This response has no request set yet.")
|
| 92 |
+
|
| 93 |
+
return Request(
|
| 94 |
+
url=self.urljoin(url),
|
| 95 |
+
sid=sid or self.request.sid,
|
| 96 |
+
callback=callback or self.request.callback,
|
| 97 |
+
priority=priority if priority is not None else self.request.priority,
|
| 98 |
+
dont_filter=dont_filter,
|
| 99 |
+
meta={**(self.meta or {}), **(meta or {})},
|
| 100 |
+
**(kwargs if kwargs else self.request._session_kwargs),
|
| 101 |
+
)
|
| 102 |
+
|
| 103 |
+
def __str__(self) -> str:
|
| 104 |
+
return f"<{self.status} {self.url}>"
|
| 105 |
+
|
| 106 |
|
| 107 |
class BaseFetcher:
|
| 108 |
__slots__ = ()
|