Add two posts: headless-browser scraping limits + NocoDB backfill gotchas
Deploy / build (push) Successful in 1m12s

- why-your-headless-browser-cant-scrape-everything (case study, en+zh)
- the-nocodb-attachment-that-wouldnt-update (note, en+zh)
- og + banner images for both, generator entries added
- gitignore .og/ scratch dir (also removes previously-committed scratch files)
This commit is contained in:
2026-09-09 06:56:20 +08:00
parent ca88623486
commit 62b681bad1
46 changed files with 537 additions and 1299 deletions
+39
View File
@@ -130,6 +130,45 @@ const BANNERS = {
{ n: '4', label: 'learn in public' },
],
},
'why-your-headless-browser-cant-scrape-everything': {
titlebar: 'root@dsm — headless browser vs anti-bot',
lines: [
{ t: 'prompt', text: '$' }, { t: 'cmd', text: 'browserless → goofish.com search?q=iPhone15' },
{ t: 'err', text: '非法访问 · "please use a normal browser"' },
{ t: 'dim', text: 'stealth flag · patched navigator.webdriver · real UA → still blocked' },
{ t: 'prompt', text: '$' }, { t: 'cmd', text: 'curl carousell search → parse __PRELOADED_STATE__' },
{ t: 'ok', text: 'listings + price + photos ✓ (no browser, no stealth)' },
{ t: 'hl', text: 'server-rendered JSON ≠ signed async API' },
{ t: 'prompt', text: '' }, { t: 'ok', text: 'read the data path before choosing a tool ✓' },
],
flow: [
{ n: '1', label: 'goofish' },
{ n: '2', label: 'signed API', err: true },
{ n: '3', label: 'carousell' },
{ n: '4', label: 'server JSON', err: false },
{ n: '5', label: 'parsed ✓' },
],
},
'the-nocodb-attachment-that-wouldnt-update': {
titlebar: 'root@dsm — nocodb backfill',
lines: [
{ t: 'prompt', text: '$' }, { t: 'cmd', text: 'PATCH image path = fullsize_url' },
{ t: 'dim', text: '200 OK — but readback still shows the old thumbnail' },
{ t: 'prompt', text: '$' }, { t: 'cmd', text: 'grep image.json | jq .id' },
{ t: 'hl', text: 'id present → NocoDB resolves by id, ignores new path' },
{ t: 'prompt', text: '$' }, { t: 'cmd', text: 'drop id + signedPath · url.replace("_progressive_thumbnail","")' },
{ t: 'prompt', text: '' }, { t: 'ok', text: '300 rows updated ✓' },
],
flow: [
{ n: '1', label: 'patch path' },
{ n: '2', label: 'id keeps old', err: true },
{ n: '3', label: 'strip id' },
{ n: '4', label: 'replace() suffix' },
{ n: '5', label: 'updated ✓' },
],
},
};
const DEFAULT_BANNER = {
+10
View File
@@ -58,6 +58,16 @@ const TERMINALS = {
<div class="line"><span class="prompt">$</span><span class="cmd">docker compose pull authentik-worker</span></div>
<div class="line"><span class="prompt">&nbsp;</span><span class="err">authorization_flow not found · SSO broken</span></div>
<div class="line"><span class="prompt">$</span><span class="cmd">uptime: 2025.8 → 2026.8</span><span class="fix">fixed ✓</span></div>`,
'why-your-headless-browser-cant-scrape-everything': `
<div class="line"><span class="prompt">$</span><span class="cmd">browserless → goofish search</span></div>
<div class="line"><span class="prompt">&nbsp;</span><span class="err">非法访问 · product list stuck "loading…"</span></div>
<div class="line"><span class="prompt">$</span><span class="cmd">carousell: server-rendered JSON</span><span class="fix">→ parsed ✓</span></div>`,
'the-nocodb-attachment-that-wouldnt-update': `
<div class="line"><span class="prompt">$</span><span class="cmd">PATCH image path → 300 rows backfill</span></div>
<div class="line"><span class="prompt">&nbsp;</span><span class="err">path unchanged · keep the id, keep the old URL</span></div>
<div class="line"><span class="prompt">$</span><span class="cmd">strip id · replace() suffix</span><span class="fix">→ updated ✓</span></div>`,
};
const DEFAULT_TERMINAL = `