File size: 6,623 Bytes
7880865
 
 
 
 
 
 
1877143
7880865
 
1a36a16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7880865
 
1a36a16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7880865
1a36a16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7880865
1a36a16
 
7880865
1a36a16
 
7880865
1a36a16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7880865
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
---
license: mit
sdk: gradio
emoji: 🏃
colorFrom: blue
colorTo: blue
pinned: true
sdk_version: 6.3.0
---
# SongBPM

A powerful Python tool to extract BPM (Beats Per Minute), musical key, and song metadata from [songbpm.com](https://songbpm.com/). Perfect for music producers, DJs, and data analysts who need tempo information for their workflows.

## Features

- **Single Song Search**: Quickly look up BPM and key for any song
- **Batch Processing**: Process multiple songs from a file
- **Multiple Export Formats**: Save results to CSV or JSON
- **Web Interface**: User-friendly Gradio web demo for easy searching
- **Respectful Scraping**: Built-in delays to avoid overloading servers
- **Error Handling**: Robust error handling with retry logic
- **Headless Mode**: Run silently or with visible browser for debugging

## Requirements

- Python 3.9 or higher
- Google Chrome or Chromium browser
- Required Python packages (see `requirements.txt`)
- Gradio (for web interface demo)

## Installation

1. Clone or download this repository:

```bash
git clone https://huggingface.co/spaces/terastudio/SongBPM
cd SongBPM
```

2. Create a virtual environment (recommended):

```bash
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
```

3. Install required packages:

```bash
pip install -r requirements.txt
```

4. Install Playwright browsers:

```bash
playwright install chromium
```

## Usage

### Basic Search

Search for a single song:

```bash
python songbpm_scraper.py "queen - under pressure"
```

### Batch Processing

Process multiple songs from a file:

```bash
# Create a file with one song per line
echo "daft punk - one more time" > songs.txt
echo "the prodigy - firestarter" >> songs.txt
echo "metallica - enter sandman" >> songs.txt

python songbpm_scraper.py --file songs.txt
```

### Export Results

Save results to CSV:

```bash
python songbpm_scraper.py "adele - rolling in the deep" --csv results.csv
```

Save results to JSON:

```bash
python songbpm_scraper.py "taylor swift - shake it off" --json output.json
```

### Debug Mode

Show the browser window during scraping:

```bash
python songbpm_scraper.py "beyoncé - crazy in love" --visible
```

### Custom Delay

Adjust the delay between requests (in seconds):

```bash
python songbpm_scraper.py "song name" --delay 5.0
```

## Web Interface (Gradio Demo)

A user-friendly web interface is available for easy song searching without using the command line:

### Launch the Web Demo

```bash
python app.py
```

This starts a local web server. Open your browser to:
- **Local URL**: http://127.0.0.1:7860

### Web Interface Features

The web demo provides three tabs:

1. **Single Search** - Search for one song at a time with instant results
2. **Batch Search** - Upload a file with multiple song queries
3. **Help** - Usage instructions and tips

### Command Line Options

```bash
# Change host and port
python app.py --host 0.0.0.0 --port 8080

# Create a public share link (temporary URL)
python app.py --share

# Enable debug mode
python app.py --debug
```

### Web Interface Screenshots

The interface displays:
- Song title and artist name
- BPM (tempo) information
- Musical key (e.g., C Major, A Minor)
- Song duration
- Direct links to source pages

You can also export results directly from the web interface in CSV or JSON format.

## Output Format

### CSV Output

| Title | Artist | BPM | Key | Duration | URL |
|-------|--------|-----|-----|----------|-----|
| Under Pressure | Queen | 114 | B | 4:08 | https://songbpm.com/... |

### JSON Output

```json
[
  {
    "title": "Under Pressure",
    "artist": "Queen",
    "bpm": 114,
    "key": "B",
    "duration": "4:08",
    "url": "https://songbpm.com/..."
  }
]
```

## API Usage

You can also use the scraper as a Python library in your own projects:

```python
import asyncio
from songbpm_scraper import SongBPMExtractor

async def main():
    extractor = SongBPMExtractor()

    # Single song search
    results = await extractor.extract("coldplay - fix you")
    print(results)

    # Batch search
    songs = [
        "tame impala - the less i know the better",
        "flume - never be like you"
    ]
    all_results = await extractor.extract_batch(songs)

    # Export
    extractor.export_to_csv(all_results, "my_songs.csv")

asyncio.run(main())
```

## Customization

### Modifying Selectors

If the website structure changes, you may need to update the CSS selectors in `songbpm_scraper.py`. Look for the `_parse_search_results` method:

```python
def _parse_search_results(self, soup: BeautifulSoup, source_url: str) -> list[SongData]:
    # Update these selectors if the website changes
    song_selectors = [
        "div.track",
        "div.song-item",
        "div[data-testid='track']",
        # ... add or modify selectors
    ]
```

### Adjusting Delays

Modify the `ScraperConfig` to adjust request timing:

```python
from songbpm_scraper import ScraperConfig, SongBPMScraper

config = ScraperConfig(
    min_delay=1.0,  # Minimum delay in seconds
    max_delay=3.0,  # Maximum delay in seconds
    timeout=60000,  # Request timeout in milliseconds
    max_retries=5   # Number of retry attempts
)

scraper = SongBPMScraper(config)
```

## Ethical Usage Guidelines

1. **Respect Rate Limits**: The scraper includes delays by default. Do not reduce them excessively.
2. **Check robots.txt**: Always verify you're allowed to scrape the target website.
3. **Personal Use Only**: This tool is intended for personal, non-commercial use.
4. **API First**: If available, use official APIs instead of scraping.
5. **Cache Results**: Store results locally to avoid repeated requests for the same data.

## Troubleshooting

### Browser Not Found

If you see an error about missing browser:

```bash
playwright install chromium
```

### Timeout Errors

Increase the timeout in the configuration:

```python
config = ScraperConfig(timeout=60000)  # 60 seconds
```

### No Results

The website structure may have changed. Try with the `--visible` flag to see what's happening:

```bash
python songbpm_scraper.py "song name" --visible
```

## Legal Disclaimer

This tool is provided for educational purposes only. Users are responsible for ensuring their use complies with the website's terms of service and applicable laws. The developer is not responsible for any misuse of this tool.

## License

MIT License - feel free to use and modify for your own projects.

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## Support

If you encounter issues or have questions, please open an issue on GitHub.