blocket-toolkit 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.
- blocket_toolkit-0.1.0/.github/workflows/release.yml +63 -0
- blocket_toolkit-0.1.0/.gitignore +25 -0
- blocket_toolkit-0.1.0/LICENSE +21 -0
- blocket_toolkit-0.1.0/PKG-INFO +183 -0
- blocket_toolkit-0.1.0/README.md +154 -0
- blocket_toolkit-0.1.0/pyproject.toml +53 -0
- blocket_toolkit-0.1.0/skills/blocket-toolkit/SKILL.md +321 -0
- blocket_toolkit-0.1.0/src/blocket_toolkit/__init__.py +6 -0
- blocket_toolkit-0.1.0/src/blocket_toolkit/cli.py +563 -0
- blocket_toolkit-0.1.0/src/blocket_toolkit/client.py +366 -0
- blocket_toolkit-0.1.0/src/blocket_toolkit/enums.py +114 -0
- blocket_toolkit-0.1.0/src/blocket_toolkit/format.py +96 -0
- blocket_toolkit-0.1.0/tests/test_cli.py +150 -0
- blocket_toolkit-0.1.0/tests/test_client.py +185 -0
- blocket_toolkit-0.1.0/tests/test_enums.py +64 -0
- blocket_toolkit-0.1.0/tests/test_live.py +44 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
name: Build sdist and wheel
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout
|
|
17
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
18
|
+
|
|
19
|
+
- name: Install uv
|
|
20
|
+
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
|
|
21
|
+
with:
|
|
22
|
+
enable-cache: false
|
|
23
|
+
|
|
24
|
+
- name: Build distributions
|
|
25
|
+
run: uv build
|
|
26
|
+
|
|
27
|
+
- name: Check metadata and README rendering
|
|
28
|
+
run: uvx twine check dist/*
|
|
29
|
+
|
|
30
|
+
- name: Upload distributions
|
|
31
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
32
|
+
with:
|
|
33
|
+
name: dist
|
|
34
|
+
path: dist/
|
|
35
|
+
if-no-files-found: error
|
|
36
|
+
|
|
37
|
+
publish:
|
|
38
|
+
name: Publish to PyPI
|
|
39
|
+
needs: build
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
environment:
|
|
42
|
+
name: pypi
|
|
43
|
+
url: https://pypi.org/p/blocket-toolkit
|
|
44
|
+
permissions:
|
|
45
|
+
id-token: write
|
|
46
|
+
contents: read
|
|
47
|
+
steps:
|
|
48
|
+
- name: Download distributions
|
|
49
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
50
|
+
with:
|
|
51
|
+
name: dist
|
|
52
|
+
path: dist/
|
|
53
|
+
|
|
54
|
+
- name: Install uv
|
|
55
|
+
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
|
|
56
|
+
with:
|
|
57
|
+
enable-cache: false
|
|
58
|
+
|
|
59
|
+
- name: Generate PEP 740 attestations
|
|
60
|
+
uses: astral-sh/attest-action@f589a42a7efb6fe400b4f400de60b4bc90390027 # v0.0.6
|
|
61
|
+
|
|
62
|
+
- name: Publish to PyPI
|
|
63
|
+
run: uv publish --trusted-publishing always
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
build/
|
|
6
|
+
dist/
|
|
7
|
+
.eggs/
|
|
8
|
+
|
|
9
|
+
# Environments
|
|
10
|
+
.venv/
|
|
11
|
+
venv/
|
|
12
|
+
env/
|
|
13
|
+
|
|
14
|
+
# Tooling
|
|
15
|
+
.pytest_cache/
|
|
16
|
+
.ruff_cache/
|
|
17
|
+
.mypy_cache/
|
|
18
|
+
.coverage
|
|
19
|
+
htmlcov/
|
|
20
|
+
|
|
21
|
+
# OS
|
|
22
|
+
.DS_Store
|
|
23
|
+
|
|
24
|
+
# Output
|
|
25
|
+
*.jsonl
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Daniel Hidefjäll
|
|
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,183 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: blocket-toolkit
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Search all of Blocket.se from the terminal: general items, cars, boats and motorcycles.
|
|
5
|
+
Project-URL: Homepage, https://github.com/dojje/blocket-toolkit
|
|
6
|
+
Project-URL: Repository, https://github.com/dojje/blocket-toolkit
|
|
7
|
+
Project-URL: Issues, https://github.com/dojje/blocket-toolkit/issues
|
|
8
|
+
Author: Daniel Hidefjäll
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: blocket,boats,cars,cli,marketplace,second-hand,sweden
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
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: Topic :: Utilities
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Requires-Dist: blocket-api>=0.5.2
|
|
24
|
+
Requires-Dist: httpx>=0.28.1
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# blocket-toolkit
|
|
31
|
+
|
|
32
|
+
Search **all of Blocket.se** from the terminal: general items (*torget*), cars, boats
|
|
33
|
+
and motorcycles, with clean JSON output that is easy to pipe into other tools or hand
|
|
34
|
+
to an LLM.
|
|
35
|
+
|
|
36
|
+
Built on top of the [`blocket-api`](https://pypi.org/project/blocket_api/) Python
|
|
37
|
+
package.
|
|
38
|
+
|
|
39
|
+
## Features
|
|
40
|
+
|
|
41
|
+
- **Everything on Blocket**: torget, cars, boats, motorcycles and full ad details.
|
|
42
|
+
- **Full filter surface**: category + subcategory, all 21 regions, price, year, milage,
|
|
43
|
+
horsepower, colour, gearbox, wheel drive, length, engine volume, brand/model.
|
|
44
|
+
- **AI-friendly output**: compacted, flat JSON by default; `jsonl` and text `table` when
|
|
45
|
+
you want them.
|
|
46
|
+
- **Self-documenting enums**: every category, subcategory, region, brand and model can
|
|
47
|
+
be listed or resolved by name *or* by Blocket's internal id.
|
|
48
|
+
- **Pagination**: `--page`, `-n/--limit`, or `--all`.
|
|
49
|
+
|
|
50
|
+
## Install
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
uv tool install blocket-toolkit # or: pip install blocket-toolkit
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
From a checkout:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
git clone https://github.com/dojje/blocket-toolkit
|
|
60
|
+
cd blocket-toolkit
|
|
61
|
+
uv venv && uv pip install -e '.[dev]'
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Quick start
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
blocket-toolkit search "kindle" --price-max 800 --sort price_asc
|
|
68
|
+
|
|
69
|
+
blocket-toolkit search "grafikkort" -c elektronik_och_vitvaror --sub-category datorer -n 5
|
|
70
|
+
|
|
71
|
+
blocket-toolkit cars --model volvo --year-min 2018 --mileage-max 12000 --sort mileage_asc
|
|
72
|
+
|
|
73
|
+
blocket-toolkit boats --type segelbat_motorseglare --length-min 30
|
|
74
|
+
|
|
75
|
+
blocket-toolkit mc --model yamaha --engine-min 600 --price-max 80000
|
|
76
|
+
|
|
77
|
+
blocket-toolkit ad 20851738 --type recommerce
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Every command accepts `-o json|jsonl|table` (default `json`).
|
|
81
|
+
|
|
82
|
+
## Commands
|
|
83
|
+
|
|
84
|
+
| Command | What it does |
|
|
85
|
+
|---|---|
|
|
86
|
+
| `search <query>` | General items on torget |
|
|
87
|
+
| `cars [query]` | Used cars |
|
|
88
|
+
| `boats [query]` | Used boats |
|
|
89
|
+
| `mc [query]` | Used motorcycles |
|
|
90
|
+
| `ad <ad_id> --type ...` | Full details for one listing |
|
|
91
|
+
| `categories` | All 11 top-level categories |
|
|
92
|
+
| `subcategories [-c CATEGORY]` | All subcategories, optionally for one category |
|
|
93
|
+
| `locations` | All 21 Swedish regions |
|
|
94
|
+
| `car-options` | Car brands, colours, gearboxes, wheel drives, sort orders |
|
|
95
|
+
| `boat-options` | Boat types and sort orders |
|
|
96
|
+
| `mc-options` | MC brands, types and sort orders |
|
|
97
|
+
|
|
98
|
+
Run `blocket-toolkit <command> --help` for the full filter list.
|
|
99
|
+
|
|
100
|
+
### Common flags
|
|
101
|
+
|
|
102
|
+
| Flag | Applies to | Meaning |
|
|
103
|
+
|---|---|---|
|
|
104
|
+
| `-c, --category` | `search` | Category name or id (e.g. `elektronik_och_vitvaror` or `0.93`) |
|
|
105
|
+
| `--sub-category` | `search` | Subcategory name or id (mutually exclusive with `--category`) |
|
|
106
|
+
| `-l, --location` | all searches | Region(s), repeatable or comma-separated (`-l stockholm,skane`) |
|
|
107
|
+
| `--sort` | all searches | Sort order; valid values depend on the command |
|
|
108
|
+
| `--price-min/--price-max` | `search`, `cars`, `boats`, `mc` | Price range in SEK |
|
|
109
|
+
| `--newer-than HOURS` | `search` | Only ads published within the last N hours |
|
|
110
|
+
| `--page`, `-n/--limit`, `--all` | all searches | Pagination |
|
|
111
|
+
| `-o, --output` | everything | `json` (default), `jsonl`, `table` |
|
|
112
|
+
| `--raw` | searches | Return Blocket's raw objects instead of compacted records |
|
|
113
|
+
|
|
114
|
+
> `--price-min/--price-max` and `--newer-than` are applied **client-side** for torget,
|
|
115
|
+
> because Blocket's general search endpoint has no server-side price filter. For cars,
|
|
116
|
+
> boats and motorcycles the price range is sent to the API.
|
|
117
|
+
|
|
118
|
+
## Output shape
|
|
119
|
+
|
|
120
|
+
Search commands return:
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"page": 1,
|
|
125
|
+
"last_page": 20,
|
|
126
|
+
"total": 1187,
|
|
127
|
+
"count": 40,
|
|
128
|
+
"items": [
|
|
129
|
+
{
|
|
130
|
+
"id": 20851738,
|
|
131
|
+
"heading": "Kindle Paperwhite 11th gen",
|
|
132
|
+
"price": 750,
|
|
133
|
+
"location": "Stockholm",
|
|
134
|
+
"url": "https://www.blocket.se/annons/20851738",
|
|
135
|
+
"image_url": "https://...",
|
|
136
|
+
"timestamp": 1700000000000,
|
|
137
|
+
"published_at": "2023-11-14T22:13:20+00:00"
|
|
138
|
+
}
|
|
139
|
+
]
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
`ad` returns the full payload for a single listing.
|
|
144
|
+
|
|
145
|
+
## Finding valid filter values
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
blocket-toolkit categories -o table
|
|
149
|
+
blocket-toolkit subcategories -c elektronik_och_vitvaror -o table
|
|
150
|
+
blocket-toolkit locations -o table
|
|
151
|
+
blocket-toolkit car-options -o table
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Values are resolved case-insensitively and accept spaces or dashes, so
|
|
155
|
+
`ELEKTRONIK_OCH_VITVAROR`, `elektronik och vitvaror` and `0.93` are all valid.
|
|
156
|
+
|
|
157
|
+
## Development
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
uv venv && uv pip install -e '.[dev]'
|
|
161
|
+
pytest # unit tests (no network)
|
|
162
|
+
pytest -m live # smoke tests against the real Blocket API
|
|
163
|
+
ruff check .
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Notes and limitations
|
|
167
|
+
|
|
168
|
+
- Blocket has no official public API; this uses the same internal endpoints as the
|
|
169
|
+
website. Be gentle: don't hammer it with `--all --max-pages 200`.
|
|
170
|
+
- Torget's search endpoint does not accept a result count, so `-n/--limit` and
|
|
171
|
+
`--price-*` are applied after fetching.
|
|
172
|
+
- `ad` for `car`/`boat`/`mc` scrapes the mobility page and returns somewhat less
|
|
173
|
+
structured data than `recommerce`.
|
|
174
|
+
|
|
175
|
+
## Credits
|
|
176
|
+
|
|
177
|
+
- [`blocket-api`](https://github.com/dunderrrrrr/blocket_api) by dunderrrrrr, the
|
|
178
|
+
underlying API wrapper.
|
|
179
|
+
- Blocket.se, obviously, for the data.
|
|
180
|
+
|
|
181
|
+
## License
|
|
182
|
+
|
|
183
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# blocket-toolkit
|
|
2
|
+
|
|
3
|
+
Search **all of Blocket.se** from the terminal: general items (*torget*), cars, boats
|
|
4
|
+
and motorcycles, with clean JSON output that is easy to pipe into other tools or hand
|
|
5
|
+
to an LLM.
|
|
6
|
+
|
|
7
|
+
Built on top of the [`blocket-api`](https://pypi.org/project/blocket_api/) Python
|
|
8
|
+
package.
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- **Everything on Blocket**: torget, cars, boats, motorcycles and full ad details.
|
|
13
|
+
- **Full filter surface**: category + subcategory, all 21 regions, price, year, milage,
|
|
14
|
+
horsepower, colour, gearbox, wheel drive, length, engine volume, brand/model.
|
|
15
|
+
- **AI-friendly output**: compacted, flat JSON by default; `jsonl` and text `table` when
|
|
16
|
+
you want them.
|
|
17
|
+
- **Self-documenting enums**: every category, subcategory, region, brand and model can
|
|
18
|
+
be listed or resolved by name *or* by Blocket's internal id.
|
|
19
|
+
- **Pagination**: `--page`, `-n/--limit`, or `--all`.
|
|
20
|
+
|
|
21
|
+
## Install
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
uv tool install blocket-toolkit # or: pip install blocket-toolkit
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
From a checkout:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
git clone https://github.com/dojje/blocket-toolkit
|
|
31
|
+
cd blocket-toolkit
|
|
32
|
+
uv venv && uv pip install -e '.[dev]'
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Quick start
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
blocket-toolkit search "kindle" --price-max 800 --sort price_asc
|
|
39
|
+
|
|
40
|
+
blocket-toolkit search "grafikkort" -c elektronik_och_vitvaror --sub-category datorer -n 5
|
|
41
|
+
|
|
42
|
+
blocket-toolkit cars --model volvo --year-min 2018 --mileage-max 12000 --sort mileage_asc
|
|
43
|
+
|
|
44
|
+
blocket-toolkit boats --type segelbat_motorseglare --length-min 30
|
|
45
|
+
|
|
46
|
+
blocket-toolkit mc --model yamaha --engine-min 600 --price-max 80000
|
|
47
|
+
|
|
48
|
+
blocket-toolkit ad 20851738 --type recommerce
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Every command accepts `-o json|jsonl|table` (default `json`).
|
|
52
|
+
|
|
53
|
+
## Commands
|
|
54
|
+
|
|
55
|
+
| Command | What it does |
|
|
56
|
+
|---|---|
|
|
57
|
+
| `search <query>` | General items on torget |
|
|
58
|
+
| `cars [query]` | Used cars |
|
|
59
|
+
| `boats [query]` | Used boats |
|
|
60
|
+
| `mc [query]` | Used motorcycles |
|
|
61
|
+
| `ad <ad_id> --type ...` | Full details for one listing |
|
|
62
|
+
| `categories` | All 11 top-level categories |
|
|
63
|
+
| `subcategories [-c CATEGORY]` | All subcategories, optionally for one category |
|
|
64
|
+
| `locations` | All 21 Swedish regions |
|
|
65
|
+
| `car-options` | Car brands, colours, gearboxes, wheel drives, sort orders |
|
|
66
|
+
| `boat-options` | Boat types and sort orders |
|
|
67
|
+
| `mc-options` | MC brands, types and sort orders |
|
|
68
|
+
|
|
69
|
+
Run `blocket-toolkit <command> --help` for the full filter list.
|
|
70
|
+
|
|
71
|
+
### Common flags
|
|
72
|
+
|
|
73
|
+
| Flag | Applies to | Meaning |
|
|
74
|
+
|---|---|---|
|
|
75
|
+
| `-c, --category` | `search` | Category name or id (e.g. `elektronik_och_vitvaror` or `0.93`) |
|
|
76
|
+
| `--sub-category` | `search` | Subcategory name or id (mutually exclusive with `--category`) |
|
|
77
|
+
| `-l, --location` | all searches | Region(s), repeatable or comma-separated (`-l stockholm,skane`) |
|
|
78
|
+
| `--sort` | all searches | Sort order; valid values depend on the command |
|
|
79
|
+
| `--price-min/--price-max` | `search`, `cars`, `boats`, `mc` | Price range in SEK |
|
|
80
|
+
| `--newer-than HOURS` | `search` | Only ads published within the last N hours |
|
|
81
|
+
| `--page`, `-n/--limit`, `--all` | all searches | Pagination |
|
|
82
|
+
| `-o, --output` | everything | `json` (default), `jsonl`, `table` |
|
|
83
|
+
| `--raw` | searches | Return Blocket's raw objects instead of compacted records |
|
|
84
|
+
|
|
85
|
+
> `--price-min/--price-max` and `--newer-than` are applied **client-side** for torget,
|
|
86
|
+
> because Blocket's general search endpoint has no server-side price filter. For cars,
|
|
87
|
+
> boats and motorcycles the price range is sent to the API.
|
|
88
|
+
|
|
89
|
+
## Output shape
|
|
90
|
+
|
|
91
|
+
Search commands return:
|
|
92
|
+
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"page": 1,
|
|
96
|
+
"last_page": 20,
|
|
97
|
+
"total": 1187,
|
|
98
|
+
"count": 40,
|
|
99
|
+
"items": [
|
|
100
|
+
{
|
|
101
|
+
"id": 20851738,
|
|
102
|
+
"heading": "Kindle Paperwhite 11th gen",
|
|
103
|
+
"price": 750,
|
|
104
|
+
"location": "Stockholm",
|
|
105
|
+
"url": "https://www.blocket.se/annons/20851738",
|
|
106
|
+
"image_url": "https://...",
|
|
107
|
+
"timestamp": 1700000000000,
|
|
108
|
+
"published_at": "2023-11-14T22:13:20+00:00"
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
`ad` returns the full payload for a single listing.
|
|
115
|
+
|
|
116
|
+
## Finding valid filter values
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
blocket-toolkit categories -o table
|
|
120
|
+
blocket-toolkit subcategories -c elektronik_och_vitvaror -o table
|
|
121
|
+
blocket-toolkit locations -o table
|
|
122
|
+
blocket-toolkit car-options -o table
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Values are resolved case-insensitively and accept spaces or dashes, so
|
|
126
|
+
`ELEKTRONIK_OCH_VITVAROR`, `elektronik och vitvaror` and `0.93` are all valid.
|
|
127
|
+
|
|
128
|
+
## Development
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
uv venv && uv pip install -e '.[dev]'
|
|
132
|
+
pytest # unit tests (no network)
|
|
133
|
+
pytest -m live # smoke tests against the real Blocket API
|
|
134
|
+
ruff check .
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Notes and limitations
|
|
138
|
+
|
|
139
|
+
- Blocket has no official public API; this uses the same internal endpoints as the
|
|
140
|
+
website. Be gentle: don't hammer it with `--all --max-pages 200`.
|
|
141
|
+
- Torget's search endpoint does not accept a result count, so `-n/--limit` and
|
|
142
|
+
`--price-*` are applied after fetching.
|
|
143
|
+
- `ad` for `car`/`boat`/`mc` scrapes the mobility page and returns somewhat less
|
|
144
|
+
structured data than `recommerce`.
|
|
145
|
+
|
|
146
|
+
## Credits
|
|
147
|
+
|
|
148
|
+
- [`blocket-api`](https://github.com/dunderrrrrr/blocket_api) by dunderrrrrr, the
|
|
149
|
+
underlying API wrapper.
|
|
150
|
+
- Blocket.se, obviously, for the data.
|
|
151
|
+
|
|
152
|
+
## License
|
|
153
|
+
|
|
154
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "blocket-toolkit"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Search all of Blocket.se from the terminal: general items, cars, boats and motorcycles."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [{ name = "Daniel Hidefjäll" }]
|
|
14
|
+
keywords = ["blocket", "cli", "marketplace", "sweden", "second-hand", "cars", "boats"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 3 - Alpha",
|
|
17
|
+
"Environment :: Console",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
"Topic :: Utilities",
|
|
26
|
+
]
|
|
27
|
+
dependencies = ["blocket-api>=0.5.2", "httpx>=0.28.1"]
|
|
28
|
+
|
|
29
|
+
[project.optional-dependencies]
|
|
30
|
+
dev = ["pytest>=8.0", "ruff>=0.6"]
|
|
31
|
+
|
|
32
|
+
[project.urls]
|
|
33
|
+
Homepage = "https://github.com/dojje/blocket-toolkit"
|
|
34
|
+
Repository = "https://github.com/dojje/blocket-toolkit"
|
|
35
|
+
Issues = "https://github.com/dojje/blocket-toolkit/issues"
|
|
36
|
+
|
|
37
|
+
[project.scripts]
|
|
38
|
+
blocket-toolkit = "blocket_toolkit.cli:main"
|
|
39
|
+
|
|
40
|
+
[tool.hatch.build.targets.wheel]
|
|
41
|
+
packages = ["src/blocket_toolkit"]
|
|
42
|
+
|
|
43
|
+
[tool.pytest.ini_options]
|
|
44
|
+
testpaths = ["tests"]
|
|
45
|
+
markers = ["live: tests that hit the real Blocket API (deselected by default)"]
|
|
46
|
+
addopts = "-m 'not live'"
|
|
47
|
+
|
|
48
|
+
[tool.ruff]
|
|
49
|
+
line-length = 100
|
|
50
|
+
target-version = "py310"
|
|
51
|
+
|
|
52
|
+
[tool.ruff.lint]
|
|
53
|
+
select = ["E", "F", "I", "UP", "B"]
|