scrapebadger-cli 0.18.0__tar.gz → 0.20.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.
Files changed (53) hide show
  1. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/PKG-INFO +1 -1
  2. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/pyproject.toml +1 -1
  3. scrapebadger_cli-0.20.0/src/scrapebadger_cli/commands/gumtree.py +149 -0
  4. scrapebadger_cli-0.20.0/src/scrapebadger_cli/commands/wallapop.py +200 -0
  5. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/main.py +4 -0
  6. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/uv.lock +1 -1
  7. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/.gitignore +0 -0
  8. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/README.md +0 -0
  9. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/__init__.py +0 -0
  10. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/client.py +0 -0
  11. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/__init__.py +0 -0
  12. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/airbnb.py +0 -0
  13. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/amazon.py +0 -0
  14. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/apartments.py +0 -0
  15. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/app_store.py +0 -0
  16. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/auth.py +0 -0
  17. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/baidu.py +0 -0
  18. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/bing.py +0 -0
  19. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/booking.py +0 -0
  20. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/chatgpt.py +0 -0
  21. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/depop.py +0 -0
  22. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/duckduckgo.py +0 -0
  23. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/ebay.py +0 -0
  24. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/facebook.py +0 -0
  25. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/gemini.py +0 -0
  26. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/google.py +0 -0
  27. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/google_play.py +0 -0
  28. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/idealista.py +0 -0
  29. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/immobiliare.py +0 -0
  30. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/instagram.py +0 -0
  31. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/leboncoin.py +0 -0
  32. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/linkedin.py +0 -0
  33. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/loopnet.py +0 -0
  34. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/naver.py +0 -0
  35. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/perplexity.py +0 -0
  36. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/realtor.py +0 -0
  37. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/reddit.py +0 -0
  38. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/redfin.py +0 -0
  39. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/stream.py +0 -0
  40. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/tiktok.py +0 -0
  41. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/twitter.py +0 -0
  42. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/vinted.py +0 -0
  43. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/walmart.py +0 -0
  44. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/web.py +0 -0
  45. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/yahoo.py +0 -0
  46. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/yandex.py +0 -0
  47. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/youtube.py +0 -0
  48. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/commands/zillow.py +0 -0
  49. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/config.py +0 -0
  50. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/src/scrapebadger_cli/output.py +0 -0
  51. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/tests/test_naver.py +0 -0
  52. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/tests/test_tiktok_pagination.py +0 -0
  53. {scrapebadger_cli-0.18.0 → scrapebadger_cli-0.20.0}/tests/test_vinted_image_search.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: scrapebadger-cli
3
- Version: 0.18.0
3
+ Version: 0.20.0
4
4
  Summary: ScrapeBadger CLI — Twitter, Vinted, Google, and Web Scraping from the command line
5
5
  Author: ScrapeBadger Team
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "scrapebadger-cli"
3
- version = "0.18.0"
3
+ version = "0.20.0"
4
4
  description = "ScrapeBadger CLI — Twitter, Vinted, Google, and Web Scraping from the command line"
5
5
  requires-python = ">=3.10"
6
6
  license = {text = "MIT"}
