vlr-stats-scraper 1.0.0 → 1.0.1
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.
- package/README.md +73 -74
- package/package.json +2 -2
- package/scripts/player-info-scraper.mjs +10 -4
- package/scripts/player-link-scraper.mjs +14 -8
package/README.md
CHANGED
|
@@ -1,74 +1,73 @@
|
|
|
1
|
-
# vlr-stats-scraper
|
|
2
|
-
|
|
3
|
-
Scrapes player stats from [vlr.gg](https://www.vlr.gg) and stores them in a local SQLite
|
|
4
|
-
database, grouped by tournament or stage, so you can pull a backlog of players
|
|
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
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
- `
|
|
59
|
-
- `
|
|
60
|
-
- `
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
- `
|
|
64
|
-
- `
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
ISC
|
|
1
|
+
# vlr-stats-scraper
|
|
2
|
+
|
|
3
|
+
Scrapes player stats from [vlr.gg](https://www.vlr.gg) and stores them in a local SQLite
|
|
4
|
+
database, grouped by tournament or stage, so you can pull a backlog of players.
|
|
5
|
+
|
|
6
|
+
## Setup
|
|
7
|
+
|
|
8
|
+
Requires a [Hyperbrowser](https://hyperbrowser.ai) API key for scraping.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install vlr-stats-scraper
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Create a `.env` file in the directory you run it from:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
HYPERBROWSER_API_KEY=your_key_here
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## CLI usage
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npx valstats <link> <year> <event-name>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npx valstats https://www.vlr.gg/event/2977/vct-2026-americas-stage-2/group-stage 2026 "Stage 2"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
- `link` — the vlr.gg event/group-stage page to scrape.
|
|
31
|
+
- `year` — the year the event took place.
|
|
32
|
+
- `event-name` — a label for this tournament/stage (used to group players together later).
|
|
33
|
+
|
|
34
|
+
Each player on that event page gets scraped and saved to `players.db` in your current
|
|
35
|
+
directory, linked to that event name.
|
|
36
|
+
|
|
37
|
+
## Library usage
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
import {
|
|
41
|
+
scrapePlayer,
|
|
42
|
+
scrapeWebsite,
|
|
43
|
+
savePlayer,
|
|
44
|
+
saveEvent,
|
|
45
|
+
addPlayerToEvent,
|
|
46
|
+
getPlayersByEvent,
|
|
47
|
+
getRandomPlayerFromEvent,
|
|
48
|
+
} from 'vlr-stats-scraper';
|
|
49
|
+
|
|
50
|
+
const links = await scrapeWebsite('https://www.vlr.gg/event/.../group-stage');
|
|
51
|
+
const player = await scrapePlayer(links[0], 'AMER');
|
|
52
|
+
savePlayer(player);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Exports
|
|
56
|
+
|
|
57
|
+
- `scrapePlayer(url, region)` — scrapes one player's profile page.
|
|
58
|
+
- `scrapeWebsite(url)` — scrapes an event page for player profile links.
|
|
59
|
+
- `savePlayer(player)` / `getPlayer(name)` / `getAllPlayers()` / `getRandomPlayer()`
|
|
60
|
+
- `saveEvent({ name, url, region, year, stage })` — creates/updates a tournament or stage,
|
|
61
|
+
returns its id.
|
|
62
|
+
- `addPlayerToEvent(eventId, playerName)`
|
|
63
|
+
- `getEvents()` / `getEventByName(name)`
|
|
64
|
+
- `getPlayersByEvent(eventName)` / `getRandomPlayerFromEvent(eventName)`
|
|
65
|
+
|
|
66
|
+
## Data storage
|
|
67
|
+
|
|
68
|
+
Player and event data is stored in a `players.db` SQLite file created in whichever
|
|
69
|
+
directory you run the tool from.
|
|
70
|
+
|
|
71
|
+
## License
|
|
72
|
+
|
|
73
|
+
ISC
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vlr-stats-scraper",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Scrapes player stats from vlr.gg and stores them in a local SQLite database, grouped by tournament or stage.",
|
|
5
5
|
"homepage": "https://github.com/OverYander/VLR-Webscraper#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"main": "./index.mjs",
|
|
17
17
|
"exports": "./index.mjs",
|
|
18
18
|
"bin": {
|
|
19
|
-
"valstats": "
|
|
19
|
+
"valstats": "main.mjs"
|
|
20
20
|
},
|
|
21
21
|
"files": [
|
|
22
22
|
"index.mjs",
|
|
@@ -4,14 +4,20 @@ import { config } from "dotenv";
|
|
|
4
4
|
|
|
5
5
|
config();
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
let client;
|
|
8
|
+
function getClient() {
|
|
9
|
+
if (!client) {
|
|
10
|
+
client = new Hyperbrowser({
|
|
11
|
+
apiKey: process.env.HYPERBROWSER_API_KEY,
|
|
12
|
+
})
|
|
13
|
+
}
|
|
14
|
+
return client;
|
|
15
|
+
}
|
|
10
16
|
|
|
11
17
|
async function scrapePlayer(url, region) {
|
|
12
18
|
console.log('scrapePlayer ran')
|
|
13
19
|
try {
|
|
14
|
-
const scrapeData = await
|
|
20
|
+
const scrapeData = await getClient().scrape.startAndWait({
|
|
15
21
|
url: url,
|
|
16
22
|
scrapeOptions: {
|
|
17
23
|
formats: ["html"]
|
|
@@ -3,13 +3,19 @@ import { config } from "dotenv";
|
|
|
3
3
|
|
|
4
4
|
config();
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
let client;
|
|
7
|
+
function getClient() {
|
|
8
|
+
if (!client) {
|
|
9
|
+
client = new Hyperbrowser({
|
|
10
|
+
apiKey: process.env.HYPERBROWSER_API_KEY,
|
|
11
|
+
})
|
|
12
|
+
}
|
|
13
|
+
return client;
|
|
14
|
+
}
|
|
9
15
|
|
|
10
16
|
async function scrapeWebsite(url) {
|
|
11
17
|
try {
|
|
12
|
-
const scrapeData = await
|
|
18
|
+
const scrapeData = await getClient().scrape.startAndWait({
|
|
13
19
|
url: url,
|
|
14
20
|
scrapeOptions: {
|
|
15
21
|
formats: ["html"],
|
|
@@ -19,14 +25,14 @@ async function scrapeWebsite(url) {
|
|
|
19
25
|
|
|
20
26
|
const players = scrapeData.data.html.split('\n').filter(line => line.includes('event-team-players-item'))
|
|
21
27
|
const playerLinks = players.map(player => {
|
|
22
|
-
const match = player.match(/href="(https:\/\/www\.vlr\.gg\/player\/[^"]*)"/)
|
|
23
|
-
return match ? match[1] : null;
|
|
28
|
+
const match = player.match(/href="(https:\/\/www\.vlr\.gg\/player\/[^"]*)"/)
|
|
29
|
+
return match ? match[1] + "/?timespan=all" : null;
|
|
24
30
|
}).filter(link => link !== null);
|
|
25
31
|
|
|
26
|
-
return playerLinks
|
|
32
|
+
return playerLinks
|
|
27
33
|
}
|
|
28
34
|
catch (error) {
|
|
29
|
-
console.error("Error scraping website:", error)
|
|
35
|
+
console.error("Error scraping website:", error)
|
|
30
36
|
}
|
|
31
37
|
}
|
|
32
38
|
|