This release is a pre-release and may not be stable for production use.
la-metro-scraper
CLI for continuously streaming LA Metro bus + rail vehicle positions from the api.metro.net
GTFS-realtime WebSocket feeds into a SQLite database.
uv run la-metro-scraper run -o vehicle_positions.sqlite # runs until ^C
uv run la-metro-scraper run -o vehicle_positions.sqlite \
--within query.geojson # only store positions inside the boundary
uv run la-metro-scraper run -o vehicle_positions.sqlite \
--feeds rail --routes A,C # rail feed only; A + C line only
uv run la-metro-scraper stats -o vehicle_positions.sqlite
uv run la-metro-scraper vehicles -o vehicle_positions.sqlite \
--within query.geojson # only list vehicles inside the boundary
Each WebSocket frame is one FeedEntity; frames are buffered and flushed
to SQLite once a second. schema.sql decomposes the payload into a
history table (metro_vehicle_position, deduped on
(feed, vehicle_id, observed_at)) with triggers maintaining
latest-state tables metro_vehicle, metro_trip, and metro_route.
The raw payload JSON is not stored — every field the feed sends has its
own column. The insert statement lives in procedures.sql. The typed
wrapper _queries.py is codegen'd from both SQL files — after editing
either, regenerate with make (runs solite codegen piped through
tools/codegen.py; solite is pinned to 0.0.1a36 because later
prereleases stopped embedding the schema in the generated setup).
CLI Reference
run — stream vehicle positions into SQLite until interrupted
Connects to the selected WebSocket feeds and continuously inserts
position snapshots. Databases are created in WAL mode. Filters
(--feeds, --routes, --within) compose with AND; filtered frames
are dropped before they reach the database.
| Flag | Default | Description |
|---|---|---|
-o, --out FILE.sqlite |
vehicle_positions.sqlite |
Database to stream into; created (in WAL mode) if missing. |
--feeds FEEDS |
bus,rail |
Comma-separated feeds to subscribe to. Unselected feeds are never connected. |
--routes CODES |
all routes | Comma-separated route codes to store, e.g. 2,720,A. Letter lines A B C D E G J K auto-convert to the numeric codes the feeds publish (A=801, B=802, C=803, E=804, D=805, K=807, G=901, J=910; G and J ride the bus feed). Deadheading vehicles (no route) are dropped. |
--within FILE.geojson |
no filter | Only store positions inside this geometry (GeoJSON Feature or bare geometry; WKT/WKB also work), tested per-frame with sqlite-tg. Frames with no position are dropped. |
--bucket SECONDS |
off | Log one aggregated line per interval (with running db totals) instead of one line per flush. Warns if an interval passes with no frames. |
--verbose, -v |
off | DEBUG logging; with --bucket, also shows the per-flush lines. |
Log lines count every drop reason: duplicate (Metro re-broadcasts
unchanged positions; deduped by primary key), off-route (--routes),
outside boundary (--within), invalid (unparseable JSON).
vehicles — list the latest known position of each vehicle
One line per vehicle from metro_vehicle (feed, route, fleet label,
lat/lon, speed, age of last observation), ordered by feed then route.
Opens the database read-only, so it's safe against a live run.
| Flag | Default | Description |
|---|---|---|
-o, --out FILE.sqlite |
vehicle_positions.sqlite |
Database to inspect. |
--within FILE.geojson |
no filter | Only list vehicles currently inside this geometry (same formats as run --within). |
stats — print row counts and time range
One-shot summary: counts of positions, vehicles, trips, and routes,
plus the received_at time span of the stored history. Read-only.
| Flag | Default | Description |
|---|---|---|
-o, --out FILE.sqlite |
vehicle_positions.sqlite |
Database to inspect. |
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file la_metro_scraper-0.1.0a2.tar.gz.
File metadata
- Download URL: la_metro_scraper-0.1.0a2.tar.gz
- Upload date:
- Size: 12.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f375329bcf6385c164be15f7ae3b1878ce170e4cda6aabb118d09aa1dfc15638
|
|
| MD5 |
cb511bb4798a0dd47393e7775ac03a41
|
|
| BLAKE2b-256 |
c0d4bb76c36f9186f577337bb2081744a32895cb7d465fc9513d0d3920959310
|
File details
Details for the file la_metro_scraper-0.1.0a2-py3-none-any.whl.
File metadata
- Download URL: la_metro_scraper-0.1.0a2-py3-none-any.whl
- Upload date:
- Size: 17.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
80ab3ccbc695e999352d990c7fe4a8cbb0d749cd53bc4f80c5b9828e530ae583
|
|
| MD5 |
fe9670e19db5a78f9b328e829415afc2
|
|
| BLAKE2b-256 |
abe93ee5e22e9c8f89d69b1ca920bfc17511ac7ca390d7923dc62bf36ab78f31
|