Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export SCRAPEBADGER_API_KEY="sb_live_xxxxxxxxxxxxx"
| **eBay** | 12 endpoints across 18 markets — search, completed/sold search, item detail, item reviews, seller profile/items/feedback, category browse, categories, autocomplete, markets | [eBay Guide](docs/ebay.md) |
| **YouTube** | 39 endpoints — search, autocomplete, video detail/related/comments/replies/transcript/captions/streams/live-chat/batch, channel detail + videos/shorts/streams/playlists/community/about/subscriber-count/in-channel-search/resolve, playlists/items/mixes, trending/hashtag/home, shorts, community post/comments, music search, oembed, categories/languages/regions | [YouTube Guide](docs/youtube.md) |
| **TikTok** | 25 endpoints — user profile/videos/followers/following/liked/reposts, video detail/comments/replies/related/transcript/oEmbed, search (general/videos/hashtags/users), music detail/videos, hashtag detail/videos, trending videos/hashtags/songs, ad library, regions | [TikTok Guide](docs/tiktok.md) |
| **Immobiliare** | 8 endpoints across immobiliare.it, indomio.es, indomio.gr, immotop.lu — autocomplete, search, listing detail, agency profile/listings, price stats, markets, reference | [Immobiliare Guide](docs/immobiliare.md) |

## Error Handling

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "scrapebadger"
version = "0.15.7"
version = "0.16.0"
description = "Official Python SDK for ScrapeBadger - Async web scraping APIs for Twitter and more"
readme = "README.md"
license = { text = "MIT" }
Expand Down
81 changes: 80 additions & 1 deletion src/scrapebadger/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,64 @@ async def main():
SellerProfileResponse as EbaySellerProfileResponse,
)
from scrapebadger.google.client import GoogleClient
from scrapebadger.immobiliare.client import ImmobiliareClient
from scrapebadger.immobiliare.models import (
Agency as ImmobiliareAgency,
)
from scrapebadger.immobiliare.models import (
AgencyAgent as ImmobiliareAgencyAgent,
)
from scrapebadger.immobiliare.models import (
AgencyListingsResponse as ImmobiliareAgencyListingsResponse,
)
from scrapebadger.immobiliare.models import (
AgencyProfile as ImmobiliareAgencyProfile,
)
from scrapebadger.immobiliare.models import (
Agent as ImmobiliareAgent,
)
from scrapebadger.immobiliare.models import (
Feature as ImmobiliareFeature,
)
from scrapebadger.immobiliare.models import (
Listing as ImmobiliareListing,
)
from scrapebadger.immobiliare.models import (
Location as ImmobiliareLocation,
)
from scrapebadger.immobiliare.models import (
Market as ImmobiliareMarket,
)
from scrapebadger.immobiliare.models import (
Photo as ImmobiliarePhoto,
)
from scrapebadger.immobiliare.models import (
Price as ImmobiliarePrice,
)
from scrapebadger.immobiliare.models import (
PriceStatsPoint as ImmobiliarePriceStatsPoint,
)
from scrapebadger.immobiliare.models import (
PriceStatsResponse as ImmobiliarePriceStatsResponse,
)
from scrapebadger.immobiliare.models import (
PropertyUnit as ImmobiliarePropertyUnit,
)
from scrapebadger.immobiliare.models import (
ReferenceResponse as ImmobiliareReferenceResponse,
)
from scrapebadger.immobiliare.models import (
RelatedSearch as ImmobiliareRelatedSearch,
)
from scrapebadger.immobiliare.models import (
SearchResponse as ImmobiliareSearchResponse,
)
from scrapebadger.immobiliare.models import (
Suggestion as ImmobiliareSuggestion,
)
from scrapebadger.immobiliare.models import (
SuggestResponse as ImmobiliareSuggestResponse,
)
from scrapebadger.leboncoin.client import LeboncoinClient
from scrapebadger.leboncoin.models import (
Ad as LeboncoinAd,
Expand Down Expand Up @@ -639,7 +697,7 @@ async def main():
ZestimateHistoryPoint as ZillowZestimateHistoryPoint,
)

__version__ = "0.15.7"
__version__ = "0.16.0"