@@ -0,0 +1,149 @@
1
+ """Gumtree (UK classifieds) commands. gumtree.com only — no market option."""
2
+
3
+ import typer
4
+
5
+ from scrapebadger_cli.client import api_get
6
+ from scrapebadger_cli.output import render
7
+
8
+ app = typer.Typer(no_args_is_help=True)
9
+
10
+ FMT = typer.Option("json", "--output", "-o", help="Output format: json, csv, table, markdown")
11
+ FIELDS = typer.Option(None, "--fields", "-f", help="Comma-separated fields to include")
12
+
13
+ SORT_HELP = "relevance, date, price_asc, price_desc, distance"
14
+
15
+ _LISTING_COLS = "id,title,price_text,location,posted_text,seller_type"
16
+ _TREE_COLS = "id,name,slug,has_children"
17
+
18
+
19
+ def _show(
20
+ data: object, fmt: str, fields: str | None, table_cols: str, key: str | None = None
21
+ ) -> None:
22
+ """Render, defaulting the columns for the human formats only (see walmart.py)."""
23
+ if fmt in ("table", "markdown"):
24
+ if key and isinstance(data, dict):
25
+ data = data.get(key, data)
26
+ fields = fields or table_cols
27
+ render(data, fmt, fields)
28
+
29
+
30
+ @app.command()
31
+ def search(
32
+ query: str | None = typer.Argument(None, help="Search keywords, e.g. 'mountain bike'"),
33
+ category: str = typer.Option("all", "--category", "-c", help="e.g. cars, for-sale, jobs"),
34
+ location: str = typer.Option("uk", "--location", "-l", help="Town slug or UK postcode"),
35
+ distance: float | None = typer.Option(None, "--distance", "-d", help="Radius in miles"),
36
+ min_price: int | None = typer.Option(None, "--min-price", help="GBP; needs a category"),
37
+ max_price: int | None = typer.Option(None, "--max-price", help="GBP; needs a category"),
38
+ sort: str | None = typer.Option(None, "--sort", "-s", help=SORT_HELP),
39
+ seller_type: str | None = typer.Option(None, "--seller-type", help="private or trade"),
40
+ urgent_only: bool = typer.Option(False, "--urgent-only"),
41
+ with_photos: bool = typer.Option(False, "--with-photos"),
42
+ filters: str | None = typer.Option(
43
+ None, "--filters", help="key:value pairs, e.g. 'vehicle_make:bmw,vehicle_fuel_type:petrol'"
44
+ ),
45
+ page: int = typer.Option(1, "--page", "-p", help="1-50"),
46
+ fmt: str = FMT,
47
+ fields: str | None = FIELDS,
48
+ ) -> None:
49
+ """Search Gumtree UK listings."""
50
+ data = api_get(
51
+ "/v1/gumtree/search",
52
+ {
53
+ "query": query,
54
+ "category": category,
55
+ "location": location,
56
+ "distance": distance,
57
+ "min_price": min_price,
58
+ "max_price": max_price,
59
+ "sort": sort,
60
+ "seller_type": seller_type,
61
+ "urgent_only": urgent_only or None,
62
+ "with_photos": with_photos or None,
63
+ "filters": filters,
64
+ "page": page,
65
+ },
66
+ )
67
+ _show(data, fmt, fields, _LISTING_COLS, "listings")
68
+
69
+
70
+ @app.command()
71
+ def filters(
72
+ category: str = typer.Argument("all", help="Category slug, e.g. 'cars'"),
73
+ location: str = typer.Option("uk", "--location", "-l"),
74
+ query: str | None = typer.Option(None, "--query", "-q"),
75
+ fmt: str = FMT,
76
+ fields: str | None = FIELDS,
77
+ ) -> None:
78
+ """List the filters Gumtree offers for a category, with live counts."""
79
+ data = api_get(
80
+ "/v1/gumtree/search/filters",
81
+ {"category": category, "location": location, "query": query},
82
+ )
83
+ _show(data, fmt, fields, "key,label,type,min_key,max_key", "filters")
84
+
85
+
86
+ @app.command()
87
+ def listing(
88
+ listing_id: str = typer.Argument(..., help="Listing id from a gumtree.com/p/... URL"),
89
+ fmt: str = FMT,
90
+ fields: str | None = FIELDS,
91
+ ) -> None:
92
+ """Get a full Gumtree listing."""
93
+ render(api_get(f"/v1/gumtree/listings/{listing_id}"), fmt, fields)
94
+
95
+
96
+ @app.command("seller-listings")
97
+ def seller_listings(
98
+ listing_id: str = typer.Argument(..., help="Any listing id of the seller"),
99
+ page: int = typer.Option(1, "--page", "-p", help="1-50"),
100
+ fmt: str = FMT,
101
+ fields: str | None = FIELDS,
102
+ ) -> None:
103
+ """Every live listing by the seller of a listing."""
104
+ data = api_get(f"/v1/gumtree/listings/{listing_id}/seller-listings", {"page": page})
105
+ _show(data, fmt, fields, _LISTING_COLS, "listings")
106
+
107
+
108
+ @app.command()
109
+ def autocomplete(
110
+ query: str = typer.Argument(..., help="Partial search term, e.g. 'iph'"),
111
+ fmt: str = FMT,
112
+ fields: str | None = FIELDS,
113
+ ) -> None:
114
+ """Gumtree search suggestions."""
115
+ data = api_get("/v1/gumtree/autocomplete", {"query": query})
116
+ _show(data, fmt, fields, "query,highlighted", "suggestions")
117
+
118
+
119
+ @app.command("locations-autocomplete")
120
+ def locations_autocomplete(
121
+ query: str = typer.Argument(..., help="Town or postcode prefix, e.g. 'manch'"),
122
+ fmt: str = FMT,
123
+ fields: str | None = FIELDS,
124
+ ) -> None:
125
+ """Resolve a UK town or postcode prefix to Gumtree locations."""
126
+ data = api_get("/v1/gumtree/locations/autocomplete", {"query": query})
127
+ _show(data, fmt, fields, "id,name,type,latitude,longitude", "locations")
128
+
129
+
130
+ @app.command()
131
+ def locations(
132
+ parent_id: int | None = typer.Option(None, "--parent-id", help="Default: United Kingdom"),
133
+ fmt: str = FMT,
134
+ fields: str | None = FIELDS,
135
+ ) -> None:
136
+ """Browse Gumtree's location tree."""
137
+ data = api_get("/v1/gumtree/locations", {"parent_id": parent_id})
138
+ _show(data, fmt, fields, _TREE_COLS, "children")
139
+
140
+
141
+ @app.command()
142
+ def categories(
143
+ parent_id: int | None = typer.Option(None, "--parent-id", help="Default: all categories"),
144
+ fmt: str = FMT,
145
+ fields: str | None = FIELDS,
146
+ ) -> None:
147
+ """Browse Gumtree's category tree."""
148
+ data = api_get("/v1/gumtree/categories", {"parent_id": parent_id})
149
+ _show(data, fmt, fields, _TREE_COLS, "children")
@@ -0,0 +1,200 @@
1
+ """Wallapop marketplace commands."""
2
+
3
+ import typer
4
+
5
+ from scrapebadger_cli.client import api_get
6
+ from scrapebadger_cli.output import render
7
+
8
+ app = typer.Typer(no_args_is_help=True)
9
+
10
+ FMT = typer.Option("json", "--output", "-o", help="Output format: json, csv, table, markdown")
11
+ FIELDS = typer.Option(None, "--fields", "-f", help="Comma-separated fields to include")
12
+ MARKET = typer.Option("es", "--market", "-m", help="es, it, pt")
13
+ NEXT_PAGE = typer.Option(None, "--next-page", help="Cursor from the previous page")
14
+ USER_ID = typer.Argument(..., help="User id (dqjwdd53wwzo) or profile slug (alexc-25115753)")
15
+
16
+
17
+ @app.command()
18
+ def search(
19
+ query: str | None = typer.Argument(None, help='Search text (e.g. "iphone 14")'),
20
+ market: str = MARKET,
21
+ category_id: int | None = typer.Option(None, "--category-id", help="See `categories`"),
22
+ min_price: float | None = typer.Option(None, "--min-price"),
23
+ max_price: float | None = typer.Option(None, "--max-price"),
24
+ condition: str | None = typer.Option(
25
+ None,
26
+ "--condition",
27
+ help="CSV: un_opened, in_box, new, as_good_as_new, good, fair, has_given_it_all",
28
+ ),
29
+ brand: str | None = typer.Option(None, "--brand", help="e.g. Apple"),
30
+ model: str | None = typer.Option(None, "--model", help="e.g. iPhone 14"),
31
+ color: str | None = typer.Option(None, "--color", help="Colour id, e.g. black"),
32
+ latitude: float | None = typer.Option(None, "--lat", help="Search centre latitude"),
33
+ longitude: float | None = typer.Option(None, "--lng", help="Search centre longitude"),
34
+ distance_km: int | None = typer.Option(None, "--distance-km", help="Radius (1-500)"),
35
+ time_filter: str | None = typer.Option(
36
+ None, "--time-filter", help="today, lastWeek, lastMonth"
37
+ ),
38
+ shippable: bool = typer.Option(False, "--shippable", help="Only listings that ship"),
39
+ has_warranty: bool = typer.Option(False, "--has-warranty", help="Only with a warranty"),
40
+ refurbished: bool = typer.Option(False, "--refurbished", help="Only refurbished listings"),
41
+ min_year: int | None = typer.Option(None, "--min-year", help="Cars"),
42
+ max_year: int | None = typer.Option(None, "--max-year", help="Cars"),
43
+ min_km: int | None = typer.Option(None, "--min-km", help="Cars"),
44
+ max_km: int | None = typer.Option(None, "--max-km", help="Cars"),
45
+ gearbox: str | None = typer.Option(None, "--gearbox", help="Cars: manual or automatic"),
46
+ min_horsepower: int | None = typer.Option(None, "--min-horsepower", help="Cars"),
47
+ max_horsepower: int | None = typer.Option(None, "--max-horsepower", help="Cars"),
48
+ order_by: str | None = typer.Option(
49
+ None,
50
+ "--order-by",
51
+ help="most_relevance, newest, closest, price_low_to_high, price_high_to_low",
52
+ ),
53
+ next_page: str | None = NEXT_PAGE,
54
+ fmt: str = FMT,
55
+ fields: str | None = FIELDS,
56
+ ) -> None:
57
+ """Search Wallapop listings (needs a query or --category-id)."""
58
+ data = api_get(
59
+ "/v1/wallapop/search",
60
+ {
61
+ "query": query,
62
+ "market": market,
63
+ "category_id": category_id,
64
+ "min_price": min_price,
65
+ "max_price": max_price,
66
+ "condition": condition,
67
+ "brand": brand,
68
+ "model": model,
69
+ "color": color,
70
+ "latitude": latitude,
71
+ "longitude": longitude,
72
+ "distance_km": distance_km,
73
+ "time_filter": time_filter,
74
+ "shippable": "true" if shippable else None,
75
+ "has_warranty": "true" if has_warranty else None,
76
+ "refurbished": "true" if refurbished else None,
77
+ "min_year": min_year,
78
+ "max_year": max_year,
79
+ "min_km": min_km,
80
+ "max_km": max_km,
81
+ "gearbox": gearbox,
82
+ "min_horsepower": min_horsepower,
83
+ "max_horsepower": max_horsepower,
84
+ "order_by": order_by,
85
+ "next_page": next_page,
86
+ },
87
+ )
88
+ render(data, fmt, fields)
89
+
90
+
91
+ @app.command()
92
+ def item(
93
+ item_id: str = typer.Argument(..., help="Listing id, slug or wallapop.com URL"),
94
+ market: str = MARKET,
95
+ fmt: str = FMT,
96
+ fields: str | None = FIELDS,
97
+ ) -> None:
98
+ """Get a Wallapop listing's full detail."""
99
+ data = api_get(f"/v1/wallapop/items/{item_id}", {"market": market})
100
+ render(data, fmt, fields)
101
+
102
+
103
+ @app.command()
104
+ def user(
105
+ user_id: str = USER_ID,
106
+ market: str = MARKET,
107
+ fmt: str = FMT,
108
+ fields: str | None = FIELDS,
109
+ ) -> None:
110
+ """Get a Wallapop seller profile (ratings, sales, verifications)."""
111
+ data = api_get(f"/v1/wallapop/users/{user_id}", {"market": market})
112
+ render(data, fmt, fields)
113
+
114
+
115
+ @app.command("user-items")
116
+ def user_items(
117
+ user_id: str = USER_ID,
118
+ market: str = MARKET,
119
+ next_page: str | None = NEXT_PAGE,
120
+ fmt: str = FMT,
121
+ fields: str | None = FIELDS,
122
+ ) -> None:
123
+ """Get a Wallapop seller's live listings."""
124
+ data = api_get(
125
+ f"/v1/wallapop/users/{user_id}/items", {"market": market, "next_page": next_page}
126
+ )
127
+ render(data, fmt, fields)
128
+
129
+
130
+ @app.command("user-reviews")
131
+ def user_reviews(
132
+ user_id: str = USER_ID,
133
+ market: str = MARKET,
134
+ next_page: str | None = NEXT_PAGE,
135
+ fmt: str = FMT,
136
+ fields: str | None = FIELDS,
137
+ ) -> None:
138
+ """Get the reviews a Wallapop seller received, newest first."""
139
+ data = api_get(
140
+ f"/v1/wallapop/users/{user_id}/reviews", {"market": market, "next_page": next_page}
141
+ )
142
+ render(data, fmt, fields)
143
+
144
+
145
+ @app.command()
146
+ def autocomplete(
147
+ query: str = typer.Argument(..., help='Partial search text (e.g. "bici")'),
148
+ market: str = MARKET,
149
+ fmt: str = FMT,
150
+ fields: str | None = FIELDS,
151
+ ) -> None:
152
+ """Get Wallapop search-box suggestions for a partial query."""
153
+ data = api_get("/v1/wallapop/autocomplete", {"query": query, "market": market})
154
+ render(data, fmt, fields)
155
+
156
+
157
+ @app.command()
158
+ def categories(market: str = MARKET, fmt: str = FMT, fields: str | None = FIELDS) -> None:
159
+ """List the Wallapop category tree (ids usable as --category-id)."""
160
+ data = api_get("/v1/wallapop/categories", {"market": market})
161
+ render(data, fmt, fields)
162
+
163
+
164
+ @app.command()
165
+ def filters(
166
+ category_id: int | None = typer.Option(None, "--category-id"),
167
+ query: str | None = typer.Option(None, "--query", "-q"),
168
+ market: str = MARKET,
169
+ fmt: str = FMT,
170
+ fields: str | None = FIELDS,
171
+ ) -> None:
172
+ """List the search filters Wallapop offers for a category/query."""
173
+ data = api_get(
174
+ "/v1/wallapop/filters", {"category_id": category_id, "query": query, "market": market}
175
+ )
176
+ render(data, fmt, fields)
177
+
178
+
179
+ @app.command("filter-options")
180
+ def filter_options(
181
+ filter_id: str = typer.Argument(..., help="Filter id from `filters` (e.g. brand)"),
182
+ category_id: int | None = typer.Option(None, "--category-id"),
183
+ query: str | None = typer.Option(None, "--query", "-q"),
184
+ market: str = MARKET,
185
+ fmt: str = FMT,
186
+ fields: str | None = FIELDS,
187
+ ) -> None:
188
+ """List a Wallapop filter's long option list (brands, models)."""
189
+ data = api_get(
190
+ f"/v1/wallapop/filters/{filter_id}/options",
191
+ {"category_id": category_id, "query": query, "market": market},
192
+ )
193
+ render(data, fmt, fields)
194
+
195
+
196
+ @app.command("markets")
197
+ def list_markets(fmt: str = FMT, fields: str | None = FIELDS) -> None:
198
+ """List Wallapop coverage markets (es, it, pt)."""
199
+ data = api_get("/v1/wallapop/markets", {})
200
+ render(data, fmt, fields)
@@ -19,6 +19,7 @@ from scrapebadger_cli.commands import (
19
19
  gemini,
20
20
  google,
21
21
  google_play,
22
+ gumtree,
22
23
  idealista,
23
24
  immobiliare,
24
25
  instagram,
@@ -34,6 +35,7 @@ from scrapebadger_cli.commands import (
34
35
  tiktok,
35
36
  twitter,
36
37
  vinted,
38
+ wallapop,
37
39
  walmart,
38
40
  web,
39
41
  yahoo,
@@ -56,6 +58,7 @@ app.add_typer(vinted.app, name="vinted", help="Vinted marketplace commands")
56
58
  app.add_typer(amazon.app, name="amazon", help="Amazon marketplace commands")
57
59
  app.add_typer(ebay.app, name="ebay", help="eBay marketplace commands")
58
60
  app.add_typer(walmart.app, name="walmart", help="Walmart marketplace commands")
61
+ app.add_typer(gumtree.app, name="gumtree", help="Gumtree UK classifieds commands")
59
62
  app.add_typer(google_play.app, name="google-play", help="Google Play Store commands")
60
63
  app.add_typer(app_store.app, name="app-store", help="Apple App Store commands")
61
64
  app.add_typer(idealista.app, name="idealista", help="Idealista real-estate commands")
@@ -79,6 +82,7 @@ app.add_typer(
79
82
  booking.app, name="booking", help="Booking.com property search, detail and reviews commands"
80
83
  )
81
84
  app.add_typer(depop.app, name="depop", help="Depop marketplace commands")
85
+ app.add_typer(wallapop.app, name="wallapop", help="Wallapop marketplace commands")
82
86
  app.add_typer(redfin.app, name="redfin", help="Redfin real-estate commands")
83
87
  app.add_typer(apartments.app, name="apartments", help="Apartments.com rental commands")
84
88
  app.add_typer(linkedin.app, name="linkedin", help="LinkedIn public data commands")
@@ -228,7 +228,7 @@ wheels = [
228
228
 
229
229
  [[package]]
230
230
  name = "scrapebadger-cli"
231
- version = "0.18.0"
231
+ version = "0.20.0"
232
232
  source = { editable = "." }
233
233
  dependencies = [
234
234
  { name = "httpx" },