blocket-api 0.2.8__tar.gz → 0.2.9__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.
- {blocket_api-0.2.8 → blocket_api-0.2.9}/PKG-INFO +27 -21
- {blocket_api-0.2.8 → blocket_api-0.2.9}/README.md +24 -19
- {blocket_api-0.2.8 → blocket_api-0.2.9}/blocket_api/blocket.py +137 -12
- blocket_api-0.2.9/blocket_api/models.py +151 -0
- {blocket_api-0.2.8 → blocket_api-0.2.9}/blocket_api.egg-info/PKG-INFO +27 -21
- {blocket_api-0.2.8 → blocket_api-0.2.9}/blocket_api.egg-info/SOURCES.txt +1 -0
- {blocket_api-0.2.8 → blocket_api-0.2.9}/blocket_api.egg-info/requires.txt +2 -1
- {blocket_api-0.2.8 → blocket_api-0.2.9}/pyproject.toml +3 -2
- {blocket_api-0.2.8 → blocket_api-0.2.9}/LICENSE +0 -0
- {blocket_api-0.2.8 → blocket_api-0.2.9}/blocket_api/__init__.py +0 -0
- {blocket_api-0.2.8 → blocket_api-0.2.9}/blocket_api/qasa.py +0 -0
- {blocket_api-0.2.8 → blocket_api-0.2.9}/blocket_api.egg-info/dependency_links.txt +0 -0
- {blocket_api-0.2.8 → blocket_api-0.2.9}/blocket_api.egg-info/top_level.txt +0 -0
- {blocket_api-0.2.8 → blocket_api-0.2.9}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: blocket_api
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.9
|
|
4
4
|
Summary: A python API wrapper for blocket.se
|
|
5
5
|
Author-email: dunderrrrrr <emil.bjorkroth@gmail.com>
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -11,12 +11,13 @@ Requires-Dist: pre-commit>=3.7.1
|
|
|
11
11
|
Requires-Dist: pytest>=8.2.2
|
|
12
12
|
Requires-Dist: respx>=0.21.1
|
|
13
13
|
Requires-Dist: mypy>=1.15.0
|
|
14
|
-
Requires-Dist:
|
|
14
|
+
Requires-Dist: pydantic>=2.11.7
|
|
15
|
+
Requires-Dist: ruff>=0.13.0
|
|
15
16
|
Dynamic: license-file
|
|
16
17
|
|
|
17
18
|
# BlocketAPI
|
|
18
19
|
|
|
19
|
-
[](https://pypi.org/project/blocket_api/) [](https://github.com/dunderrrrrr/blocket_api/blob/main/LICENSE)
|
|
20
|
+
[](https://pypi.org/project/blocket_api/) [](https://github.com/dunderrrrrr/blocket_api/blob/main/LICENSE)  
|
|
20
21
|
|
|
21
22
|
BlocketAPI allows users to query saved searches, known as "Bevakningar", on [blocket.se](https://blocket.se/). This means you can either retrieve results from a specific saved search or list all listings/ads across all saved searches. The results from these queries are returned in a `json` format.
|
|
22
23
|
|
|
@@ -55,20 +56,20 @@ Some calls require a `bearerToken`. However, some calls are public and don't req
|
|
|
55
56
|
[Where token?](#-blocket-api-token)
|
|
56
57
|
|
|
57
58
|
|
|
58
|
-
| Function | Token required | Description |
|
|
59
|
-
|
|
60
|
-
| [`api.saved_searches()`](#saved_searches) | 🔐 Yes | List your saved searches (bevakningar) |
|
|
61
|
-
| [`api.get_listings()`](#
|
|
62
|
-
| [`api.custom_search()`](#
|
|
63
|
-
| [`api.motor_search()`](#
|
|
64
|
-
| [`api.price_eval()`](#
|
|
65
|
-
| [`api.home_search()`](#
|
|
66
|
-
| [`api.store_search()`](#
|
|
67
|
-
| [`api.get_store_listings()`](#
|
|
59
|
+
| Function | Token required | `as_objects` | Description |
|
|
60
|
+
|---|---|---|---|
|
|
61
|
+
| [`api.saved_searches()`](#saved_searches) | 🔐 Yes | - | List your saved searches (bevakningar) |
|
|
62
|
+
| [`api.get_listings()`](#get_listings) | 🔐 Yes | - | List items related to a saved search |
|
|
63
|
+
| [`api.custom_search()`](#custom_search) | 👏 No | Yes | Search for everything on Blocket and filter by region |
|
|
64
|
+
| [`api.motor_search()`](#motor_search) | 👏 No | Yes | Advanced search for car-listings. |
|
|
65
|
+
| [`api.price_eval()`](#price_eval) | 👏 No | - | Vehicle purchase valuation and details. |
|
|
66
|
+
| [`api.home_search()`](#home_search) | 👏 No | - | Query home listings.
|
|
67
|
+
| [`api.store_search()`](#store_search) | 👏 No | Yes | Search for a store.
|
|
68
|
+
| [`api.get_store_listings()`](#get_store_listings) | 👏 No | - | Get listings from a specific store.
|
|
68
69
|
|
|
69
70
|
## 🤓 Detailed usage
|
|
70
71
|
|
|
71
|
-
### saved_searches
|
|
72
|
+
### saved_searches
|
|
72
73
|
|
|
73
74
|
Saved searches are your so called "Bevakningar" and can be found [here](https://www.blocket.se/sparade/bevakningar). Each saved search has and unique `id` which can be used as a parameter to `get_listings()`, see below.
|
|
74
75
|
|
|
@@ -87,7 +88,7 @@ Saved searches are your so called "Bevakningar" and can be found [here](https://
|
|
|
87
88
|
]
|
|
88
89
|
```
|
|
89
90
|
|
|
90
|
-
### get_listings
|
|
91
|
+
### get_listings
|
|
91
92
|
Returns all listings related to a saved search.
|
|
92
93
|
|
|
93
94
|
Parameters:
|
|
@@ -121,7 +122,7 @@ Parameters:
|
|
|
121
122
|
}
|
|
122
123
|
```
|
|
123
124
|
|
|
124
|
-
### custom_search
|
|
125
|
+
### custom_search
|
|
125
126
|
Make a custom search through out all of blocked. A region can be passed in as parameter for filtering.
|
|
126
127
|
|
|
127
128
|
Parameters:
|
|
@@ -129,6 +130,7 @@ Parameters:
|
|
|
129
130
|
- `region` (`enum`, optional) - Filter results on a region, default is all of Sweden.
|
|
130
131
|
- `category` (`enum`, optional) - Filter for a specific category, ex. `Category.for_hemmet`.
|
|
131
132
|
- `limit` (`int`, optional) - Limit number of results returned, max is 99.
|
|
133
|
+
- `as_objects` (`bool`, optional) - Return results as pydantic models, default is `False`.
|
|
132
134
|
|
|
133
135
|
```py
|
|
134
136
|
>>> from blocket_api import Region
|
|
@@ -162,7 +164,7 @@ Parameters:
|
|
|
162
164
|
}
|
|
163
165
|
```
|
|
164
166
|
|
|
165
|
-
### motor_search
|
|
167
|
+
### motor_search
|
|
166
168
|
To query listings related to a specific car, supply the following parameters:
|
|
167
169
|
|
|
168
170
|
- `page` (`int`, required) - Results are split in pages, set page number here.
|
|
@@ -173,6 +175,8 @@ To query listings related to a specific car, supply the following parameters:
|
|
|
173
175
|
- `modelYear` (`Optional[Tuple[int, int]]`) - Set model year range, ex. `(2000, 2020)`.
|
|
174
176
|
- `milage` (`Optional[Tuple[int, int]]`) - Set milage range, ex. `(1000, 2000)`.
|
|
175
177
|
- `gearbox` (`Optional[GEARBOX_OPTIONS]`) - Filter a specific gearbox, ex. `Automat`.
|
|
178
|
+
- `as_objects` (`bool`, optional) - Return results as pydantic models, default is `False`.
|
|
179
|
+
|
|
176
180
|
```py
|
|
177
181
|
>>> api.motor_search(
|
|
178
182
|
make=["Audi", "Ford"],
|
|
@@ -184,7 +188,7 @@ To query listings related to a specific car, supply the following parameters:
|
|
|
184
188
|
...
|
|
185
189
|
```
|
|
186
190
|
|
|
187
|
-
### price_eval
|
|
191
|
+
### price_eval
|
|
188
192
|
Query price evaluation for a specific vehicle by using cars registration number (ABC123). This returns company and private estimated prices, car information, and more. The api queries same endpoint as Blockets ["värdera bil"](https://www.blocket.se/tjanster/vardera-bil) service.
|
|
189
193
|
|
|
190
194
|
- `registration_number` (`str`, required) - Registration number of the vehicle.
|
|
@@ -203,7 +207,7 @@ Query price evaluation for a specific vehicle by using cars registration number
|
|
|
203
207
|
}
|
|
204
208
|
```
|
|
205
209
|
|
|
206
|
-
### home_search
|
|
210
|
+
### home_search
|
|
207
211
|
Query home listings from [bostad.blocket.se](https://bostad.blocket.se/).
|
|
208
212
|
|
|
209
213
|
- `city` (`str`, required) - City name, ex. Stockholm.
|
|
@@ -223,11 +227,13 @@ Query home listings from [bostad.blocket.se](https://bostad.blocket.se/).
|
|
|
223
227
|
...
|
|
224
228
|
```
|
|
225
229
|
|
|
226
|
-
### store_search
|
|
230
|
+
### store_search
|
|
227
231
|
Search for a store in Blocket stores from [blocket.se/butiker](https://www.blocket.se/butiker).
|
|
228
232
|
|
|
229
233
|
- `search_query` (`str`, required) - The name of the store.
|
|
230
234
|
- `page` (`int`, optional) - The page number to return.
|
|
235
|
+
- `as_objects` (`bool`, optional) - Return results as pydantic models, default is `False`.
|
|
236
|
+
|
|
231
237
|
|
|
232
238
|
```py
|
|
233
239
|
>>> api.store_search("Jannes Car and Kebab")
|
|
@@ -243,7 +249,7 @@ Search for a store in Blocket stores from [blocket.se/butiker](https://www.block
|
|
|
243
249
|
}
|
|
244
250
|
```
|
|
245
251
|
|
|
246
|
-
### get_store_listings
|
|
252
|
+
### get_store_listings
|
|
247
253
|
Get listings from a specific store.
|
|
248
254
|
|
|
249
255
|
- `store_id` (`int`, required) - The store id. Can be obtained by calling `store_search()`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# BlocketAPI
|
|
2
2
|
|
|
3
|
-
[](https://pypi.org/project/blocket_api/) [](https://github.com/dunderrrrrr/blocket_api/blob/main/LICENSE)
|
|
3
|
+
[](https://pypi.org/project/blocket_api/) [](https://github.com/dunderrrrrr/blocket_api/blob/main/LICENSE)  
|
|
4
4
|
|
|
5
5
|
BlocketAPI allows users to query saved searches, known as "Bevakningar", on [blocket.se](https://blocket.se/). This means you can either retrieve results from a specific saved search or list all listings/ads across all saved searches. The results from these queries are returned in a `json` format.
|
|
6
6
|
|
|
@@ -39,20 +39,20 @@ Some calls require a `bearerToken`. However, some calls are public and don't req
|
|
|
39
39
|
[Where token?](#-blocket-api-token)
|
|
40
40
|
|
|
41
41
|
|
|
42
|
-
| Function | Token required | Description |
|
|
43
|
-
|
|
44
|
-
| [`api.saved_searches()`](#saved_searches) | 🔐 Yes | List your saved searches (bevakningar) |
|
|
45
|
-
| [`api.get_listings()`](#
|
|
46
|
-
| [`api.custom_search()`](#
|
|
47
|
-
| [`api.motor_search()`](#
|
|
48
|
-
| [`api.price_eval()`](#
|
|
49
|
-
| [`api.home_search()`](#
|
|
50
|
-
| [`api.store_search()`](#
|
|
51
|
-
| [`api.get_store_listings()`](#
|
|
42
|
+
| Function | Token required | `as_objects` | Description |
|
|
43
|
+
|---|---|---|---|
|
|
44
|
+
| [`api.saved_searches()`](#saved_searches) | 🔐 Yes | - | List your saved searches (bevakningar) |
|
|
45
|
+
| [`api.get_listings()`](#get_listings) | 🔐 Yes | - | List items related to a saved search |
|
|
46
|
+
| [`api.custom_search()`](#custom_search) | 👏 No | Yes | Search for everything on Blocket and filter by region |
|
|
47
|
+
| [`api.motor_search()`](#motor_search) | 👏 No | Yes | Advanced search for car-listings. |
|
|
48
|
+
| [`api.price_eval()`](#price_eval) | 👏 No | - | Vehicle purchase valuation and details. |
|
|
49
|
+
| [`api.home_search()`](#home_search) | 👏 No | - | Query home listings.
|
|
50
|
+
| [`api.store_search()`](#store_search) | 👏 No | Yes | Search for a store.
|
|
51
|
+
| [`api.get_store_listings()`](#get_store_listings) | 👏 No | - | Get listings from a specific store.
|
|
52
52
|
|
|
53
53
|
## 🤓 Detailed usage
|
|
54
54
|
|
|
55
|
-
### saved_searches
|
|
55
|
+
### saved_searches
|
|
56
56
|
|
|
57
57
|
Saved searches are your so called "Bevakningar" and can be found [here](https://www.blocket.se/sparade/bevakningar). Each saved search has and unique `id` which can be used as a parameter to `get_listings()`, see below.
|
|
58
58
|
|
|
@@ -71,7 +71,7 @@ Saved searches are your so called "Bevakningar" and can be found [here](https://
|
|
|
71
71
|
]
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
### get_listings
|
|
74
|
+
### get_listings
|
|
75
75
|
Returns all listings related to a saved search.
|
|
76
76
|
|
|
77
77
|
Parameters:
|
|
@@ -105,7 +105,7 @@ Parameters:
|
|
|
105
105
|
}
|
|
106
106
|
```
|
|
107
107
|
|
|
108
|
-
### custom_search
|
|
108
|
+
### custom_search
|
|
109
109
|
Make a custom search through out all of blocked. A region can be passed in as parameter for filtering.
|
|
110
110
|
|
|
111
111
|
Parameters:
|
|
@@ -113,6 +113,7 @@ Parameters:
|
|
|
113
113
|
- `region` (`enum`, optional) - Filter results on a region, default is all of Sweden.
|
|
114
114
|
- `category` (`enum`, optional) - Filter for a specific category, ex. `Category.for_hemmet`.
|
|
115
115
|
- `limit` (`int`, optional) - Limit number of results returned, max is 99.
|
|
116
|
+
- `as_objects` (`bool`, optional) - Return results as pydantic models, default is `False`.
|
|
116
117
|
|
|
117
118
|
```py
|
|
118
119
|
>>> from blocket_api import Region
|
|
@@ -146,7 +147,7 @@ Parameters:
|
|
|
146
147
|
}
|
|
147
148
|
```
|
|
148
149
|
|
|
149
|
-
### motor_search
|
|
150
|
+
### motor_search
|
|
150
151
|
To query listings related to a specific car, supply the following parameters:
|
|
151
152
|
|
|
152
153
|
- `page` (`int`, required) - Results are split in pages, set page number here.
|
|
@@ -157,6 +158,8 @@ To query listings related to a specific car, supply the following parameters:
|
|
|
157
158
|
- `modelYear` (`Optional[Tuple[int, int]]`) - Set model year range, ex. `(2000, 2020)`.
|
|
158
159
|
- `milage` (`Optional[Tuple[int, int]]`) - Set milage range, ex. `(1000, 2000)`.
|
|
159
160
|
- `gearbox` (`Optional[GEARBOX_OPTIONS]`) - Filter a specific gearbox, ex. `Automat`.
|
|
161
|
+
- `as_objects` (`bool`, optional) - Return results as pydantic models, default is `False`.
|
|
162
|
+
|
|
160
163
|
```py
|
|
161
164
|
>>> api.motor_search(
|
|
162
165
|
make=["Audi", "Ford"],
|
|
@@ -168,7 +171,7 @@ To query listings related to a specific car, supply the following parameters:
|
|
|
168
171
|
...
|
|
169
172
|
```
|
|
170
173
|
|
|
171
|
-
### price_eval
|
|
174
|
+
### price_eval
|
|
172
175
|
Query price evaluation for a specific vehicle by using cars registration number (ABC123). This returns company and private estimated prices, car information, and more. The api queries same endpoint as Blockets ["värdera bil"](https://www.blocket.se/tjanster/vardera-bil) service.
|
|
173
176
|
|
|
174
177
|
- `registration_number` (`str`, required) - Registration number of the vehicle.
|
|
@@ -187,7 +190,7 @@ Query price evaluation for a specific vehicle by using cars registration number
|
|
|
187
190
|
}
|
|
188
191
|
```
|
|
189
192
|
|
|
190
|
-
### home_search
|
|
193
|
+
### home_search
|
|
191
194
|
Query home listings from [bostad.blocket.se](https://bostad.blocket.se/).
|
|
192
195
|
|
|
193
196
|
- `city` (`str`, required) - City name, ex. Stockholm.
|
|
@@ -207,11 +210,13 @@ Query home listings from [bostad.blocket.se](https://bostad.blocket.se/).
|
|
|
207
210
|
...
|
|
208
211
|
```
|
|
209
212
|
|
|
210
|
-
### store_search
|
|
213
|
+
### store_search
|
|
211
214
|
Search for a store in Blocket stores from [blocket.se/butiker](https://www.blocket.se/butiker).
|
|
212
215
|
|
|
213
216
|
- `search_query` (`str`, required) - The name of the store.
|
|
214
217
|
- `page` (`int`, optional) - The page number to return.
|
|
218
|
+
- `as_objects` (`bool`, optional) - Return results as pydantic models, default is `False`.
|
|
219
|
+
|
|
215
220
|
|
|
216
221
|
```py
|
|
217
222
|
>>> api.store_search("Jannes Car and Kebab")
|
|
@@ -227,7 +232,7 @@ Search for a store in Blocket stores from [blocket.se/butiker](https://www.block
|
|
|
227
232
|
}
|
|
228
233
|
```
|
|
229
234
|
|
|
230
|
-
### get_store_listings
|
|
235
|
+
### get_store_listings
|
|
231
236
|
Get listings from a specific store.
|
|
232
237
|
|
|
233
238
|
- `store_id` (`int`, required) - The store id. Can be obtained by calling `store_search()`.
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from collections.abc import Callable
|
|
4
|
-
from functools import wraps
|
|
5
3
|
import urllib
|
|
4
|
+
from collections.abc import Callable
|
|
6
5
|
from dataclasses import dataclass
|
|
7
6
|
from enum import Enum
|
|
8
|
-
from
|
|
7
|
+
from functools import wraps
|
|
8
|
+
from typing import TYPE_CHECKING, Any, List, Literal, Optional, Tuple, Union, overload
|
|
9
9
|
|
|
10
10
|
import httpx
|
|
11
11
|
|
|
12
|
+
from blocket_api.models import (
|
|
13
|
+
CustomSearchResults,
|
|
14
|
+
MotorSearchResults,
|
|
15
|
+
StoreSearchResults,
|
|
16
|
+
)
|
|
12
17
|
from blocket_api.qasa import HOME_SEARCH_ORDERING, HomeType, OrderBy, Qasa
|
|
13
18
|
|
|
14
19
|
if TYPE_CHECKING:
|
|
@@ -232,6 +237,39 @@ class BlocketAPI:
|
|
|
232
237
|
token=self.token,
|
|
233
238
|
).json()
|
|
234
239
|
|
|
240
|
+
@overload
|
|
241
|
+
def custom_search(
|
|
242
|
+
self,
|
|
243
|
+
search_query: str,
|
|
244
|
+
region: Region = Region.hela_sverige,
|
|
245
|
+
category: Category | None = None,
|
|
246
|
+
limit: int = 99,
|
|
247
|
+
*,
|
|
248
|
+
as_objects: Literal[True],
|
|
249
|
+
) -> CustomSearchResults: ...
|
|
250
|
+
|
|
251
|
+
@overload
|
|
252
|
+
def custom_search(
|
|
253
|
+
self,
|
|
254
|
+
search_query: str,
|
|
255
|
+
region: Region = Region.hela_sverige,
|
|
256
|
+
category: Category | None = None,
|
|
257
|
+
limit: int = 99,
|
|
258
|
+
*,
|
|
259
|
+
as_objects: Literal[False] = False,
|
|
260
|
+
) -> dict: ...
|
|
261
|
+
|
|
262
|
+
@overload
|
|
263
|
+
def custom_search(
|
|
264
|
+
self,
|
|
265
|
+
search_query: str,
|
|
266
|
+
region: Region = Region.hela_sverige,
|
|
267
|
+
category: Category | None = None,
|
|
268
|
+
limit: int = 99,
|
|
269
|
+
*,
|
|
270
|
+
as_objects: bool = False,
|
|
271
|
+
) -> Union[dict, CustomSearchResults]: ...
|
|
272
|
+
|
|
235
273
|
@public_token
|
|
236
274
|
def custom_search(
|
|
237
275
|
self,
|
|
@@ -239,10 +277,11 @@ class BlocketAPI:
|
|
|
239
277
|
region: Region = Region.hela_sverige,
|
|
240
278
|
category: Category | None = None,
|
|
241
279
|
limit: int = 99,
|
|
242
|
-
|
|
280
|
+
*,
|
|
281
|
+
as_objects: bool = False,
|
|
282
|
+
) -> dict | CustomSearchResults:
|
|
243
283
|
"""
|
|
244
|
-
Do a custom search
|
|
245
|
-
Supply a region for filtering. Default is all of Sweden.
|
|
284
|
+
Do a custom search throughout all of Blocket.
|
|
246
285
|
"""
|
|
247
286
|
assert self.token
|
|
248
287
|
|
|
@@ -254,7 +293,53 @@ class BlocketAPI:
|
|
|
254
293
|
if category:
|
|
255
294
|
url += f"&cg={category.value}"
|
|
256
295
|
|
|
257
|
-
|
|
296
|
+
response = _make_request(url=url, token=self.token).json()
|
|
297
|
+
return CustomSearchResults.model_validate(response) if as_objects else response
|
|
298
|
+
|
|
299
|
+
@overload
|
|
300
|
+
def motor_search(
|
|
301
|
+
self,
|
|
302
|
+
page: int,
|
|
303
|
+
make: List[MAKE_OPTIONS],
|
|
304
|
+
fuel: Optional[List[FUEL_OPTIONS]] = None,
|
|
305
|
+
chassi: Optional[List[CHASSI_OPTIONS]] = None,
|
|
306
|
+
price: Optional[Tuple[int, int]] = None,
|
|
307
|
+
modelYear: Optional[Tuple[int, int]] = None,
|
|
308
|
+
milage: Optional[Tuple[int, int]] = None,
|
|
309
|
+
gearbox: Optional[GEARBOX_OPTIONS] = None,
|
|
310
|
+
*,
|
|
311
|
+
as_objects: Literal[True],
|
|
312
|
+
) -> MotorSearchResults: ...
|
|
313
|
+
|
|
314
|
+
@overload
|
|
315
|
+
def motor_search(
|
|
316
|
+
self,
|
|
317
|
+
page: int,
|
|
318
|
+
make: List[MAKE_OPTIONS],
|
|
319
|
+
fuel: Optional[List[FUEL_OPTIONS]] = None,
|
|
320
|
+
chassi: Optional[List[CHASSI_OPTIONS]] = None,
|
|
321
|
+
price: Optional[Tuple[int, int]] = None,
|
|
322
|
+
modelYear: Optional[Tuple[int, int]] = None,
|
|
323
|
+
milage: Optional[Tuple[int, int]] = None,
|
|
324
|
+
gearbox: Optional[GEARBOX_OPTIONS] = None,
|
|
325
|
+
*,
|
|
326
|
+
as_objects: Literal[False] = False,
|
|
327
|
+
) -> dict: ...
|
|
328
|
+
|
|
329
|
+
@overload
|
|
330
|
+
def motor_search(
|
|
331
|
+
self,
|
|
332
|
+
page: int,
|
|
333
|
+
make: List[MAKE_OPTIONS],
|
|
334
|
+
fuel: Optional[List[FUEL_OPTIONS]] = None,
|
|
335
|
+
chassi: Optional[List[CHASSI_OPTIONS]] = None,
|
|
336
|
+
price: Optional[Tuple[int, int]] = None,
|
|
337
|
+
modelYear: Optional[Tuple[int, int]] = None,
|
|
338
|
+
milage: Optional[Tuple[int, int]] = None,
|
|
339
|
+
gearbox: Optional[GEARBOX_OPTIONS] = None,
|
|
340
|
+
*,
|
|
341
|
+
as_objects: bool = False,
|
|
342
|
+
) -> Union[dict, MotorSearchResults]: ...
|
|
258
343
|
|
|
259
344
|
@public_token
|
|
260
345
|
def motor_search(
|
|
@@ -267,7 +352,9 @@ class BlocketAPI:
|
|
|
267
352
|
modelYear: Optional[Tuple[int, int]] = None,
|
|
268
353
|
milage: Optional[Tuple[int, int]] = None,
|
|
269
354
|
gearbox: Optional[GEARBOX_OPTIONS] = None,
|
|
270
|
-
|
|
355
|
+
*,
|
|
356
|
+
as_objects: bool = False,
|
|
357
|
+
) -> dict | MotorSearchResults:
|
|
271
358
|
"""
|
|
272
359
|
Search specifically in the car section of Blocket
|
|
273
360
|
with set optional parameters for filtering.
|
|
@@ -278,7 +365,8 @@ class BlocketAPI:
|
|
|
278
365
|
set_params = {
|
|
279
366
|
key: value
|
|
280
367
|
for key, value in locals().items()
|
|
281
|
-
if key not in ["self", "page", "range_params"]
|
|
368
|
+
if key not in ["self", "page", "range_params", "as_objects"]
|
|
369
|
+
and value is not None
|
|
282
370
|
}
|
|
283
371
|
|
|
284
372
|
filters = []
|
|
@@ -298,7 +386,8 @@ class BlocketAPI:
|
|
|
298
386
|
filters_str = "&".join([f"filter={f}" for f in filters])
|
|
299
387
|
url = f"{motor_base_url}?{filters_str}&page={page}"
|
|
300
388
|
|
|
301
|
-
|
|
389
|
+
response = _make_request(url=f"{url}", token=self.token).json()
|
|
390
|
+
return MotorSearchResults.model_validate(response) if as_objects else response
|
|
302
391
|
|
|
303
392
|
@public_token
|
|
304
393
|
def price_eval(
|
|
@@ -335,18 +424,54 @@ class BlocketAPI:
|
|
|
335
424
|
offset=offset,
|
|
336
425
|
).search()
|
|
337
426
|
|
|
427
|
+
@overload
|
|
428
|
+
def search_store(
|
|
429
|
+
self,
|
|
430
|
+
search_query: str,
|
|
431
|
+
page: int = 0,
|
|
432
|
+
*,
|
|
433
|
+
as_objects: Literal[True],
|
|
434
|
+
) -> StoreSearchResults: ...
|
|
435
|
+
|
|
436
|
+
@overload
|
|
437
|
+
def search_store(
|
|
438
|
+
self,
|
|
439
|
+
search_query: str,
|
|
440
|
+
page: int = 0,
|
|
441
|
+
*,
|
|
442
|
+
as_objects: Literal[False] = False,
|
|
443
|
+
) -> dict: ...
|
|
444
|
+
|
|
445
|
+
@overload
|
|
446
|
+
def search_store(
|
|
447
|
+
self,
|
|
448
|
+
page: int,
|
|
449
|
+
make: List[MAKE_OPTIONS],
|
|
450
|
+
fuel: Optional[List[FUEL_OPTIONS]] = None,
|
|
451
|
+
chassi: Optional[List[CHASSI_OPTIONS]] = None,
|
|
452
|
+
price: Optional[Tuple[int, int]] = None,
|
|
453
|
+
modelYear: Optional[Tuple[int, int]] = None,
|
|
454
|
+
milage: Optional[Tuple[int, int]] = None,
|
|
455
|
+
gearbox: Optional[GEARBOX_OPTIONS] = None,
|
|
456
|
+
*,
|
|
457
|
+
as_objects: bool = False,
|
|
458
|
+
) -> Union[dict, StoreSearchResults]: ...
|
|
459
|
+
|
|
338
460
|
@public_token
|
|
339
461
|
def search_store(
|
|
340
462
|
self,
|
|
341
463
|
search_query: str,
|
|
342
464
|
page: int = 0,
|
|
343
|
-
|
|
465
|
+
*,
|
|
466
|
+
as_objects: bool = False,
|
|
467
|
+
) -> dict | StoreSearchResults:
|
|
344
468
|
"""
|
|
345
469
|
Searching through Blocket stores from https://www.blocket.se/butiker.
|
|
346
470
|
The store_id is used for get_store_listings().
|
|
347
471
|
"""
|
|
348
472
|
url = f"{BASE_URL}/search_bff/v1/stores?q={search_query}&page={page}"
|
|
349
|
-
|
|
473
|
+
response = _make_request(url=f"{url}", token=self.token).json()
|
|
474
|
+
return StoreSearchResults.model_validate(response) if as_objects else response
|
|
350
475
|
|
|
351
476
|
@public_token
|
|
352
477
|
def get_store_listings(
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
|
|
5
|
+
### CustomSearch ###
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class CustomSearchPrice(BaseModel):
|
|
9
|
+
suffix: str
|
|
10
|
+
value: int
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class CustomSearchLocation(BaseModel):
|
|
14
|
+
image_url: str
|
|
15
|
+
label: str
|
|
16
|
+
query_key: str | None = None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class CustomSearchImage(BaseModel):
|
|
20
|
+
height: int
|
|
21
|
+
type: str
|
|
22
|
+
url: str
|
|
23
|
+
width: int
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class CustomSearchCategory(BaseModel):
|
|
27
|
+
id: str
|
|
28
|
+
name: str
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class CustomSearchResult(BaseModel):
|
|
32
|
+
ad_id: str
|
|
33
|
+
ad_status: str
|
|
34
|
+
body: str
|
|
35
|
+
category: list[CustomSearchCategory]
|
|
36
|
+
images: list[CustomSearchImage] = []
|
|
37
|
+
list_id: str
|
|
38
|
+
list_time: datetime.datetime
|
|
39
|
+
map: CustomSearchLocation | None = None
|
|
40
|
+
map_url: str | None = None
|
|
41
|
+
price: CustomSearchPrice
|
|
42
|
+
share_url: str
|
|
43
|
+
state_id: str
|
|
44
|
+
subject: str
|
|
45
|
+
type: str
|
|
46
|
+
zipcode: str | None = None
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class CustomSearchResults(BaseModel):
|
|
50
|
+
data: list[CustomSearchResult]
|
|
51
|
+
total_count: int
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
### MotorSearch ###
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class MotorSearchCarEquipment(BaseModel):
|
|
58
|
+
label: str
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class MotorSearchCarLocation(BaseModel):
|
|
62
|
+
region: str
|
|
63
|
+
municipality: str
|
|
64
|
+
area: str
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class MotorSearchCarImage(BaseModel):
|
|
68
|
+
height: int
|
|
69
|
+
width: int
|
|
70
|
+
image: str
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class MotorSearchCar(BaseModel):
|
|
74
|
+
images: list[MotorSearchCarImage]
|
|
75
|
+
location: MotorSearchCarLocation
|
|
76
|
+
fuel: str
|
|
77
|
+
gearbox: str
|
|
78
|
+
regDate: int
|
|
79
|
+
mileage: int
|
|
80
|
+
equipment: list[MotorSearchCarEquipment] | None = None
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class MotorSearchPrice(BaseModel):
|
|
84
|
+
amount: str
|
|
85
|
+
billingPeriod: str
|
|
86
|
+
oldPrice: str | None = None
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class MotorSearchSeller(BaseModel):
|
|
90
|
+
type: str
|
|
91
|
+
name: str
|
|
92
|
+
id: str
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class MotorSearchResult(BaseModel):
|
|
96
|
+
dealId: str
|
|
97
|
+
link: str
|
|
98
|
+
listTime: datetime.datetime
|
|
99
|
+
originalListTime: datetime.datetime
|
|
100
|
+
seller: MotorSearchSeller
|
|
101
|
+
heading: str
|
|
102
|
+
price: MotorSearchPrice
|
|
103
|
+
thumbnail: str
|
|
104
|
+
car: MotorSearchCar
|
|
105
|
+
description: str
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class MotorSearchResults(BaseModel):
|
|
109
|
+
cars: list[MotorSearchResult]
|
|
110
|
+
hits: int
|
|
111
|
+
pages: int
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
### StoreSearch ###
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class StoreSearchLocation(BaseModel):
|
|
118
|
+
longitude: float
|
|
119
|
+
latitude: float
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class StoreSearchImage(BaseModel):
|
|
123
|
+
height: int
|
|
124
|
+
width: int
|
|
125
|
+
url: str
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class StoreSearchLogotype(BaseModel):
|
|
129
|
+
height: int
|
|
130
|
+
width: int
|
|
131
|
+
url: str
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class StoreSearchResult(BaseModel):
|
|
135
|
+
address: str | None = None
|
|
136
|
+
id: str
|
|
137
|
+
logotype: StoreSearchLogotype
|
|
138
|
+
image: StoreSearchImage | None = None
|
|
139
|
+
description: str
|
|
140
|
+
external_store_url: str | None = None
|
|
141
|
+
location: StoreSearchLocation | None = None
|
|
142
|
+
name: str
|
|
143
|
+
title: str
|
|
144
|
+
ad_count: int
|
|
145
|
+
category: str
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class StoreSearchResults(BaseModel):
|
|
149
|
+
data: list[StoreSearchResult]
|
|
150
|
+
total_count: int
|
|
151
|
+
total_page_count: int
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: blocket_api
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.9
|
|
4
4
|
Summary: A python API wrapper for blocket.se
|
|
5
5
|
Author-email: dunderrrrrr <emil.bjorkroth@gmail.com>
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -11,12 +11,13 @@ Requires-Dist: pre-commit>=3.7.1
|
|
|
11
11
|
Requires-Dist: pytest>=8.2.2
|
|
12
12
|
Requires-Dist: respx>=0.21.1
|
|
13
13
|
Requires-Dist: mypy>=1.15.0
|
|
14
|
-
Requires-Dist:
|
|
14
|
+
Requires-Dist: pydantic>=2.11.7
|
|
15
|
+
Requires-Dist: ruff>=0.13.0
|
|
15
16
|
Dynamic: license-file
|
|
16
17
|
|
|
17
18
|
# BlocketAPI
|
|
18
19
|
|
|
19
|
-
[](https://pypi.org/project/blocket_api/) [](https://github.com/dunderrrrrr/blocket_api/blob/main/LICENSE)
|
|
20
|
+
[](https://pypi.org/project/blocket_api/) [](https://github.com/dunderrrrrr/blocket_api/blob/main/LICENSE)  
|
|
20
21
|
|
|
21
22
|
BlocketAPI allows users to query saved searches, known as "Bevakningar", on [blocket.se](https://blocket.se/). This means you can either retrieve results from a specific saved search or list all listings/ads across all saved searches. The results from these queries are returned in a `json` format.
|
|
22
23
|
|
|
@@ -55,20 +56,20 @@ Some calls require a `bearerToken`. However, some calls are public and don't req
|
|
|
55
56
|
[Where token?](#-blocket-api-token)
|
|
56
57
|
|
|
57
58
|
|
|
58
|
-
| Function | Token required | Description |
|
|
59
|
-
|
|
60
|
-
| [`api.saved_searches()`](#saved_searches) | 🔐 Yes | List your saved searches (bevakningar) |
|
|
61
|
-
| [`api.get_listings()`](#
|
|
62
|
-
| [`api.custom_search()`](#
|
|
63
|
-
| [`api.motor_search()`](#
|
|
64
|
-
| [`api.price_eval()`](#
|
|
65
|
-
| [`api.home_search()`](#
|
|
66
|
-
| [`api.store_search()`](#
|
|
67
|
-
| [`api.get_store_listings()`](#
|
|
59
|
+
| Function | Token required | `as_objects` | Description |
|
|
60
|
+
|---|---|---|---|
|
|
61
|
+
| [`api.saved_searches()`](#saved_searches) | 🔐 Yes | - | List your saved searches (bevakningar) |
|
|
62
|
+
| [`api.get_listings()`](#get_listings) | 🔐 Yes | - | List items related to a saved search |
|
|
63
|
+
| [`api.custom_search()`](#custom_search) | 👏 No | Yes | Search for everything on Blocket and filter by region |
|
|
64
|
+
| [`api.motor_search()`](#motor_search) | 👏 No | Yes | Advanced search for car-listings. |
|
|
65
|
+
| [`api.price_eval()`](#price_eval) | 👏 No | - | Vehicle purchase valuation and details. |
|
|
66
|
+
| [`api.home_search()`](#home_search) | 👏 No | - | Query home listings.
|
|
67
|
+
| [`api.store_search()`](#store_search) | 👏 No | Yes | Search for a store.
|
|
68
|
+
| [`api.get_store_listings()`](#get_store_listings) | 👏 No | - | Get listings from a specific store.
|
|
68
69
|
|
|
69
70
|
## 🤓 Detailed usage
|
|
70
71
|
|
|
71
|
-
### saved_searches
|
|
72
|
+
### saved_searches
|
|
72
73
|
|
|
73
74
|
Saved searches are your so called "Bevakningar" and can be found [here](https://www.blocket.se/sparade/bevakningar). Each saved search has and unique `id` which can be used as a parameter to `get_listings()`, see below.
|
|
74
75
|
|
|
@@ -87,7 +88,7 @@ Saved searches are your so called "Bevakningar" and can be found [here](https://
|
|
|
87
88
|
]
|
|
88
89
|
```
|
|
89
90
|
|
|
90
|
-
### get_listings
|
|
91
|
+
### get_listings
|
|
91
92
|
Returns all listings related to a saved search.
|
|
92
93
|
|
|
93
94
|
Parameters:
|
|
@@ -121,7 +122,7 @@ Parameters:
|
|
|
121
122
|
}
|
|
122
123
|
```
|
|
123
124
|
|
|
124
|
-
### custom_search
|
|
125
|
+
### custom_search
|
|
125
126
|
Make a custom search through out all of blocked. A region can be passed in as parameter for filtering.
|
|
126
127
|
|
|
127
128
|
Parameters:
|
|
@@ -129,6 +130,7 @@ Parameters:
|
|
|
129
130
|
- `region` (`enum`, optional) - Filter results on a region, default is all of Sweden.
|
|
130
131
|
- `category` (`enum`, optional) - Filter for a specific category, ex. `Category.for_hemmet`.
|
|
131
132
|
- `limit` (`int`, optional) - Limit number of results returned, max is 99.
|
|
133
|
+
- `as_objects` (`bool`, optional) - Return results as pydantic models, default is `False`.
|
|
132
134
|
|
|
133
135
|
```py
|
|
134
136
|
>>> from blocket_api import Region
|
|
@@ -162,7 +164,7 @@ Parameters:
|
|
|
162
164
|
}
|
|
163
165
|
```
|
|
164
166
|
|
|
165
|
-
### motor_search
|
|
167
|
+
### motor_search
|
|
166
168
|
To query listings related to a specific car, supply the following parameters:
|
|
167
169
|
|
|
168
170
|
- `page` (`int`, required) - Results are split in pages, set page number here.
|
|
@@ -173,6 +175,8 @@ To query listings related to a specific car, supply the following parameters:
|
|
|
173
175
|
- `modelYear` (`Optional[Tuple[int, int]]`) - Set model year range, ex. `(2000, 2020)`.
|
|
174
176
|
- `milage` (`Optional[Tuple[int, int]]`) - Set milage range, ex. `(1000, 2000)`.
|
|
175
177
|
- `gearbox` (`Optional[GEARBOX_OPTIONS]`) - Filter a specific gearbox, ex. `Automat`.
|
|
178
|
+
- `as_objects` (`bool`, optional) - Return results as pydantic models, default is `False`.
|
|
179
|
+
|
|
176
180
|
```py
|
|
177
181
|
>>> api.motor_search(
|
|
178
182
|
make=["Audi", "Ford"],
|
|
@@ -184,7 +188,7 @@ To query listings related to a specific car, supply the following parameters:
|
|
|
184
188
|
...
|
|
185
189
|
```
|
|
186
190
|
|
|
187
|
-
### price_eval
|
|
191
|
+
### price_eval
|
|
188
192
|
Query price evaluation for a specific vehicle by using cars registration number (ABC123). This returns company and private estimated prices, car information, and more. The api queries same endpoint as Blockets ["värdera bil"](https://www.blocket.se/tjanster/vardera-bil) service.
|
|
189
193
|
|
|
190
194
|
- `registration_number` (`str`, required) - Registration number of the vehicle.
|
|
@@ -203,7 +207,7 @@ Query price evaluation for a specific vehicle by using cars registration number
|
|
|
203
207
|
}
|
|
204
208
|
```
|
|
205
209
|
|
|
206
|
-
### home_search
|
|
210
|
+
### home_search
|
|
207
211
|
Query home listings from [bostad.blocket.se](https://bostad.blocket.se/).
|
|
208
212
|
|
|
209
213
|
- `city` (`str`, required) - City name, ex. Stockholm.
|
|
@@ -223,11 +227,13 @@ Query home listings from [bostad.blocket.se](https://bostad.blocket.se/).
|
|
|
223
227
|
...
|
|
224
228
|
```
|
|
225
229
|
|
|
226
|
-
### store_search
|
|
230
|
+
### store_search
|
|
227
231
|
Search for a store in Blocket stores from [blocket.se/butiker](https://www.blocket.se/butiker).
|
|
228
232
|
|
|
229
233
|
- `search_query` (`str`, required) - The name of the store.
|
|
230
234
|
- `page` (`int`, optional) - The page number to return.
|
|
235
|
+
- `as_objects` (`bool`, optional) - Return results as pydantic models, default is `False`.
|
|
236
|
+
|
|
231
237
|
|
|
232
238
|
```py
|
|
233
239
|
>>> api.store_search("Jannes Car and Kebab")
|
|
@@ -243,7 +249,7 @@ Search for a store in Blocket stores from [blocket.se/butiker](https://www.block
|
|
|
243
249
|
}
|
|
244
250
|
```
|
|
245
251
|
|
|
246
|
-
### get_store_listings
|
|
252
|
+
### get_store_listings
|
|
247
253
|
Get listings from a specific store.
|
|
248
254
|
|
|
249
255
|
- `store_id` (`int`, required) - The store id. Can be obtained by calling `store_search()`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "blocket_api"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.9"
|
|
4
4
|
description = "A python API wrapper for blocket.se"
|
|
5
5
|
authors = [{name = "dunderrrrrr", email = "emil.bjorkroth@gmail.com"}]
|
|
6
6
|
readme = "README.md"
|
|
@@ -11,7 +11,8 @@ dependencies = [
|
|
|
11
11
|
"pytest>=8.2.2",
|
|
12
12
|
"respx>=0.21.1",
|
|
13
13
|
"mypy>=1.15.0",
|
|
14
|
-
"
|
|
14
|
+
"pydantic>=2.11.7",
|
|
15
|
+
"ruff>=0.13.0",
|
|
15
16
|
]
|
|
16
17
|
|
|
17
18
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|