scrapely-python 0.1.32__py3-none-any.whl → 0.1.33__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
scrapely/__init__.py CHANGED
@@ -227,7 +227,7 @@ if TYPE_CHECKING: # Static analysers and IDEs see the lazy names as plain impor
227
227
  set_api_storage,
228
228
  )
229
229
 
230
- __version__ = '0.1.32'
230
+ __version__ = '0.1.33'
231
231
  __all__ = [
232
232
  # Core
233
233
  'Actor',
scrapely/actor.py CHANGED
@@ -925,7 +925,14 @@ class Actor(metaclass=_ActorMeta):
925
925
 
926
926
  # Debug capture: raw source payloads for platform diagnostics. Only active when the platform
927
927
  # sets SCRAPELY_DEBUG_CAPTURE=1 on its own diagnostic runs; a no-op in every other run.
928
+ # A payload up to _DEBUG_CAPTURE_MAX_BYTES characters is stored as it is; a larger one gzip-compressed
929
+ # (base64, at most _DEBUG_CAPTURE_MAX_BYTES characters again), keeping up to _DEBUG_CAPTURE_MAX_CHARS
930
+ # characters / _DEBUG_CAPTURE_MAX_ENCODED bytes of it. A plain cut at 256 KiB lost the part a check
931
+ # needed when a large API document starts with site navigation (the seller section of a 581 KB
932
+ # listing JSON sat at ~333 KB).
928
933
  _DEBUG_CAPTURE_MAX_BYTES = 256 * 1024
934
+ _DEBUG_CAPTURE_MAX_CHARS = 8 * 1024 * 1024
935
+ _DEBUG_CAPTURE_MAX_ENCODED = 8 * 1024 * 1024
929
936
  _DEBUG_CAPTURE_MAX_RECORDS = 500
930
937
  _debug_capture_count = 0
931
938
 
@@ -967,15 +974,33 @@ class Actor(metaclass=_ActorMeta):
967
974
  if cls._debug_capture_count >= cls._DEBUG_CAPTURE_MAX_RECORDS:
968
975
  return
969
976
  try:
970
- text = payload if isinstance(payload, str) else json.dumps(payload, default=str, ensure_ascii=False)
971
- if isinstance(text, bytes):
972
- text = text.decode('utf-8', 'replace')
973
- text = text[: cls._DEBUG_CAPTURE_MAX_BYTES]
977
+ if isinstance(payload, (bytes, bytearray)):
978
+ text = bytes(payload).decode('utf-8', 'replace')
979
+ elif isinstance(payload, str):
980
+ text = payload
981
+ else:
982
+ text = json.dumps(payload, default=str, ensure_ascii=False, separators=(',', ':'))
983
+ record = cls._debug_capture_record(str(key), text)
974
984
  cls._debug_capture_count += 1
975
- await cls.set_value(cls.debug_capture_record_key(key), {'key': str(key), 'payload': text})
985
+ await cls.set_value(cls.debug_capture_record_key(key), record)
976
986
  except Exception as err: # never break the run
977
987
  logging.getLogger('scrapely').debug('debug_capture failed: %s', err)
978
988
 
989
+ @classmethod
990
+ def _debug_capture_record(cls, key: str, text: str) -> Dict[str, Any]:
991
+ """The record for one capture: plain when small, else gzip-base64 (plain head as the last resort)."""
992
+ limit = cls._DEBUG_CAPTURE_MAX_BYTES
993
+ if len(text) <= limit:
994
+ return {'key': key, 'payload': text}
995
+ import gzip
996
+ raw = text[: cls._DEBUG_CAPTURE_MAX_CHARS].encode('utf-8')
997
+ kept = raw[: cls._DEBUG_CAPTURE_MAX_ENCODED]
998
+ packed = base64.b64encode(gzip.compress(kept, 6)).decode('ascii')
999
+ if len(packed) <= limit:
1000
+ truncated = len(text) > cls._DEBUG_CAPTURE_MAX_CHARS or len(kept) < len(raw)
1001
+ return {'key': key, 'payload': packed, 'encoding': 'gzip-base64', 'length': len(text), 'truncated': truncated}
1002
+ return {'key': key, 'payload': text[:limit], 'length': len(text), 'truncated': True}
1003
+
979
1004
  @classmethod
980
1005
  def _resolve_open_args(
981
1006
  cls,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scrapely-python
3
- Version: 0.1.32
3
+ Version: 0.1.33
4
4
  Summary: Scrapely Python SDK - A toolkit for building Actors on the Scrapely platform
5
5
  Author-email: Scrapely <support@scrape.ly>
6
6
  License-Expression: MIT AND Apache-2.0
@@ -1,6 +1,6 @@
1
- scrapely/__init__.py,sha256=10DwJc_P2SptqSlrJGlBxK_Tfp70RpDIf1Tuv0NVO5Q,9668
1
+ scrapely/__init__.py,sha256=IewlIO5DRdcqs_defs-pLoIJ_u78Vb7J7Ix0uMhV-ds,9668
2
2
  scrapely/_browser_locations.py,sha256=8QVVnkms2bDn3_LDYgYDR59MvFx8757l_JYnZ7xb3oI,145269
3
- scrapely/actor.py,sha256=mq5kchL3EIm_E1Y4uxj5UnzgUVJ7Gze33YXJNTOhUng,87611
3
+ scrapely/actor.py,sha256=mnQ0zYCsRJEAipxH1Sdg6o6_r2gEAvnuA1r5M3AsEgo,89122
4
4
  scrapely/browser_configuration.py,sha256=jAZapNSHLFW05B96df4wNBtcyiiU9DA3ml0yTL1FwfA,5770
5
5
  scrapely/cdp_retry.py,sha256=hdTJEAIKhApM7IOk1DrQEl8NoflSJSmqd4RbNJ2IsgI,8540
6
6
  scrapely/charging.py,sha256=osi2Ys99IyIJwFj0eRtV_RshokPs4mA2CE7oftNbN58,95559
@@ -55,10 +55,10 @@ scrapely/storage/_file_system/_key_value_store_client.py,sha256=1C22qY-RWlARzMyW
55
55
  scrapely/storage/_file_system/_storage_client.py,sha256=QHa3IULEb6AmgRFwpBqHD2OUTmtA_gl3lId-j6QdSFo,2027
56
56
  scrapely/storage_clients/__init__.py,sha256=q2pC-Rwe-BfHl018OyN_P0EDSx4-hNdxbk3pOCLLd4U,618
57
57
  scrapely/storages/__init__.py,sha256=kDNtd9VodjdHd4u7GzruJo0aB2HeiBN2_-HrkeqjmFg,139
58
- scrapely_python-0.1.32.dist-info/licenses/LICENSE,sha256=pQGY0XwjIYh-a2HfawxHq1en53bXkFkDj2Q70jKWHr4,1088
59
- scrapely_python-0.1.32.dist-info/licenses/LICENSE-APACHE,sha256=N8m0FzMq8i4UbTgXZvKEZJSD-27OF8pWZYS_atz4kTU,11355
60
- scrapely_python-0.1.32.dist-info/licenses/NOTICE,sha256=1ltrzKk2ez7x2BPNpXeyvOlTty5AfABYDBlwNilpORk,788
61
- scrapely_python-0.1.32.dist-info/METADATA,sha256=YyH8wpWXWABQFwdL1I4o5HEB1OQbqiPGPPguoQ-a4mQ,3582
62
- scrapely_python-0.1.32.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
63
- scrapely_python-0.1.32.dist-info/top_level.txt,sha256=T4B9UMrs4q99QSAFyD1zdXhl40KnLhBKqrDkPhOTsmY,9
64
- scrapely_python-0.1.32.dist-info/RECORD,,
58
+ scrapely_python-0.1.33.dist-info/licenses/LICENSE,sha256=pQGY0XwjIYh-a2HfawxHq1en53bXkFkDj2Q70jKWHr4,1088
59
+ scrapely_python-0.1.33.dist-info/licenses/LICENSE-APACHE,sha256=N8m0FzMq8i4UbTgXZvKEZJSD-27OF8pWZYS_atz4kTU,11355
60
+ scrapely_python-0.1.33.dist-info/licenses/NOTICE,sha256=1ltrzKk2ez7x2BPNpXeyvOlTty5AfABYDBlwNilpORk,788
61
+ scrapely_python-0.1.33.dist-info/METADATA,sha256=hhDlcnp5JyIcT9C_-kawPgmqmGanpQgX3TJJqcCQl7s,3582
62
+ scrapely_python-0.1.33.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
63
+ scrapely_python-0.1.33.dist-info/top_level.txt,sha256=T4B9UMrs4q99QSAFyD1zdXhl40KnLhBKqrDkPhOTsmY,9
64
+ scrapely_python-0.1.33.dist-info/RECORD,,