docs: document reels-scrape.py, and add a global gallery-dl safety net
Two additions: - A "Reels" section in TOOLING.md with the exact two-step command sequence for scraping and fetching reels by hand, since it's a separate manual tool, not wired into gdl-cron.sh. - ~/.config/gallery-dl/config.json on mattellite, so a plain `gallery-dl <url>` typed by hand -- outside gdl-sync.py entirely -- still gets the hand-paced sleep/rate/api settings instead of gallery-dl's own faster defaults. Documented in TOOLING.md since the file itself isn't tracked (host-local, like artms.db). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011qAds5qr7nZRq5R4yAuxUk
This commit is contained in:
+113
@@ -58,6 +58,53 @@ Long runs: `setsid nohup ~/gdl/gdl-cron.sh profiles >/dev/null 2>&1 &` and
|
|||||||
`tail -f ~/gdl/logs/$(ls -1t ~/gdl/logs | head -1)`. Nothing reaches the
|
`tail -f ~/gdl/logs/$(ls -1t ~/gdl/logs | head -1)`. Nothing reaches the
|
||||||
archive until a run finishes, so killing one midway is safe.
|
archive until a run finishes, so killing one midway is safe.
|
||||||
|
|
||||||
|
## Safety net: a global gallery-dl config
|
||||||
|
|
||||||
|
`~/.config/gallery-dl/config.json` on `mattellite` exists so that a **plain
|
||||||
|
`gallery-dl <url>` typed by hand** — for a quick manual check, outside
|
||||||
|
`gdl-sync.py` entirely — still gets the hand-paced caution settings instead of
|
||||||
|
gallery-dl's own faster defaults. It is loaded automatically; nothing needs to
|
||||||
|
reference it. `gdl-sync.py`'s own `--sleep-request`/`--sleep`/`--rate` flags
|
||||||
|
still override it as normal — this is only a floor for when nobody passed any.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"extractor": {
|
||||||
|
"instagram": {
|
||||||
|
"api": "rest",
|
||||||
|
"cookies": ["chrome", "/home/matt/.config/google-chrome-devtools"],
|
||||||
|
"sleep-request": [12.0, 20.0],
|
||||||
|
"sleep": [5.0, 10.0],
|
||||||
|
"sleep-429": 120.0,
|
||||||
|
"retries": 8,
|
||||||
|
"videos": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"downloader": {
|
||||||
|
"http": {
|
||||||
|
"rate": "500K",
|
||||||
|
"retries": 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Every value here mirrors `gdl-cron.sh`'s own hand-paced defaults (see its
|
||||||
|
`SLEEP_REQUEST`/`SLEEP`/`RATE` comments) and `build_config()` in
|
||||||
|
`gdl-sync.py` — `api: rest` matters most: the graphql backend issues one
|
||||||
|
request PER POST for every video and carousel, the pattern that got this
|
||||||
|
account banned once already. `cookies` here is the config-file equivalent of
|
||||||
|
`--cookies-from-browser`, so a bare `gallery-dl <url>` is already
|
||||||
|
authenticated as the archive account, not anonymous.
|
||||||
|
|
||||||
|
Verified with `gallery_dl.config.load()` + `config.get(...)` (zero live
|
||||||
|
requests) — every value above loads correctly with no `--config` flag passed.
|
||||||
|
|
||||||
|
This file is **not tracked in the repo** — like `artms.db` and the state
|
||||||
|
files, it is host-local runtime config, and it embeds the same real
|
||||||
|
Chrome-profile path already documented above. Recreate it by hand (or from
|
||||||
|
this section) after a fresh `mattellite` setup.
|
||||||
|
|
||||||
## Remotes
|
## Remotes
|
||||||
|
|
||||||
| remote | what goes there |
|
| remote | what goes there |
|
||||||
@@ -482,6 +529,72 @@ The documented escalation is CDN 429 → 400 on a stories/highlights endpoint
|
|||||||
suspension. It has now run twice, and both times the 400 was the last warning
|
suspension. It has now run twice, and both times the 400 was the last warning
|
||||||
before something worse.
|
before something worse.
|
||||||
|
|
||||||
|
## Reels: the API is blocked, scrape by scrolling instead
|
||||||
|
|
||||||
|
As of 2026-08-26/27, `gallery-dl`'s dedicated reels extractor fails on every
|
||||||
|
profile with `HTTP redirect to home page` — confirmed hours apart, with a
|
||||||
|
freshly-warmed session and a correct `X-IG-WWW-Claim` header (that was the
|
||||||
|
first suspect; ruled out by tracing the raw HTTP exchange). It is not a
|
||||||
|
scraping-warning interstitial — the reels tab loads completely normally in a
|
||||||
|
real, already-signed-in browser — so this is Meta blocking the specific
|
||||||
|
`/api/v1/clips/user/` endpoint gallery-dl calls, not an account-health issue.
|
||||||
|
Posts, highlights and stories are unaffected; only reels breaks.
|
||||||
|
|
||||||
|
`scripts/reels-scrape.py` works around it by never calling that endpoint:
|
||||||
|
it drives the same signed-in Chrome via its loopback CDP port (`:9222`,
|
||||||
|
already exposed for MCP automation), scrolls the reels tab like a person
|
||||||
|
would, and scrapes `/reel/<code>/` links out of the rendered page. It only
|
||||||
|
finds shortcodes — nothing is downloaded until step 2 — and dedupes against
|
||||||
|
the archive first, so re-running it costs nothing for reels already held.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ssh mattellite
|
||||||
|
|
||||||
|
PROFILE=someuser
|
||||||
|
|
||||||
|
# 1. Scrape by scrolling; dedupe against the archive; write new URLs to a file.
|
||||||
|
# Needs gallery-dl's own pipx venv python -- that's where websocket-client
|
||||||
|
# (the one extra dependency this needs) got injected.
|
||||||
|
~/.local/share/pipx/venvs/gallery-dl/bin/python3 ~/gdl/reels-scrape.py \
|
||||||
|
--profile "$PROFILE" \
|
||||||
|
--index https://instaarchive.ergosteur.com \
|
||||||
|
--out ~/gdl/"$PROFILE"-reels.txt
|
||||||
|
|
||||||
|
# 2. Fetch whatever's new -- dry run first, same as any other gdl-sync.py call.
|
||||||
|
cd ~/gdl && PATH=$HOME/.local/bin:$PATH ./gdl-sync.py \
|
||||||
|
--publish agentapi@10.20.28.200:/volume1/rslsync/sync/Instagram-archive/archives/ \
|
||||||
|
--staging ~/gdl/staging-reels-scraped \
|
||||||
|
--sleep-request 12 20 --sleep 5 10 --rate 500K \
|
||||||
|
--post-urls-file ~/gdl/"$PROFILE"-reels.txt --dry-run
|
||||||
|
# ...then swap --dry-run for --execute once the plan looks right.
|
||||||
|
|
||||||
|
# 3. Clean up the scratch files -- reels-scrape.py's --out file and gdl-sync.py's
|
||||||
|
# own staging directory are both left behind on purpose (same reasoning as
|
||||||
|
# everywhere else here: nothing is silently deleted).
|
||||||
|
rm -rf ~/gdl/staging-reels-scraped ~/gdl/staging-reels-scraped.gdl-config.json \
|
||||||
|
~/gdl/"$PROFILE"-reels.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
Verified end to end against `zindoriyam` on 2026-08-27: 26 reels found on the
|
||||||
|
page, 16 already archived (correctly skipped), 10 new ones fetched and
|
||||||
|
published cleanly.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
- `reels-scrape.py` fails fast if Chrome/CDP isn't up
|
||||||
|
(`curl -s http://localhost:9222/json/version` to check first).
|
||||||
|
- If it finds nothing new, `gdl-sync.py --post-urls-file` refuses to run
|
||||||
|
("no usable URLs") rather than doing nothing quietly — expected when a
|
||||||
|
profile is already caught up.
|
||||||
|
- `--max-idle-rounds` (default 3) and `--scroll-pause MIN MAX` (default
|
||||||
|
`2.0 3.5`) are worth raising for an unusually large or slow-loading reels
|
||||||
|
tab; the default stops once 3 consecutive scrolls find nothing new.
|
||||||
|
- **Not wired into `gdl-cron.sh` or the timers.** It drives your actual
|
||||||
|
browser session rather than firing a background request, and it is slower
|
||||||
|
by design (real scrolling, not an API call) — both good reasons not to run
|
||||||
|
it unattended without deciding that deliberately. Today it is a per-profile,
|
||||||
|
by-hand tool only.
|
||||||
|
|
||||||
## What changed on 2026-08-20
|
## What changed on 2026-08-20
|
||||||
|
|
||||||
One session, three separate pieces of work. Recorded because the reasons are
|
One session, three separate pieces of work. Recorded because the reasons are
|
||||||
|
|||||||
Reference in New Issue
Block a user