__all__ = [
# TikTok core models
Expand Down Expand Up @@ -698,6 +756,27 @@ async def main():
"FeedbackBreakdown",
# Google Scraper
"GoogleClient",
# Immobiliare
"ImmobiliareAgency",
"ImmobiliareAgencyAgent",
"ImmobiliareAgencyListingsResponse",
"ImmobiliareAgencyProfile",
"ImmobiliareAgent",
"ImmobiliareClient",
"ImmobiliareFeature",
"ImmobiliareListing",
"ImmobiliareLocation",
"ImmobiliareMarket",
"ImmobiliarePhoto",
"ImmobiliarePrice",
"ImmobiliarePriceStatsPoint",
"ImmobiliarePriceStatsResponse",
"ImmobiliarePropertyUnit",
"ImmobiliareReferenceResponse",
"ImmobiliareRelatedSearch",
"ImmobiliareSearchResponse",
"ImmobiliareSuggestResponse",
"ImmobiliareSuggestion",
"InsufficientCreditsError",
"ItemDetailResponse",
# Leboncoin
Expand Down
5 changes: 3 additions & 2 deletions src/scrapebadger/_internal/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
T = TypeVar("T")

# User agent for SDK requests
SDK_VERSION = "0.15.6"
SDK_VERSION = "0.16.0"
USER_AGENT = f"scrapebadger-python/{SDK_VERSION}"


Expand Down Expand Up @@ -254,7 +254,8 @@ async def _request_with_retry(
self._handle_error_response(response, data)

# Check for application-level errors in response
if data.get("error"):
# (bare JSON array bodies, e.g. /markets, have no .get)
if isinstance(data, dict) and data.get("error"):
raise ScrapeBadgerError(
data["error"],
response.status_code,
Expand Down
24 changes: 24 additions & 0 deletions src/scrapebadger/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from scrapebadger.amazon.client import AmazonClient
from scrapebadger.ebay.client import EbayClient
from scrapebadger.google.client import GoogleClient
from scrapebadger.immobiliare.client import ImmobiliareClient
from scrapebadger.leboncoin.client import LeboncoinClient
from scrapebadger.realtor.client import RealtorClient
from scrapebadger.reddit.client import RedditClient
Expand Down Expand Up @@ -130,6 +131,7 @@ def __init__(
self._realtor: RealtorClient | None = None
self._zillow: ZillowClient | None = None
self._leboncoin: LeboncoinClient | None = None
self._immobiliare: ImmobiliareClient | None = None

@property
def config(self) -> ClientConfig:
Expand Down Expand Up @@ -381,6 +383,28 @@ def leboncoin(self) -> LeboncoinClient:
self._leboncoin = LeboncoinClient(self._base_client)
return self._leboncoin

@property
def immobiliare(self) -> ImmobiliareClient:
"""Access Immobiliare Scraper API operations.

Returns:
ImmobiliareClient providing access to all Immobiliare-group
endpoints (autocomplete, search, listing detail, agency
profile/listings, price stats, markets, reference) across
immobiliare.it, indomio.es, indomio.gr, and immotop.lu.

Example:
```python
hits = await client.immobiliare.autocomplete("Milano")
results = await client.immobiliare.search(location="Milano")
detail = await client.immobiliare.get_listing(123456789)
markets = await client.immobiliare.list_markets()
```
"""
if self._immobiliare is None:
self._immobiliare = ImmobiliareClient(self._base_client)
return self._immobiliare

@property
def tiktok(self) -> TikTokClient:
"""Access TikTok Scraper API operations.
Expand Down
74 changes: 74 additions & 0 deletions src/scrapebadger/immobiliare/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""Immobiliare API module for ScrapeBadger SDK.

This module provides an async client for scraping Immobiliare-group
real-estate data (immobiliare.it, indomio.es, indomio.gr, immotop.lu) through
the ScrapeBadger API. Endpoints: autocomplete, search, listing detail, agency
profile + listings, price stats (€/m² time series), markets, and reference.
All methods are async and return strongly-typed Pydantic models.

Example:
```python
from scrapebadger import ScrapeBadger

async with ScrapeBadger(api_key="your-key") as client:
# Resolve a place, then search it
hits = await client.immobiliare.autocomplete("Milano")
city = hits.suggestions[0]
results = await client.immobiliare.search(city_id=city.city_id, price_max=500000)
for listing in results.listings:
print(f"{listing.id}: {listing.title}")

# Full listing detail
detail = await client.immobiliare.get_listing(123456789)
print(detail.description)
```
"""

from scrapebadger.immobiliare.client import ImmobiliareClient
from scrapebadger.immobiliare.models import (
Agency,
AgencyAgent,
AgencyListingsResponse,
AgencyProfile,
Agent,
Feature,
Listing,
Location,
Market,
Photo,
Price,
PriceStatsPoint,
PriceStatsResponse,
PropertyUnit,
ReferenceResponse,
RelatedSearch,
SearchResponse,
Suggestion,
SuggestResponse,
)

__all__ = [
# Shared / nested models
"Agency",
"AgencyAgent",
# Response envelopes
"AgencyListingsResponse",
"AgencyProfile",
"Agent",
"Feature",
# Client
"ImmobiliareClient",
"Listing",
"Location",
"Market",
"Photo",
"Price",
"PriceStatsPoint",
"PriceStatsResponse",
"PropertyUnit",
"ReferenceResponse",
"RelatedSearch",
"SearchResponse",
"SuggestResponse",
"Suggestion",
]
Loading
Loading