Metadata-Version: 2.4
Name: shopscout
Version: 0.2.0
Summary: Scrape any Shopify store - products, collections, pages, metadata & reviews from the public JSON API. SDK + CLI + REST API.
Project-URL: Homepage, https://github.com/zaidkx37/shopscout
Project-URL: Repository, https://github.com/zaidkx37/shopscout
Project-URL: Issues, https://github.com/zaidkx37/shopscout/issues
Author: Muhammad Zaid
License-Expression: MIT
License-File: LICENSE
Keywords: cli,collections,ecommerce,no-api-key,products,rest-api,scraper,sdk,shopify,shopify-api,shopify-scraper,store
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: beautifulsoup4>=4.12
Requires-Dist: requests>=2.28.0
Provides-Extra: all
Requires-Dist: click>=8.0; extra == 'all'
Requires-Dist: fastapi>=0.100.0; extra == 'all'
Requires-Dist: rich>=13.0; extra == 'all'
Requires-Dist: uvicorn[standard]>=0.20.0; extra == 'all'
Provides-Extra: api
Requires-Dist: fastapi>=0.100.0; extra == 'api'
Requires-Dist: uvicorn[standard]>=0.20.0; extra == 'api'
Provides-Extra: cli
Requires-Dist: click>=8.0; extra == 'cli'
Requires-Dist: rich>=13.0; extra == 'cli'
Provides-Extra: dev
Requires-Dist: mypy>=1.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Requires-Dist: types-requests>=2.28.0; extra == 'dev'
Description-Content-Type: text/markdown

<h1 align="center">shopscout</h1>

<p align="center">
  <a href="https://pypi.org/project/shopscout/"><img src="https://img.shields.io/pypi/v/shopscout" alt="PyPI"></a>
  <a href="https://pypi.org/project/shopscout/"><img src="https://img.shields.io/pypi/pyversions/shopscout" alt="Python"></a>
  <a href="https://github.com/zaidkx37/shopscout/blob/main/LICENSE"><img src="https://img.shields.io/github/license/zaidkx37/shopscout" alt="License"></a>
  <a href="https://pypi.org/project/shopscout/"><img src="https://img.shields.io/pypi/dm/shopscout" alt="Downloads"></a>
</p>

Scrape any Shopify store - products, collections, pages & metadata from the public JSON API. No API key required.

**Three interfaces:** Python SDK, CLI, and REST API.

## Installation

```bash
# Core SDK only
pip install shopscout

# With CLI (click + rich tables)
pip install shopscout[cli]

# With REST API (FastAPI + uvicorn)
pip install shopscout[api]

# Everything
pip install shopscout[all]
```

## Quick Start

```python
from shopscout import Shopify

shop = Shopify('spharetech.com')

# Store metadata
store = shop.store()
print(store.name, store.currency)

# All products (auto-paginated)
products = shop.products()
for p in products:
    print(p.title, p.price, p.available)

# All collections
collections = shop.collections()
for c in collections:
    print(c.title, c.products_count)

# Products in a specific collection
power_banks = shop.collection_products('power-banks')

# Single product
product = shop.product('66w-transparent-power-bank-20000mah')

# Pages
pages = shop.pages()
```

## Pagination

Fetch everything at once or paginate manually — your choice.

```python
shop = Shopify('spharetech.com')

# Auto-paginate: fetches ALL products in one call
all_products = shop.products()

# Manual pagination: fetch one page at a time
page1 = shop.products_page(page=1, limit=30)
page2 = shop.products_page(page=2, limit=30)

# Same for collection products
all_power_banks = shop.collection_products('power-banks')
first_page = shop.collection_products_page('power-banks', page=1, limit=10)
```

## Exporting

```python
from shopscout import Exporter, Shopify

shop = Shopify('spharetech.com')
products = shop.products()

exporter = Exporter(output_dir='output')
exporter.products_to_json(products)
exporter.products_to_csv(products)
```

## Proxy Support

```python
shop = Shopify('store.com', proxy='http://user:pass@host:port')
```

## CLI

```bash
# Scrape products
shopscout products spharetech.com
shopscout products spharetech.com --collection power-banks
shopscout products spharetech.com --json
shopscout products spharetech.com --save products.csv

# Scrape collections
shopscout collections spharetech.com

# Store metadata
shopscout store spharetech.com

# With proxy
shopscout --proxy http://host:port products spharetech.com
```

## REST API

```bash
# Start the API server
shopscout serve
shopscout serve --port 3000
```

### Endpoints

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/v1/products?domain=store.com` | All products |
| GET | `/api/v1/products?domain=store.com&collection=power-banks` | Collection products |
| GET | `/api/v1/products/{handle}?domain=store.com` | Single product |
| GET | `/api/v1/collections?domain=store.com` | All collections |
| GET | `/api/v1/store?domain=store.com` | Store metadata |
| GET | `/api/v1/pages?domain=store.com` | All pages |
| GET | `/health` | Health check |

Interactive docs at `http://localhost:8000/docs`

## Error Handling

```python
from shopscout import Shopify, StoreNotFoundError, ProductNotFoundError

shop = Shopify('not-a-shopify-store.com')
try:
    store = shop.store()
except StoreNotFoundError:
    print('Not a Shopify store')

try:
    product = shop.product('nonexistent')
except ProductNotFoundError:
    print('Product not found')
```

## Exception Hierarchy

```
ShopifyError
├── StoreNotFoundError
├── ProductNotFoundError
├── CollectionNotFoundError
├── PageNotFoundError
├── RateLimitError
├── RequestError
└── ParsingError
```

## Data Models

| Model | Description |
|-------|-------------|
| `Store` | Store metadata (name, currency, counts) |
| `Product` | Product with variants, images, options |
| `Variant` | Pricing, stock, SKU, weight |
| `ProductImage` | Image URL with dimensions |
| `ProductOption` | Option name and values |
| `Collection` | Collection with image and product count |
| `Page` | Static page content |

All models have a `.to_dict()` method for serialization.

## License

MIT
