mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-07-22 23:31:12 +02:00
refactor: implement cross-country proxy rotation for Reddit and TikTok scrapers, enhancing resilience against IP blocks and improving search query handling
This commit is contained in:
parent
c0ebb62fb2
commit
8a5d37a4db
10 changed files with 213 additions and 22 deletions
|
|
@ -266,3 +266,7 @@ async def test_fan_out_closes_all_sessions_on_early_stop(monkeypatch):
|
|||
async def test_fan_out_empty_jobs_is_noop():
|
||||
out = [x async for x in scraper.fan_out([])]
|
||||
assert out == []
|
||||
|
||||
|
||||
# Cross-country rotation lives in app.utils.proxy.rotation and is shared with the
|
||||
# TikTok sibling; its unit tests live in tests/unit/utils/proxy/test_rotation.py.
|
||||
|
|
|
|||
|
|
@ -169,6 +169,37 @@ async def test_listing_dedupes_then_caps_per_target():
|
|||
assert [i["id"] for i in items] == ["1", "2"]
|
||||
|
||||
|
||||
async def test_search_query_resolves_to_listing_target():
|
||||
# searchQueries must produce a search target (not be silently dropped): a
|
||||
# query with results flows through the listing parse/dedupe/cap path.
|
||||
async def fake_listing(url: str, _count: int) -> list[dict]:
|
||||
assert "search?q=meal%20prep" in url # query wired into the search URL
|
||||
return [{"id": "1", "author": {"uniqueId": "a"}}]
|
||||
|
||||
items = await scrape_tiktok(
|
||||
TikTokScrapeInput(searchQueries=["meal prep"], resultsPerPage=5),
|
||||
fetch=_no_html,
|
||||
fetch_listing=fake_listing,
|
||||
)
|
||||
assert [i["id"] for i in items] == ["1"]
|
||||
|
||||
|
||||
async def test_empty_search_query_degrades_to_error_item():
|
||||
# A withheld anonymous search feed must surface one honest ErrorItem tagged
|
||||
# with the query, never a silent empty.
|
||||
async def fake_listing(_url: str, _count: int) -> list[dict]:
|
||||
return []
|
||||
|
||||
items = await scrape_tiktok(
|
||||
TikTokScrapeInput(searchQueries=["meal prep"], resultsPerPage=5),
|
||||
fetch=_no_html,
|
||||
fetch_listing=fake_listing,
|
||||
)
|
||||
assert len(items) == 1
|
||||
assert items[0]["errorCode"] == "no_items"
|
||||
assert items[0]["input"] == "meal prep"
|
||||
|
||||
|
||||
async def test_empty_listing_emits_error_item():
|
||||
# A trust-gated/empty feed (0 videos) must surface one honest ErrorItem,
|
||||
# tagged with errorCode, rather than vanishing silently.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue