Skip to content

Commit c5555fb

Browse files
author
Thordata
committed
feat(serp): add typed SERP requests, engine-specific mappings and integration smoke tests
1 parent cb6a712 commit c5555fb

File tree

6 files changed

+770
-26
lines changed

6 files changed

+770
-26
lines changed

src/thordata/async_client.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
ProxyUserList,
7676
ScraperTaskConfig,
7777
SerpRequest,
78+
SerpTypedRequest,
7879
UniversalScrapeRequest,
7980
UsageStatistics,
8081
VideoTaskConfig,
@@ -275,29 +276,53 @@ async def serp_search(
275276
*,
276277
engine: Engine | str = Engine.GOOGLE,
277278
num: int = 10,
279+
start: int = 0,
278280
country: str | None = None,
279281
language: str | None = None,
282+
google_domain: str | None = None,
283+
countries_filter: str | None = None,
284+
languages_filter: str | None = None,
285+
location: str | None = None,
286+
uule: str | None = None,
280287
search_type: str | None = None,
288+
safe_search: bool | None = None,
289+
time_filter: str | None = None,
290+
no_autocorrect: bool = False,
291+
filter_duplicates: bool | None = None,
281292
device: str | None = None,
282293
render_js: bool | None = None,
283294
no_cache: bool | None = None,
284295
output_format: str = "json",
285296
ai_overview: bool = False,
297+
ludocid: str | None = None,
298+
kgmid: str | None = None,
286299
**kwargs: Any,
287300
) -> dict[str, Any]:
288301
engine_str = engine.value if isinstance(engine, Engine) else engine.lower()
289302
request = SerpRequest(
290303
query=query,
291304
engine=engine_str,
292305
num=num,
306+
start=start,
293307
country=country,
294308
language=language,
309+
google_domain=google_domain,
310+
countries_filter=countries_filter,
311+
languages_filter=languages_filter,
312+
location=location,
313+
uule=uule,
295314
search_type=search_type,
315+
safe_search=safe_search,
316+
time_filter=time_filter,
317+
no_autocorrect=no_autocorrect,
318+
filter_duplicates=filter_duplicates,
296319
device=device,
297320
render_js=render_js,
298321
no_cache=no_cache,
299322
output_format=output_format,
300323
ai_overview=ai_overview,
324+
ludocid=ludocid,
325+
kgmid=kgmid,
301326
extra_params=kwargs,
302327
)
303328
return await self.serp_search_advanced(request)
@@ -328,6 +353,12 @@ async def serp_search_advanced(self, request: SerpRequest) -> dict[str, Any]:
328353
text = await response.text()
329354
return {"html": text}
330355

356+
async def serp_search_typed(self, request: SerpTypedRequest) -> dict[str, Any]:
357+
"""
358+
Execute a strongly-typed SERP request (async).
359+
"""
360+
return await self.serp_search_advanced(request.to_serp_request())
361+
331362
async def serp_batch_search(
332363
self,
333364
requests: list[SerpRequest | dict[str, Any]],

src/thordata/client.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
ProxyUserList,
9090
ScraperTaskConfig,
9191
SerpRequest,
92+
SerpTypedRequest,
9293
UniversalScrapeRequest,
9394
UsageStatistics,
9495
VideoTaskConfig,
@@ -301,14 +302,26 @@ def serp_search(
301302
*,
302303
engine: Engine | str = Engine.GOOGLE,
303304
num: int = 10,
305+
start: int = 0,
304306
country: str | None = None,
305307
language: str | None = None,
308+
google_domain: str | None = None,
309+
countries_filter: str | None = None,
310+
languages_filter: str | None = None,
311+
location: str | None = None,
312+
uule: str | None = None,
306313
search_type: str | None = None,
314+
safe_search: bool | None = None,
315+
time_filter: str | None = None,
316+
no_autocorrect: bool = False,
317+
filter_duplicates: bool | None = None,
307318
device: str | None = None,
308319
render_js: bool | None = None,
309320
no_cache: bool | None = None,
310321
output_format: str = "json",
311322
ai_overview: bool = False,
323+
ludocid: str | None = None,
324+
kgmid: str | None = None,
312325
**kwargs: Any,
313326
) -> dict[str, Any]:
314327
engine_str = engine.value if isinstance(engine, Engine) else engine.lower()
@@ -317,14 +330,26 @@ def serp_search(
317330
query=query,
318331
engine=engine_str,
319332
num=num,
333+
start=start,
320334
country=country,
321335
language=language,
336+
google_domain=google_domain,
337+
countries_filter=countries_filter,
338+
languages_filter=languages_filter,
339+
location=location,
340+
uule=uule,
322341
search_type=search_type,
342+
safe_search=safe_search,
343+
time_filter=time_filter,
344+
no_autocorrect=no_autocorrect,
345+
filter_duplicates=filter_duplicates,
323346
device=device,
324347
render_js=render_js,
325348
no_cache=no_cache,
326349
output_format=output_format,
327350
ai_overview=ai_overview,
351+
ludocid=ludocid,
352+
kgmid=kgmid,
328353
extra_params=kwargs,
329354
)
330355
return self.serp_search_advanced(request)
@@ -363,6 +388,15 @@ def serp_search_advanced(self, request: SerpRequest) -> dict[str, Any]:
363388

364389
return {"html": response.text}
365390

391+
def serp_search_typed(self, request: SerpTypedRequest) -> dict[str, Any]:
392+
"""
393+
Execute a strongly-typed SERP request.
394+
395+
This keeps the SDK minimal while offering better DX for engine/mode-specific
396+
required parameters with upfront validation.
397+
"""
398+
return self.serp_search_advanced(request.to_serp_request())
399+
366400
def serp_batch_search(
367401
self,
368402
requests: list[SerpRequest | dict[str, Any]],

0 commit comments

Comments
 (0)