Add two posts: headless-browser scraping limits + NocoDB backfill gotchas
Deploy / build (push) Successful in 1m12s
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:
@@ -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 = {
|
||||
|
||||
@@ -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"> </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"> </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"> </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 = `
|
||||
|
||||
Reference in New Issue
Block a user