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. |
Metadata
Release files for la-metro-scraper 0.1.0a2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| la_metro_scraper-0.1.0a2.tar.gz | 12.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| la_metro_scraper-0.1.0a2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 29.0 kB
Release files / la_metro_scraper-0.1.0a2.tar.gz
| Download URL | la_metro_scraper-0.1.0a2.tar.gz |
|---|---|
| Size | 12.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f375329bcf6385c164be15f7ae3b1878ce170e4cda6aabb118d09aa1dfc15638
|
|
BLAKE2b-256 checksum How to use checksums |
c0d4bb76c36f9186f577337bb2081744a32895cb7d465fc9513d0d3920959310
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is 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}
|
Release files / la_metro_scraper-0.1.0a2-py3-none-any.whl
| Download URL | la_metro_scraper-0.1.0a2-py3-none-any.whl |
|---|---|
| Size | 17.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
80ab3ccbc695e999352d990c7fe4a8cbb0d749cd53bc4f80c5b9828e530ae583
|
|
BLAKE2b-256 checksum How to use checksums |
abe93ee5e22e9c8f89d69b1ca920bfc17511ac7ca390d7923dc62bf36ab78f31
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is 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}
|