apple-appstore-metadata-extractor 0.1.2__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.
- apple_appstore_metadata_extractor-0.1.2/CHANGELOG.md +43 -0
- apple_appstore_metadata_extractor-0.1.2/LICENSE +21 -0
- apple_appstore_metadata_extractor-0.1.2/MANIFEST.in +8 -0
- apple_appstore_metadata_extractor-0.1.2/PKG-INFO +298 -0
- apple_appstore_metadata_extractor-0.1.2/README.md +254 -0
- apple_appstore_metadata_extractor-0.1.2/examples/apps.json +24 -0
- apple_appstore_metadata_extractor-0.1.2/examples/async_batch.py +84 -0
- apple_appstore_metadata_extractor-0.1.2/examples/basic_usage.py +36 -0
- apple_appstore_metadata_extractor-0.1.2/examples/monitor_changes.py +100 -0
- apple_appstore_metadata_extractor-0.1.2/pyproject.toml +179 -0
- apple_appstore_metadata_extractor-0.1.2/requirements-dev.txt +17 -0
- apple_appstore_metadata_extractor-0.1.2/requirements.txt +9 -0
- apple_appstore_metadata_extractor-0.1.2/setup.cfg +4 -0
- apple_appstore_metadata_extractor-0.1.2/src/apple_appstore_metadata_extractor.egg-info/PKG-INFO +298 -0
- apple_appstore_metadata_extractor-0.1.2/src/apple_appstore_metadata_extractor.egg-info/SOURCES.txt +45 -0
- apple_appstore_metadata_extractor-0.1.2/src/apple_appstore_metadata_extractor.egg-info/dependency_links.txt +1 -0
- apple_appstore_metadata_extractor-0.1.2/src/apple_appstore_metadata_extractor.egg-info/entry_points.txt +2 -0
- apple_appstore_metadata_extractor-0.1.2/src/apple_appstore_metadata_extractor.egg-info/requires.txt +19 -0
- apple_appstore_metadata_extractor-0.1.2/src/apple_appstore_metadata_extractor.egg-info/top_level.txt +1 -0
- apple_appstore_metadata_extractor-0.1.2/src/appstore_metadata_extractor/__init__.py +45 -0
- apple_appstore_metadata_extractor-0.1.2/src/appstore_metadata_extractor/change_monitor.py +285 -0
- apple_appstore_metadata_extractor-0.1.2/src/appstore_metadata_extractor/cli/commands.py +259 -0
- apple_appstore_metadata_extractor-0.1.2/src/appstore_metadata_extractor/cli.py +328 -0
- apple_appstore_metadata_extractor-0.1.2/src/appstore_metadata_extractor/combined_scraper.py +470 -0
- apple_appstore_metadata_extractor-0.1.2/src/appstore_metadata_extractor/core/__init__.py +50 -0
- apple_appstore_metadata_extractor-0.1.2/src/appstore_metadata_extractor/core/cache.py +299 -0
- apple_appstore_metadata_extractor-0.1.2/src/appstore_metadata_extractor/core/exceptions.py +63 -0
- apple_appstore_metadata_extractor-0.1.2/src/appstore_metadata_extractor/core/extractors.py +673 -0
- apple_appstore_metadata_extractor-0.1.2/src/appstore_metadata_extractor/core/models.py +323 -0
- apple_appstore_metadata_extractor-0.1.2/src/appstore_metadata_extractor/core/wbs_validator.py +267 -0
- apple_appstore_metadata_extractor-0.1.2/src/appstore_metadata_extractor/models.py +53 -0
- apple_appstore_metadata_extractor-0.1.2/src/appstore_metadata_extractor/models_combined.py +210 -0
- apple_appstore_metadata_extractor-0.1.2/src/appstore_metadata_extractor/py.typed +0 -0
- apple_appstore_metadata_extractor-0.1.2/src/appstore_metadata_extractor/scraper.py +330 -0
- apple_appstore_metadata_extractor-0.1.2/src/appstore_metadata_extractor/settings.py +77 -0
- apple_appstore_metadata_extractor-0.1.2/src/appstore_metadata_extractor/wbs_extractor.py +394 -0
- apple_appstore_metadata_extractor-0.1.2/tests/conftest.py +42 -0
- apple_appstore_metadata_extractor-0.1.2/tests/functional/test_cli_functional.py +100 -0
- apple_appstore_metadata_extractor-0.1.2/tests/integration/test_change_monitoring.py +158 -0
- apple_appstore_metadata_extractor-0.1.2/tests/integration/test_combined_scraper.py +140 -0
- apple_appstore_metadata_extractor-0.1.2/tests/integration/test_wbs_extractor.py +206 -0
- apple_appstore_metadata_extractor-0.1.2/tests/test_models.py +97 -0
- apple_appstore_metadata_extractor-0.1.2/tests/unit/test_cache.py +344 -0
- apple_appstore_metadata_extractor-0.1.2/tests/unit/test_cli_help.py +72 -0
- apple_appstore_metadata_extractor-0.1.2/tests/unit/test_core_modules.py +107 -0
- apple_appstore_metadata_extractor-0.1.2/tests/unit/test_extractors_clean.py +257 -0
- apple_appstore_metadata_extractor-0.1.2/tests/unit/test_scraper.py +448 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.2] - 2025-07-29
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- Fixed PyPI publishing workflow to use API token authentication
|
|
12
|
+
- Removed trusted publishing configuration that was causing authentication failures
|
|
13
|
+
|
|
14
|
+
## [0.1.1] - 2025-07-29
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
- Attempted fix for PyPI publishing (incomplete)
|
|
18
|
+
|
|
19
|
+
## [0.1.0] - 2025-07-29
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
- Initial release of appstore-metadata-extractor
|
|
23
|
+
- Core functionality extracted from the full-stack project
|
|
24
|
+
- iTunes API integration for basic metadata
|
|
25
|
+
- Web scraping for extended metadata
|
|
26
|
+
- Combined extraction mode for comprehensive data
|
|
27
|
+
- CLI with commands: extract, extract-batch, watch
|
|
28
|
+
- Async/concurrent processing support
|
|
29
|
+
- Rate limiting and caching
|
|
30
|
+
- Rich terminal output
|
|
31
|
+
- Comprehensive error handling and retries
|
|
32
|
+
- Type hints throughout the codebase
|
|
33
|
+
- Full test suite with >80% coverage
|
|
34
|
+
|
|
35
|
+
### Features
|
|
36
|
+
- Extract app metadata from Apple App Store
|
|
37
|
+
- Monitor apps for version changes
|
|
38
|
+
- Batch processing with concurrent requests
|
|
39
|
+
- Multiple output formats (JSON, pretty-print)
|
|
40
|
+
- Configurable extraction modes
|
|
41
|
+
- WBS (What-Boundaries-Success) framework compliance
|
|
42
|
+
|
|
43
|
+
[0.1.0]: https://github.com/yourusername/appstore-metadata-extractor-python/releases/tag/v0.1.0
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Bickster LLC
|
|
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,298 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: apple-appstore-metadata-extractor
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: Extract and monitor metadata from Apple App Store applications
|
|
5
|
+
Author-email: Bickster LLC <support@bickster.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Bickster-LLC/appstore-metadata-extractor-python
|
|
8
|
+
Project-URL: Documentation, https://github.com/Bickster-LLC/appstore-metadata-extractor-python#readme
|
|
9
|
+
Project-URL: Repository, https://github.com/Bickster-LLC/appstore-metadata-extractor-python
|
|
10
|
+
Project-URL: Issues, https://github.com/Bickster-LLC/appstore-metadata-extractor-python/issues
|
|
11
|
+
Project-URL: Changelog, https://github.com/Bickster-LLC/appstore-metadata-extractor-python/blob/main/CHANGELOG.md
|
|
12
|
+
Keywords: app store,metadata,ios,apple,scraping,monitoring
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
21
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: requests>=2.31.0
|
|
26
|
+
Requires-Dist: beautifulsoup4>=4.12.0
|
|
27
|
+
Requires-Dist: lxml>=4.9.0
|
|
28
|
+
Requires-Dist: pydantic>=2.5.0
|
|
29
|
+
Requires-Dist: aiohttp>=3.9.0
|
|
30
|
+
Requires-Dist: tenacity>=8.2.0
|
|
31
|
+
Requires-Dist: rich>=13.7.0
|
|
32
|
+
Requires-Dist: click>=8.1.0
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: pytest>=7.4.0; extra == "dev"
|
|
35
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
36
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
37
|
+
Requires-Dist: black>=23.7.0; extra == "dev"
|
|
38
|
+
Requires-Dist: isort>=5.12.0; extra == "dev"
|
|
39
|
+
Requires-Dist: flake8>=6.1.0; extra == "dev"
|
|
40
|
+
Requires-Dist: mypy>=1.5.0; extra == "dev"
|
|
41
|
+
Requires-Dist: pre-commit>=3.3.0; extra == "dev"
|
|
42
|
+
Requires-Dist: types-requests>=2.31.0; extra == "dev"
|
|
43
|
+
Dynamic: license-file
|
|
44
|
+
|
|
45
|
+
# Apple App Store Metadata Extractor
|
|
46
|
+
|
|
47
|
+
[](https://badge.fury.io/py/apple-appstore-metadata-extractor)
|
|
48
|
+
[](https://pypi.org/project/apple-appstore-metadata-extractor/)
|
|
49
|
+
[](https://opensource.org/licenses/MIT)
|
|
50
|
+
|
|
51
|
+
Extract and monitor metadata from Apple App Store applications with ease.
|
|
52
|
+
|
|
53
|
+
## Features
|
|
54
|
+
|
|
55
|
+
- 📱 **Extract comprehensive app metadata** - title, description, version, ratings, and more
|
|
56
|
+
- 🔄 **Track version changes** - monitor app updates and metadata changes over time
|
|
57
|
+
- 🚀 **Async support** - fast concurrent extraction for multiple apps
|
|
58
|
+
- 💪 **Robust error handling** - automatic retries and graceful error recovery
|
|
59
|
+
- 🛡️ **Rate limiting** - respect API limits and prevent blocking
|
|
60
|
+
- 🎨 **Rich CLI** - beautiful command-line interface with progress tracking
|
|
61
|
+
- 📊 **Multiple output formats** - JSON, pretty-printed, or custom formatting
|
|
62
|
+
|
|
63
|
+
## Installation
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pip install apple-appstore-metadata-extractor
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Quick Start
|
|
70
|
+
|
|
71
|
+
### Command Line
|
|
72
|
+
|
|
73
|
+
Extract metadata for a single app:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
appstore-extractor extract https://apps.apple.com/us/app/example/id123456789
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Extract from multiple apps:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
appstore-extractor extract-batch apps.json
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Monitor apps for changes:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
appstore-extractor watch apps.json --interval 3600
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Python Library
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from appstore_metadata_extractor import AppStoreScraper
|
|
95
|
+
|
|
96
|
+
# Initialize scraper
|
|
97
|
+
scraper = AppStoreScraper()
|
|
98
|
+
|
|
99
|
+
# Extract single app metadata
|
|
100
|
+
metadata = scraper.extract("https://apps.apple.com/us/app/example/id123456789")
|
|
101
|
+
print(f"App: {metadata.title}")
|
|
102
|
+
print(f"Version: {metadata.version}")
|
|
103
|
+
print(f"Rating: {metadata.rating}")
|
|
104
|
+
|
|
105
|
+
# Extract multiple apps
|
|
106
|
+
urls = [
|
|
107
|
+
"https://apps.apple.com/us/app/app1/id111111111",
|
|
108
|
+
"https://apps.apple.com/us/app/app2/id222222222"
|
|
109
|
+
]
|
|
110
|
+
results = scraper.extract_batch(urls)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Async Usage
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
import asyncio
|
|
117
|
+
from appstore_metadata_extractor import CombinedExtractor
|
|
118
|
+
|
|
119
|
+
async def main():
|
|
120
|
+
extractor = CombinedExtractor()
|
|
121
|
+
|
|
122
|
+
# Extract single app
|
|
123
|
+
result = await extractor.extract("https://apps.apple.com/us/app/example/id123456789")
|
|
124
|
+
|
|
125
|
+
# Extract multiple apps concurrently
|
|
126
|
+
urls = ["url1", "url2", "url3"]
|
|
127
|
+
results = await extractor.extract_batch(urls)
|
|
128
|
+
|
|
129
|
+
asyncio.run(main())
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## CLI Commands
|
|
133
|
+
|
|
134
|
+
### `extract` - Extract single app metadata
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
appstore-extractor extract [OPTIONS] URL
|
|
138
|
+
|
|
139
|
+
Options:
|
|
140
|
+
-o, --output PATH Output file path
|
|
141
|
+
-f, --format [json|pretty] Output format (default: pretty)
|
|
142
|
+
--no-cache Disable caching
|
|
143
|
+
--country TEXT Country code (default: us)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### `extract-batch` - Extract multiple apps
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
appstore-extractor extract-batch [OPTIONS] INPUT_FILE
|
|
150
|
+
|
|
151
|
+
Options:
|
|
152
|
+
-o, --output PATH Output file path
|
|
153
|
+
-f, --format [json|pretty] Output format
|
|
154
|
+
--concurrent INTEGER Max concurrent requests (default: 5)
|
|
155
|
+
--delay FLOAT Delay between requests in seconds
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### `watch` - Monitor apps for changes
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
appstore-extractor watch [OPTIONS] INPUT_FILE
|
|
162
|
+
|
|
163
|
+
Options:
|
|
164
|
+
--interval INTEGER Check interval in seconds (default: 3600)
|
|
165
|
+
--output-dir PATH Directory for history files
|
|
166
|
+
--notify Enable notifications for changes
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Input File Format
|
|
170
|
+
|
|
171
|
+
For batch operations, use a JSON file:
|
|
172
|
+
|
|
173
|
+
```json
|
|
174
|
+
{
|
|
175
|
+
"apps": [
|
|
176
|
+
{
|
|
177
|
+
"name": "Example App 1",
|
|
178
|
+
"url": "https://apps.apple.com/us/app/example-1/id123456789"
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"name": "Example App 2",
|
|
182
|
+
"url": "https://apps.apple.com/us/app/example-2/id987654321"
|
|
183
|
+
}
|
|
184
|
+
]
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Advanced Usage
|
|
189
|
+
|
|
190
|
+
### Custom Extraction Modes
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
from appstore_metadata_extractor import CombinedExtractor, ExtractionMode
|
|
194
|
+
|
|
195
|
+
extractor = CombinedExtractor()
|
|
196
|
+
|
|
197
|
+
# API-only mode (faster, less data)
|
|
198
|
+
result = await extractor.extract(url, mode=ExtractionMode.API_ONLY)
|
|
199
|
+
|
|
200
|
+
# Web scraping mode (slower, more complete)
|
|
201
|
+
result = await extractor.extract(url, mode=ExtractionMode.WEB_SCRAPE)
|
|
202
|
+
|
|
203
|
+
# Combined mode (default - best of both)
|
|
204
|
+
result = await extractor.extract(url, mode=ExtractionMode.COMBINED)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Rate Limiting Configuration
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
from appstore_metadata_extractor import RateLimiter
|
|
211
|
+
|
|
212
|
+
# Configure custom rate limits
|
|
213
|
+
rate_limiter = RateLimiter(
|
|
214
|
+
calls_per_minute=20, # iTunes API limit
|
|
215
|
+
min_delay=1.0 # Minimum delay between calls
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
scraper = AppStoreScraper(rate_limiter=rate_limiter)
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Caching
|
|
222
|
+
|
|
223
|
+
```python
|
|
224
|
+
from appstore_metadata_extractor import CacheManager
|
|
225
|
+
|
|
226
|
+
# Configure cache
|
|
227
|
+
cache = CacheManager(
|
|
228
|
+
ttl=300, # Cache TTL in seconds
|
|
229
|
+
max_size=1000 # Maximum cache entries
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
scraper = AppStoreScraper(cache_manager=cache)
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Error Handling
|
|
236
|
+
|
|
237
|
+
The library provides robust error handling with automatic retries:
|
|
238
|
+
|
|
239
|
+
```python
|
|
240
|
+
from appstore_metadata_extractor import AppNotFoundError, RateLimitError
|
|
241
|
+
|
|
242
|
+
try:
|
|
243
|
+
metadata = scraper.extract(url)
|
|
244
|
+
except AppNotFoundError:
|
|
245
|
+
print("App not found")
|
|
246
|
+
except RateLimitError:
|
|
247
|
+
print("Rate limit exceeded, please wait")
|
|
248
|
+
except Exception as e:
|
|
249
|
+
print(f"Extraction failed: {e}")
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Contributing
|
|
253
|
+
|
|
254
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
255
|
+
|
|
256
|
+
1. Fork the repository
|
|
257
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
258
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
259
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
260
|
+
5. Open a Pull Request
|
|
261
|
+
|
|
262
|
+
## Development
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
# Clone the repository
|
|
266
|
+
git clone https://github.com/yourusername/appstore-metadata-extractor-python.git
|
|
267
|
+
cd appstore-metadata-extractor-python
|
|
268
|
+
|
|
269
|
+
# Install in development mode
|
|
270
|
+
pip install -e ".[dev]"
|
|
271
|
+
|
|
272
|
+
# Run tests
|
|
273
|
+
pytest
|
|
274
|
+
|
|
275
|
+
# Run linting
|
|
276
|
+
black src tests
|
|
277
|
+
isort src tests
|
|
278
|
+
flake8 src tests
|
|
279
|
+
mypy src
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## License
|
|
283
|
+
|
|
284
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
285
|
+
|
|
286
|
+
## Disclaimer
|
|
287
|
+
|
|
288
|
+
This tool is for educational and research purposes only. Make sure to comply with Apple's Terms of Service and robots.txt when using this tool. Be respectful of rate limits and implement appropriate delays between requests.
|
|
289
|
+
|
|
290
|
+
## Acknowledgments
|
|
291
|
+
|
|
292
|
+
- Built with [Beautiful Soup](https://www.crummy.com/software/BeautifulSoup/) for web scraping
|
|
293
|
+
- Uses [Rich](https://github.com/Textualize/rich) for beautiful CLI output
|
|
294
|
+
- Powered by [Pydantic](https://pydantic-docs.helpmanual.io/) for data validation
|
|
295
|
+
|
|
296
|
+
## Related Projects
|
|
297
|
+
|
|
298
|
+
For a full-featured solution with web API, authentication, and UI, check out the [parent project](https://github.com/Bickster-LLC/appstore-metadata-extractor).
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# Apple App Store Metadata Extractor
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/py/apple-appstore-metadata-extractor)
|
|
4
|
+
[](https://pypi.org/project/apple-appstore-metadata-extractor/)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
7
|
+
Extract and monitor metadata from Apple App Store applications with ease.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- 📱 **Extract comprehensive app metadata** - title, description, version, ratings, and more
|
|
12
|
+
- 🔄 **Track version changes** - monitor app updates and metadata changes over time
|
|
13
|
+
- 🚀 **Async support** - fast concurrent extraction for multiple apps
|
|
14
|
+
- 💪 **Robust error handling** - automatic retries and graceful error recovery
|
|
15
|
+
- 🛡️ **Rate limiting** - respect API limits and prevent blocking
|
|
16
|
+
- 🎨 **Rich CLI** - beautiful command-line interface with progress tracking
|
|
17
|
+
- 📊 **Multiple output formats** - JSON, pretty-printed, or custom formatting
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install apple-appstore-metadata-extractor
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
### Command Line
|
|
28
|
+
|
|
29
|
+
Extract metadata for a single app:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
appstore-extractor extract https://apps.apple.com/us/app/example/id123456789
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Extract from multiple apps:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
appstore-extractor extract-batch apps.json
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Monitor apps for changes:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
appstore-extractor watch apps.json --interval 3600
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Python Library
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from appstore_metadata_extractor import AppStoreScraper
|
|
51
|
+
|
|
52
|
+
# Initialize scraper
|
|
53
|
+
scraper = AppStoreScraper()
|
|
54
|
+
|
|
55
|
+
# Extract single app metadata
|
|
56
|
+
metadata = scraper.extract("https://apps.apple.com/us/app/example/id123456789")
|
|
57
|
+
print(f"App: {metadata.title}")
|
|
58
|
+
print(f"Version: {metadata.version}")
|
|
59
|
+
print(f"Rating: {metadata.rating}")
|
|
60
|
+
|
|
61
|
+
# Extract multiple apps
|
|
62
|
+
urls = [
|
|
63
|
+
"https://apps.apple.com/us/app/app1/id111111111",
|
|
64
|
+
"https://apps.apple.com/us/app/app2/id222222222"
|
|
65
|
+
]
|
|
66
|
+
results = scraper.extract_batch(urls)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Async Usage
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
import asyncio
|
|
73
|
+
from appstore_metadata_extractor import CombinedExtractor
|
|
74
|
+
|
|
75
|
+
async def main():
|
|
76
|
+
extractor = CombinedExtractor()
|
|
77
|
+
|
|
78
|
+
# Extract single app
|
|
79
|
+
result = await extractor.extract("https://apps.apple.com/us/app/example/id123456789")
|
|
80
|
+
|
|
81
|
+
# Extract multiple apps concurrently
|
|
82
|
+
urls = ["url1", "url2", "url3"]
|
|
83
|
+
results = await extractor.extract_batch(urls)
|
|
84
|
+
|
|
85
|
+
asyncio.run(main())
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## CLI Commands
|
|
89
|
+
|
|
90
|
+
### `extract` - Extract single app metadata
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
appstore-extractor extract [OPTIONS] URL
|
|
94
|
+
|
|
95
|
+
Options:
|
|
96
|
+
-o, --output PATH Output file path
|
|
97
|
+
-f, --format [json|pretty] Output format (default: pretty)
|
|
98
|
+
--no-cache Disable caching
|
|
99
|
+
--country TEXT Country code (default: us)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### `extract-batch` - Extract multiple apps
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
appstore-extractor extract-batch [OPTIONS] INPUT_FILE
|
|
106
|
+
|
|
107
|
+
Options:
|
|
108
|
+
-o, --output PATH Output file path
|
|
109
|
+
-f, --format [json|pretty] Output format
|
|
110
|
+
--concurrent INTEGER Max concurrent requests (default: 5)
|
|
111
|
+
--delay FLOAT Delay between requests in seconds
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### `watch` - Monitor apps for changes
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
appstore-extractor watch [OPTIONS] INPUT_FILE
|
|
118
|
+
|
|
119
|
+
Options:
|
|
120
|
+
--interval INTEGER Check interval in seconds (default: 3600)
|
|
121
|
+
--output-dir PATH Directory for history files
|
|
122
|
+
--notify Enable notifications for changes
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Input File Format
|
|
126
|
+
|
|
127
|
+
For batch operations, use a JSON file:
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
{
|
|
131
|
+
"apps": [
|
|
132
|
+
{
|
|
133
|
+
"name": "Example App 1",
|
|
134
|
+
"url": "https://apps.apple.com/us/app/example-1/id123456789"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"name": "Example App 2",
|
|
138
|
+
"url": "https://apps.apple.com/us/app/example-2/id987654321"
|
|
139
|
+
}
|
|
140
|
+
]
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Advanced Usage
|
|
145
|
+
|
|
146
|
+
### Custom Extraction Modes
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
from appstore_metadata_extractor import CombinedExtractor, ExtractionMode
|
|
150
|
+
|
|
151
|
+
extractor = CombinedExtractor()
|
|
152
|
+
|
|
153
|
+
# API-only mode (faster, less data)
|
|
154
|
+
result = await extractor.extract(url, mode=ExtractionMode.API_ONLY)
|
|
155
|
+
|
|
156
|
+
# Web scraping mode (slower, more complete)
|
|
157
|
+
result = await extractor.extract(url, mode=ExtractionMode.WEB_SCRAPE)
|
|
158
|
+
|
|
159
|
+
# Combined mode (default - best of both)
|
|
160
|
+
result = await extractor.extract(url, mode=ExtractionMode.COMBINED)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Rate Limiting Configuration
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
from appstore_metadata_extractor import RateLimiter
|
|
167
|
+
|
|
168
|
+
# Configure custom rate limits
|
|
169
|
+
rate_limiter = RateLimiter(
|
|
170
|
+
calls_per_minute=20, # iTunes API limit
|
|
171
|
+
min_delay=1.0 # Minimum delay between calls
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
scraper = AppStoreScraper(rate_limiter=rate_limiter)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Caching
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
from appstore_metadata_extractor import CacheManager
|
|
181
|
+
|
|
182
|
+
# Configure cache
|
|
183
|
+
cache = CacheManager(
|
|
184
|
+
ttl=300, # Cache TTL in seconds
|
|
185
|
+
max_size=1000 # Maximum cache entries
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
scraper = AppStoreScraper(cache_manager=cache)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Error Handling
|
|
192
|
+
|
|
193
|
+
The library provides robust error handling with automatic retries:
|
|
194
|
+
|
|
195
|
+
```python
|
|
196
|
+
from appstore_metadata_extractor import AppNotFoundError, RateLimitError
|
|
197
|
+
|
|
198
|
+
try:
|
|
199
|
+
metadata = scraper.extract(url)
|
|
200
|
+
except AppNotFoundError:
|
|
201
|
+
print("App not found")
|
|
202
|
+
except RateLimitError:
|
|
203
|
+
print("Rate limit exceeded, please wait")
|
|
204
|
+
except Exception as e:
|
|
205
|
+
print(f"Extraction failed: {e}")
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Contributing
|
|
209
|
+
|
|
210
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
211
|
+
|
|
212
|
+
1. Fork the repository
|
|
213
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
214
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
215
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
216
|
+
5. Open a Pull Request
|
|
217
|
+
|
|
218
|
+
## Development
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
# Clone the repository
|
|
222
|
+
git clone https://github.com/yourusername/appstore-metadata-extractor-python.git
|
|
223
|
+
cd appstore-metadata-extractor-python
|
|
224
|
+
|
|
225
|
+
# Install in development mode
|
|
226
|
+
pip install -e ".[dev]"
|
|
227
|
+
|
|
228
|
+
# Run tests
|
|
229
|
+
pytest
|
|
230
|
+
|
|
231
|
+
# Run linting
|
|
232
|
+
black src tests
|
|
233
|
+
isort src tests
|
|
234
|
+
flake8 src tests
|
|
235
|
+
mypy src
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## License
|
|
239
|
+
|
|
240
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
241
|
+
|
|
242
|
+
## Disclaimer
|
|
243
|
+
|
|
244
|
+
This tool is for educational and research purposes only. Make sure to comply with Apple's Terms of Service and robots.txt when using this tool. Be respectful of rate limits and implement appropriate delays between requests.
|
|
245
|
+
|
|
246
|
+
## Acknowledgments
|
|
247
|
+
|
|
248
|
+
- Built with [Beautiful Soup](https://www.crummy.com/software/BeautifulSoup/) for web scraping
|
|
249
|
+
- Uses [Rich](https://github.com/Textualize/rich) for beautiful CLI output
|
|
250
|
+
- Powered by [Pydantic](https://pydantic-docs.helpmanual.io/) for data validation
|
|
251
|
+
|
|
252
|
+
## Related Projects
|
|
253
|
+
|
|
254
|
+
For a full-featured solution with web API, authentication, and UI, check out the [parent project](https://github.com/Bickster-LLC/appstore-metadata-extractor).
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"apps": [
|
|
3
|
+
{
|
|
4
|
+
"name": "GitHub",
|
|
5
|
+
"url": "https://apps.apple.com/us/app/github/id1477376905"
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
"name": "Slack",
|
|
9
|
+
"url": "https://apps.apple.com/us/app/slack/id618783545"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"name": "Notion",
|
|
13
|
+
"url": "https://apps.apple.com/us/app/notion/id1232780281"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"name": "Spotify",
|
|
17
|
+
"url": "https://apps.apple.com/us/app/spotify/id324684580"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"name": "Discord",
|
|
21
|
+
"url": "https://apps.apple.com/us/app/discord/id985746746"
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|