tokopaedi-async 0.1.0__tar.gz

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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Hilmi Azizi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,278 @@
1
+ Metadata-Version: 2.4
2
+ Name: tokopaedi-async
3
+ Version: 0.1.0
4
+ Summary: High-performance Async Python scraper for Tokopedia (Fork of tokopaedi)
5
+ License: MIT
6
+ License-File: LICENSE
7
+ Keywords: tokopedia,scraper,ecommerce,product,data,web-scraping,python,data-analysis,tokopedia-reviews,async,asyncio
8
+ Author: pandamoon21
9
+ Author-email: pandamoon21@waifu.club
10
+ Requires-Python: >=3.9,<4.0
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Requires-Dist: curl-cffi (>=0.11.4,<0.12.0)
25
+ Project-URL: Documentation, https://github.com/pandamoon21/tokopaedi-async
26
+ Project-URL: Homepage, https://github.com/pandamoon21/tokopaedi-async
27
+ Project-URL: Repository, https://github.com/pandamoon21/tokopaedi-async
28
+ Description-Content-Type: text/markdown
29
+
30
+
31
+ # Tokopaedi Async - High-Performance Async Python Scraper for Tokopedia
32
+ ![PyPI](https://img.shields.io/pypi/v/tokopaedi-async) [![PyPI Downloads](https://static.pepy.tech/badge/tokopaedi-async)](https://pepy.tech/projects/tokopaedi-async) ![GitHub Repo stars](https://img.shields.io/github/stars/pandamoon21/tokopaedi-async?style=social) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/pandamoon21/tokopaedi-async/blob/main/LICENSE) ![GitHub forks](https://img.shields.io/github/forks/pandamoon21/tokopaedi-async?style=social)
33
+
34
+ **Extract product data, reviews, and search results from Tokopedia with ease.**
35
+
36
+ tokopaedi-async is a high-performance fork of the original [**Tokopaedi**](https://github.com/hilmiazizi/tokopaedi) library. It leverages Python's asyncio and curl_cffi to perform massive data extraction concurrently, making it significantly faster for bulk operations like enriching product details or fetching thousands of reviews.
37
+
38
+
39
+ ![Tokopaedi Runtime](https://github.com/pandamoon21/tokopaedi-async/blob/main/image/runtime.png?raw=true)
40
+
41
+ ## Key Features
42
+
43
+ - 🚀 **Asynchronous & Concurrent**: Built on asyncio for non-blocking I/O. Fetch details for more products in the time it takes to fetch one.
44
+ - 🔍 **Product Search**: Search products with advanced filters (price, rating, condition, official store, etc.).
45
+ - 📦 **Detailed Product Data**: Retrieve rich product details, including variants, pricing, stock, and media.
46
+ - 💬 **Reviews Scraper**: Scrape product reviews with ratings, timestamps, and more.
47
+ - 🛡️ **Smart Anti-Detection**: Uses curl_cffi to mimic real browser fingerprints (JA3/TLS) and rotating user agents.
48
+ - 📊 **JSON Export**: Easy serialization to JSON or Pandas DataFrame.
49
+
50
+
51
+ ## Installation
52
+ Tokopaedi is available on PyPi: [https://pypi.org/project/tokopaedi-async/](https://pypi.org/project/tokopaedi-async/)
53
+
54
+ Install Tokopaedi via pip:
55
+
56
+ ```bash
57
+ pip install tokopaedi-async
58
+ ```
59
+
60
+ ## Quick Start
61
+ Since this library is asynchronous, you must run it within an `async` function using `asyncio`.
62
+ ```python
63
+ import asyncio
64
+ import json
65
+ from tokopaedi import search, SearchFilters, get_product
66
+
67
+ async def main():
68
+ # 1. Setup Filters (Optional)
69
+ filters = SearchFilters(
70
+ bebas_ongkir_extra=True,
71
+ pmin=15000000,
72
+ pmax=25000000,
73
+ rt=4.5
74
+ )
75
+
76
+ print("🔍 Searching...")
77
+ # 'await' is required for search
78
+ results = await search("Asus Zenbook S14 32GB", max_result=100, debug=True, filters=filters)
79
+
80
+ # 2. Parallel Enrichment
81
+ # This runs 20+ concurrent requests to fetch details/reviews almost instantly
82
+ print(f"⚡ Enriching data for {len(results)} products...")
83
+ await results.enrich_details(debug=True)
84
+ await results.enrich_reviews(max_result=50, debug=True)
85
+
86
+ # 3. Save to JSON
87
+ with open('result.json', 'w') as f:
88
+ f.write(json.dumps(results.json(), indent=4))
89
+ print("✅ Done!")
90
+
91
+ if __name__ == "__main__":
92
+ asyncio.run(main())
93
+ ```
94
+
95
+ ## 📘 API Overview
96
+
97
+ ### 🔍 `async search(keyword: str, max_result: int = 100, filters: Optional[SearchFilters] = None, debug: bool = False) -> SearchResults`
98
+
99
+ Search for products from Tokopedia.
100
+
101
+ ```python
102
+ results = await search(
103
+ keyword="Laptop Gaming",
104
+ max_result=100,
105
+ filters=filters,
106
+ debug=True
107
+ )
108
+ ```
109
+
110
+ **Parameters:**
111
+
112
+ - `keyword`: string keyword (e.g., `"logitech mouse"`).
113
+
114
+ - `max_result`: Expected number of results to return.
115
+
116
+ - `filters`: Optional `SearchFilters` instance to narrow search results.
117
+
118
+ - `debug`: Show debug message if True
119
+
120
+
121
+ **Returns:**
122
+
123
+ - A `SearchResults` instance (list-like object of `ProductSearchResult`), supporting `.json()` for easy export.
124
+
125
+
126
+ ----------
127
+
128
+ ### 📦 `async get_product(product_id: Optional[Union[int, str]] = None, url: Optional[str] = None, debug: bool = False) -> ProductData`
129
+
130
+ Fetch detailed information for a given Tokopedia product.
131
+
132
+ **Parameters:**
133
+
134
+ - `product_id`: (Optional) The product ID returned from `search()`. If provided, this will take precedence over `url`.
135
+ - `url`: (Optional) The full product URL. Used only if `product_id` is not provided.
136
+ - `debug`: If `True`, prints debug output for troubleshooting.
137
+
138
+ > ⚠️ Either `product_id` or `url` must be provided. If both are given, `product_id` is used and `url` is ignored.
139
+
140
+ **Returns:**
141
+
142
+ - A `ProductData` instance containing detailed information such as product name, pricing, variants, media, stock, rating, etc.
143
+ - Supports `.json()` for easy serialization (e.g., to use with `pandas` or export as `.json`).
144
+
145
+ ----------
146
+
147
+ ### 🗣️ `async get_reviews(product_id: Optional[Union[int, str]] = None, url: Optional[str] = None, max_count: int = 20, debug: bool = False) -> List[ProductReview]`
148
+
149
+ Scrape customer reviews for a given product.
150
+
151
+ **Parameters:**
152
+
153
+ - `product_id`: (Optional) The product ID to fetch reviews for. Takes precedence over `url` if both are provided.
154
+ - `url`: (Optional) Full product URL. Used only if `product_id` is not provided.
155
+ - `max_count`: Maximum number of reviews to fetch (default: 20).
156
+ - `debug`: Show debug messages if `True`.
157
+
158
+ > ⚠️ Either `product_id` or `url` must be provided.
159
+
160
+ **Returns:**
161
+
162
+ - A list of `ProductReview` objects.
163
+ - Each object supports `.json()` for serialization (e.g., for use with `pandas` or JSON export).
164
+
165
+ **Returns:**
166
+
167
+ - A new `SearchResults` object with `.product_detail` and `.product_reviews` fields filled in (if data was provided).
168
+
169
+ ----------
170
+ ### `SearchFilters` – Optional Search Filters
171
+
172
+ Use `SearchFilters` to refine your search results. All fields are optional. Pass it into the `search()` function via the `filters` argument.
173
+
174
+ #### Example:
175
+ ```python
176
+ from tokopaedi_async import SearchFilters
177
+
178
+ filters = SearchFilters(
179
+ pmin=100000, # Min Price
180
+ pmax=5000000, # Max Price
181
+ condition=1, # 1=New, 2=Used
182
+ shop_tier=2, # 2=Official Store, 3=Power Merchant
183
+ rt=4.5, # Min Rating
184
+ latest_product=30, # Added in last 30 days
185
+ is_discount=True, # Only discounted items
186
+ is_fulfillment=True, # "Dilayani Tokopedia"
187
+ is_plus=True # Tokopedia PLUS
188
+ )
189
+
190
+ results = await search("logitech mouse", filters=filters)
191
+ ```
192
+
193
+ #### Available Fields:
194
+
195
+ | Field | Type | Description | Accepted Values |
196
+ |----------------------|----------|---------------------------------------------------|----------------------------------|
197
+ | `pmin` | `int` | Minimum price (in IDR) | e.g., `100000` |
198
+ | `pmax` | `int` | Maximum price (in IDR) | e.g., `1000000` |
199
+ | `condition` | `int` | Product condition | `1` = New, `2` = Used |
200
+ | `shop_tier` | `int` | Type of shop | `2` = Mall, `3` = Power Shop |
201
+ | `rt` | `float` | Minimum rating | e.g., `4.5` |
202
+ | `latest_product` | `int` | Product recency filter | `7`, `30`, `90` |
203
+ | `bebas_ongkir_extra` | `bool` | Filter for extra free shipping | `True` / `False` |
204
+ | `is_discount` | `bool` | Only show discounted products | `True` / `False` |
205
+ | `is_fulfillment` | `bool` | Only Fulfilled by Tokopedia | `True` / `False` |
206
+ | `is_plus` | `bool` | Only Tokopedia PLUS sellers | `True` / `False` |
207
+ | `cod` | `bool` | Cash on delivery available | `True` / `False` |
208
+
209
+
210
+ ## Product Details & Reviews Enrichment
211
+
212
+ Tokopaedi supports data enrichment to attach detailed product information and customer reviews directly to search results. This is useful when you want to go beyond basic search metadata and analyze full product details or customer feedback.
213
+ #### Example:
214
+ ```python
215
+ # Enrich search results
216
+ results = search("Asus Zenbook S14 32GB", max_result=10, debug=True, filters=filters)
217
+ results.enrich_details(debug=True)
218
+ results.enrich_reviews(max_result=50, debug=True)
219
+
220
+ # Enrich product detail with reviews
221
+ product = get_product(url="https://www.tokopedia.com/asusrogindonesia/asus-tuf-a15-fa506ncr-ryzen-7-7435hs-rtx3050-4gb-8gb-512gb-w11-ohs-o365-15-6fhd-144hz-ips-rgb-blk-r735b1t-om-laptop-8gb-512gb-4970d?extParam=whid%3D17186756&aff_unique_id=&channel=others&chain_key=")
222
+ product.enrich_reviews(max_result=50, debug=True)
223
+ ```
224
+
225
+ Enrichment methods are available on both the `SearchResults` container and individual `ProductData` objects:
226
+
227
+ ### On `SearchResults`
228
+
229
+ ```python
230
+ # Fetches details for ALL items in the list concurrently
231
+ await results.enrich_details()
232
+
233
+ # Fetches reviews for ALL items in the list concurrently
234
+ await results.enrich_reviews(max_result=20)
235
+ ```
236
+
237
+ - `enrich_details(debug: bool = False) -> None`
238
+ Enriches all items in the result with detailed product info.
239
+ - `debug`: If `True`, logs each enrichment step.
240
+
241
+ - `enrich_reviews(max_result: int = 10, debug: bool = False) -> None`
242
+ Enriches all items with customer reviews (up to `max_result` per product).
243
+ - `max_result`: Number of reviews to fetch for each product.
244
+ - `debug`: If `True`, logs the review enrichment process.
245
+
246
+ ### On `ProductData`
247
+
248
+ ```python
249
+ await product.enrich_details()
250
+ await product.enrich_reviews()
251
+ ```
252
+
253
+ - `enrich_details(debug: bool = False) -> None`
254
+ Enriches this specific product with detailed information.
255
+
256
+ - `enrich_reviews(max_result: int = 10, debug: bool = False) -> None`
257
+ Enriches this product with customer reviews.
258
+
259
+ This design allows for flexibility: enrich a full result set at once, or enrich individual items selectively as needed.
260
+
261
+
262
+ ## 📋 Changelog
263
+
264
+ ### 0.1.0
265
+ - Initial release based on [tokopaedi 0.2.3](https://github.com/hilmiazizi/tokopaedi/tree/3d74be192ff9c4e278df24eb930329a1117c68ea)
266
+
267
+ ## Disclaimer
268
+
269
+ This is an unofficial library and is not affiliated with, endorsed, or supported by Tokopedia. It is intended for educational and research purposes only. Please use responsibly and respect the website's Terms of Service.
270
+
271
+ ## Credits & License
272
+
273
+ Original library by [**Hilmi Azizi**](https://hilmiazizi.com) - Thanks :)
274
+
275
+ Async fork maintained by [**pandamoon21**](https://github.com/pandamoon21).
276
+
277
+ Distributed under the MIT License. See [LICENSE](https://github.com/pandamoon21/tokopaedi-async/blob/main/LICENSE) for more information.
278
+
@@ -0,0 +1,248 @@
1
+
2
+ # Tokopaedi Async - High-Performance Async Python Scraper for Tokopedia
3
+ ![PyPI](https://img.shields.io/pypi/v/tokopaedi-async) [![PyPI Downloads](https://static.pepy.tech/badge/tokopaedi-async)](https://pepy.tech/projects/tokopaedi-async) ![GitHub Repo stars](https://img.shields.io/github/stars/pandamoon21/tokopaedi-async?style=social) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/pandamoon21/tokopaedi-async/blob/main/LICENSE) ![GitHub forks](https://img.shields.io/github/forks/pandamoon21/tokopaedi-async?style=social)
4
+
5
+ **Extract product data, reviews, and search results from Tokopedia with ease.**
6
+
7
+ tokopaedi-async is a high-performance fork of the original [**Tokopaedi**](https://github.com/hilmiazizi/tokopaedi) library. It leverages Python's asyncio and curl_cffi to perform massive data extraction concurrently, making it significantly faster for bulk operations like enriching product details or fetching thousands of reviews.
8
+
9
+
10
+ ![Tokopaedi Runtime](https://github.com/pandamoon21/tokopaedi-async/blob/main/image/runtime.png?raw=true)
11
+
12
+ ## Key Features
13
+
14
+ - 🚀 **Asynchronous & Concurrent**: Built on asyncio for non-blocking I/O. Fetch details for more products in the time it takes to fetch one.
15
+ - 🔍 **Product Search**: Search products with advanced filters (price, rating, condition, official store, etc.).
16
+ - 📦 **Detailed Product Data**: Retrieve rich product details, including variants, pricing, stock, and media.
17
+ - 💬 **Reviews Scraper**: Scrape product reviews with ratings, timestamps, and more.
18
+ - 🛡️ **Smart Anti-Detection**: Uses curl_cffi to mimic real browser fingerprints (JA3/TLS) and rotating user agents.
19
+ - 📊 **JSON Export**: Easy serialization to JSON or Pandas DataFrame.
20
+
21
+
22
+ ## Installation
23
+ Tokopaedi is available on PyPi: [https://pypi.org/project/tokopaedi-async/](https://pypi.org/project/tokopaedi-async/)
24
+
25
+ Install Tokopaedi via pip:
26
+
27
+ ```bash
28
+ pip install tokopaedi-async
29
+ ```
30
+
31
+ ## Quick Start
32
+ Since this library is asynchronous, you must run it within an `async` function using `asyncio`.
33
+ ```python
34
+ import asyncio
35
+ import json
36
+ from tokopaedi import search, SearchFilters, get_product
37
+
38
+ async def main():
39
+ # 1. Setup Filters (Optional)
40
+ filters = SearchFilters(
41
+ bebas_ongkir_extra=True,
42
+ pmin=15000000,
43
+ pmax=25000000,
44
+ rt=4.5
45
+ )
46
+
47
+ print("🔍 Searching...")
48
+ # 'await' is required for search
49
+ results = await search("Asus Zenbook S14 32GB", max_result=100, debug=True, filters=filters)
50
+
51
+ # 2. Parallel Enrichment
52
+ # This runs 20+ concurrent requests to fetch details/reviews almost instantly
53
+ print(f"⚡ Enriching data for {len(results)} products...")
54
+ await results.enrich_details(debug=True)
55
+ await results.enrich_reviews(max_result=50, debug=True)
56
+
57
+ # 3. Save to JSON
58
+ with open('result.json', 'w') as f:
59
+ f.write(json.dumps(results.json(), indent=4))
60
+ print("✅ Done!")
61
+
62
+ if __name__ == "__main__":
63
+ asyncio.run(main())
64
+ ```
65
+
66
+ ## 📘 API Overview
67
+
68
+ ### 🔍 `async search(keyword: str, max_result: int = 100, filters: Optional[SearchFilters] = None, debug: bool = False) -> SearchResults`
69
+
70
+ Search for products from Tokopedia.
71
+
72
+ ```python
73
+ results = await search(
74
+ keyword="Laptop Gaming",
75
+ max_result=100,
76
+ filters=filters,
77
+ debug=True
78
+ )
79
+ ```
80
+
81
+ **Parameters:**
82
+
83
+ - `keyword`: string keyword (e.g., `"logitech mouse"`).
84
+
85
+ - `max_result`: Expected number of results to return.
86
+
87
+ - `filters`: Optional `SearchFilters` instance to narrow search results.
88
+
89
+ - `debug`: Show debug message if True
90
+
91
+
92
+ **Returns:**
93
+
94
+ - A `SearchResults` instance (list-like object of `ProductSearchResult`), supporting `.json()` for easy export.
95
+
96
+
97
+ ----------
98
+
99
+ ### 📦 `async get_product(product_id: Optional[Union[int, str]] = None, url: Optional[str] = None, debug: bool = False) -> ProductData`
100
+
101
+ Fetch detailed information for a given Tokopedia product.
102
+
103
+ **Parameters:**
104
+
105
+ - `product_id`: (Optional) The product ID returned from `search()`. If provided, this will take precedence over `url`.
106
+ - `url`: (Optional) The full product URL. Used only if `product_id` is not provided.
107
+ - `debug`: If `True`, prints debug output for troubleshooting.
108
+
109
+ > ⚠️ Either `product_id` or `url` must be provided. If both are given, `product_id` is used and `url` is ignored.
110
+
111
+ **Returns:**
112
+
113
+ - A `ProductData` instance containing detailed information such as product name, pricing, variants, media, stock, rating, etc.
114
+ - Supports `.json()` for easy serialization (e.g., to use with `pandas` or export as `.json`).
115
+
116
+ ----------
117
+
118
+ ### 🗣️ `async get_reviews(product_id: Optional[Union[int, str]] = None, url: Optional[str] = None, max_count: int = 20, debug: bool = False) -> List[ProductReview]`
119
+
120
+ Scrape customer reviews for a given product.
121
+
122
+ **Parameters:**
123
+
124
+ - `product_id`: (Optional) The product ID to fetch reviews for. Takes precedence over `url` if both are provided.
125
+ - `url`: (Optional) Full product URL. Used only if `product_id` is not provided.
126
+ - `max_count`: Maximum number of reviews to fetch (default: 20).
127
+ - `debug`: Show debug messages if `True`.
128
+
129
+ > ⚠️ Either `product_id` or `url` must be provided.
130
+
131
+ **Returns:**
132
+
133
+ - A list of `ProductReview` objects.
134
+ - Each object supports `.json()` for serialization (e.g., for use with `pandas` or JSON export).
135
+
136
+ **Returns:**
137
+
138
+ - A new `SearchResults` object with `.product_detail` and `.product_reviews` fields filled in (if data was provided).
139
+
140
+ ----------
141
+ ### `SearchFilters` – Optional Search Filters
142
+
143
+ Use `SearchFilters` to refine your search results. All fields are optional. Pass it into the `search()` function via the `filters` argument.
144
+
145
+ #### Example:
146
+ ```python
147
+ from tokopaedi_async import SearchFilters
148
+
149
+ filters = SearchFilters(
150
+ pmin=100000, # Min Price
151
+ pmax=5000000, # Max Price
152
+ condition=1, # 1=New, 2=Used
153
+ shop_tier=2, # 2=Official Store, 3=Power Merchant
154
+ rt=4.5, # Min Rating
155
+ latest_product=30, # Added in last 30 days
156
+ is_discount=True, # Only discounted items
157
+ is_fulfillment=True, # "Dilayani Tokopedia"
158
+ is_plus=True # Tokopedia PLUS
159
+ )
160
+
161
+ results = await search("logitech mouse", filters=filters)
162
+ ```
163
+
164
+ #### Available Fields:
165
+
166
+ | Field | Type | Description | Accepted Values |
167
+ |----------------------|----------|---------------------------------------------------|----------------------------------|
168
+ | `pmin` | `int` | Minimum price (in IDR) | e.g., `100000` |
169
+ | `pmax` | `int` | Maximum price (in IDR) | e.g., `1000000` |
170
+ | `condition` | `int` | Product condition | `1` = New, `2` = Used |
171
+ | `shop_tier` | `int` | Type of shop | `2` = Mall, `3` = Power Shop |
172
+ | `rt` | `float` | Minimum rating | e.g., `4.5` |
173
+ | `latest_product` | `int` | Product recency filter | `7`, `30`, `90` |
174
+ | `bebas_ongkir_extra` | `bool` | Filter for extra free shipping | `True` / `False` |
175
+ | `is_discount` | `bool` | Only show discounted products | `True` / `False` |
176
+ | `is_fulfillment` | `bool` | Only Fulfilled by Tokopedia | `True` / `False` |
177
+ | `is_plus` | `bool` | Only Tokopedia PLUS sellers | `True` / `False` |
178
+ | `cod` | `bool` | Cash on delivery available | `True` / `False` |
179
+
180
+
181
+ ## Product Details & Reviews Enrichment
182
+
183
+ Tokopaedi supports data enrichment to attach detailed product information and customer reviews directly to search results. This is useful when you want to go beyond basic search metadata and analyze full product details or customer feedback.
184
+ #### Example:
185
+ ```python
186
+ # Enrich search results
187
+ results = search("Asus Zenbook S14 32GB", max_result=10, debug=True, filters=filters)
188
+ results.enrich_details(debug=True)
189
+ results.enrich_reviews(max_result=50, debug=True)
190
+
191
+ # Enrich product detail with reviews
192
+ product = get_product(url="https://www.tokopedia.com/asusrogindonesia/asus-tuf-a15-fa506ncr-ryzen-7-7435hs-rtx3050-4gb-8gb-512gb-w11-ohs-o365-15-6fhd-144hz-ips-rgb-blk-r735b1t-om-laptop-8gb-512gb-4970d?extParam=whid%3D17186756&aff_unique_id=&channel=others&chain_key=")
193
+ product.enrich_reviews(max_result=50, debug=True)
194
+ ```
195
+
196
+ Enrichment methods are available on both the `SearchResults` container and individual `ProductData` objects:
197
+
198
+ ### On `SearchResults`
199
+
200
+ ```python
201
+ # Fetches details for ALL items in the list concurrently
202
+ await results.enrich_details()
203
+
204
+ # Fetches reviews for ALL items in the list concurrently
205
+ await results.enrich_reviews(max_result=20)
206
+ ```
207
+
208
+ - `enrich_details(debug: bool = False) -> None`
209
+ Enriches all items in the result with detailed product info.
210
+ - `debug`: If `True`, logs each enrichment step.
211
+
212
+ - `enrich_reviews(max_result: int = 10, debug: bool = False) -> None`
213
+ Enriches all items with customer reviews (up to `max_result` per product).
214
+ - `max_result`: Number of reviews to fetch for each product.
215
+ - `debug`: If `True`, logs the review enrichment process.
216
+
217
+ ### On `ProductData`
218
+
219
+ ```python
220
+ await product.enrich_details()
221
+ await product.enrich_reviews()
222
+ ```
223
+
224
+ - `enrich_details(debug: bool = False) -> None`
225
+ Enriches this specific product with detailed information.
226
+
227
+ - `enrich_reviews(max_result: int = 10, debug: bool = False) -> None`
228
+ Enriches this product with customer reviews.
229
+
230
+ This design allows for flexibility: enrich a full result set at once, or enrich individual items selectively as needed.
231
+
232
+
233
+ ## 📋 Changelog
234
+
235
+ ### 0.1.0
236
+ - Initial release based on [tokopaedi 0.2.3](https://github.com/hilmiazizi/tokopaedi/tree/3d74be192ff9c4e278df24eb930329a1117c68ea)
237
+
238
+ ## Disclaimer
239
+
240
+ This is an unofficial library and is not affiliated with, endorsed, or supported by Tokopedia. It is intended for educational and research purposes only. Please use responsibly and respect the website's Terms of Service.
241
+
242
+ ## Credits & License
243
+
244
+ Original library by [**Hilmi Azizi**](https://hilmiazizi.com) - Thanks :)
245
+
246
+ Async fork maintained by [**pandamoon21**](https://github.com/pandamoon21).
247
+
248
+ Distributed under the MIT License. See [LICENSE](https://github.com/pandamoon21/tokopaedi-async/blob/main/LICENSE) for more information.
@@ -0,0 +1,36 @@
1
+ [tool.poetry]
2
+ name = "tokopaedi-async"
3
+ version = "0.1.0"
4
+ description = "High-performance Async Python scraper for Tokopedia (Fork of tokopaedi)"
5
+ authors = ["pandamoon21 <pandamoon21@waifu.club>"]
6
+ readme = "README.md"
7
+ license = "MIT"
8
+ packages = [{ include = "tokopaedi_async", from = "src" }]
9
+ include = ["LICENSE"]
10
+
11
+ homepage = "https://github.com/pandamoon21/tokopaedi-async"
12
+ repository = "https://github.com/pandamoon21/tokopaedi-async"
13
+ documentation = "https://github.com/pandamoon21/tokopaedi-async"
14
+ keywords = ["tokopedia", "scraper", "ecommerce", "product", "data", "web-scraping", "python", "data-analysis", "tokopedia-reviews", "async", "asyncio"]
15
+
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "Topic :: Internet :: WWW/HTTP :: Indexing/Search",
20
+ "Topic :: Software Development :: Libraries :: Python Modules",
21
+ "License :: OSI Approved :: MIT License",
22
+ "Programming Language :: Python :: 3",
23
+ "Programming Language :: Python :: 3.9",
24
+ "Programming Language :: Python :: 3.10",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ "Operating System :: OS Independent"
28
+ ]
29
+
30
+ [tool.poetry.dependencies]
31
+ python = "^3.9"
32
+ curl-cffi = "^0.11.4"
33
+
34
+ [build-system]
35
+ requires = ["poetry-core>=1.1.0"]
36
+ build-backend = "poetry.core.masonry.api"
@@ -0,0 +1,54 @@
1
+ __version__ = '0.1.0'
2
+ from dataclasses import dataclass
3
+ from typing import Optional
4
+ from .search import search
5
+ from .get_product import get_product
6
+ from .get_reviews import get_reviews
7
+ from .tokopaedi_types import ProductData, ProductReview
8
+
9
+ @dataclass
10
+ class SearchFilters:
11
+ # Free shipping benefit (bebas ongkir ekstra)
12
+ # true = only show products with free shipping
13
+ bebas_ongkir_extra: Optional[bool] = None
14
+
15
+ # Discounted products
16
+ # true = only show products with active discounts
17
+ is_discount: Optional[bool] = None
18
+
19
+ # Product condition
20
+ # 1 = New
21
+ # 2 = Used
22
+ condition: Optional[int] = None
23
+
24
+ # Shop tier
25
+ # 2 = Mall
26
+ # 3 = Power Shop
27
+ shop_tier: Optional[int] = None
28
+
29
+ # Minimum price (in IDR)
30
+ pmin: Optional[int] = None
31
+
32
+ # Maximum price (in IDR)
33
+ pmax: Optional[int] = None
34
+
35
+ # Fulfilled by Tokopedia
36
+ # true = only show products fulfilled by Tokopedia
37
+ is_fulfillment: Optional[bool] = None
38
+
39
+ # Tokopedia Plus membership products
40
+ # true = only show products available under Tokopedia Plus
41
+ is_plus: Optional[bool] = None
42
+
43
+ # Cash on Delivery (COD)
44
+ # true = only show products eligible for COD
45
+ cod: Optional[bool] = None
46
+
47
+ # Minimum average rating (0.0 to 5.0)
48
+ rt: Optional[float] = None
49
+
50
+ # Product age in days
51
+ # 7 = added in the last 7 days
52
+ # 30 = added in the last 30 days
53
+ # 90 = added in the last 90 days
54
+ latest_product: Optional[int] = None
@@ -0,0 +1,34 @@
1
+ import logging
2
+
3
+ def setup_custom_logging():
4
+ SEARCH_LEVEL = 25
5
+ DETAIL_LEVEL = 26
6
+ REVIEWS_LEVEL = 27
7
+
8
+ logging.addLevelName(SEARCH_LEVEL, "SEARCH")
9
+ logging.addLevelName(DETAIL_LEVEL, "DETAIL")
10
+ logging.addLevelName(REVIEWS_LEVEL, "REVIEW")
11
+
12
+ class CustomLogger(logging.Logger):
13
+ def search(self, message, *args, **kwargs):
14
+ if self.isEnabledFor(SEARCH_LEVEL):
15
+ self._log(SEARCH_LEVEL, message, args, **kwargs)
16
+
17
+ def detail(self, message, *args, **kwargs):
18
+ if self.isEnabledFor(DETAIL_LEVEL):
19
+ self._log(DETAIL_LEVEL, message, args, **kwargs)
20
+
21
+ def reviews(self, message, *args, **kwargs):
22
+ if self.isEnabledFor(REVIEWS_LEVEL):
23
+ self._log(REVIEWS_LEVEL, message, args, **kwargs)
24
+
25
+ logging.setLoggerClass(CustomLogger)
26
+
27
+ logging.basicConfig(
28
+ level=SEARCH_LEVEL,
29
+ format="{asctime} - {levelname} - {message}",
30
+ style="{",
31
+ datefmt="%Y-%m-%d %H:%M",
32
+ )
33
+
34
+ return logging.getLogger(__name__)