extract_embedded_state
Tapak moden menyirikan data yang dipaparkan antara mukanya terus ke dalam dokumen. Alat ini membacanya semula: satu pengambilan, nilai yang tepat, dan tiada model langsung dalam laluan ekstraksi.
Kes Penggunaan
Harga tepat daripada halaman yang dipapar dengan JavaScript
Harga, tahap stok dan ID datang daripada keadaan tapak itu sendiri dan bukan daripada model yang membaca teks yang dipapar, jadi tiada apa yang boleh direka.
Penyenaraian yang tidak dapat dilihat oleh scrape biasa
Hasil carian dan grid produk yang dipapar di sebelah klien selalunya sudah pun hadir dalam __NEXT_DATA__ atau muatan RSC pada respons pertama.
Lebih murah daripada ekstraksi LLM
2 credits berbanding 3 bagi extract_with_llm atau extract_structured, tanpa langkah inferens yang perlu ditunggu.
Mengaudit apa yang tapak terbitkan tentang dirinya
found melaporkan setiap sumber keadaan pada halaman dan saiznya, yang selalunya lebih banyak daripada yang ditunjukkan antara muka.
Endpoint
/api/v1/tools/extract_embedded_stateParameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
url | string | Required | - | Halaman untuk membaca keadaan terbenam. Example: https://example.com/products/widget |
path | string | Optional | - | Memulangkan satu subpohon dan bukan keseluruhan muatan. Hanya kunci bertitik dan indeks tatasusunan - ini bukan JSONPath, jadi tiada kad liar, penapis, hirisan atau penurunan rekursif. Laluan yang tidak dapat diselesaikan dipulangkan sebagai 400 yang menamakan kunci yang ada di tempat ia berhenti, dan tidak mengenakan credits. Example: next_data.props.pageProps |
user_agent | string | Optional | - | Menggantikan User-Agent yang dihantar kepada sasaran. Permintaan kekal ditandatangani sebagai CrawlForge; tandatangan itu meliputi authority, bukan pengepala ini. Example: MyCompanyBot/1.0 |
respect_robots | boolean | Optional | true | Menghormati robots.txt tapak sasaran. Dibiarkan pada `true`, laluan yang tidak dibenarkan untuk `CrawlForge` ditolak dengan 403 sebelum apa-apa diambil dan tiada credits dikenakan. Tetapkan kepada `false` hanya untuk sasaran yang anda ada perjanjian sendiri dengannya - respons kemudiannya membawa entri `warnings` dan penggantian itu direkodkan terhadap API key anda. Example: true |
timeout | number | Optional | 20000 | Had masa pengambilan dalam milisaat, antara 1000 dan 60000. Muatan keadaan selalunya bersaiz megabait, jadi nilai lalai di sini lebih tinggi daripada alat ekstraksi yang lebih ringan. Example: 20000 |
Contoh Permintaan
cURL - Baca keseluruhan keadaan
curl -X POST https://crawlforge.dev/api/v1/tools/extract_embedded_state \
-H "X-API-Key: cf_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/products/widget"
}'TypeScript - Hadkan dengan path
const response = await fetch('https://crawlforge.dev/api/v1/tools/extract_embedded_state', {
method: 'POST',
headers: {
'X-API-Key': process.env.CRAWLFORGE_API_KEY!,
'Content-Type': 'application/json',
},
body: JSON.stringify({
url: 'https://example.com/products/widget',
// Dotted keys and array indexes. Not JSONPath: no wildcards or filters.
path: 'next_data.props.pageProps',
}),
});
const payload = await response.json();
if (!response.ok) {
// A path that does not resolve is a 400 naming the keys that were available.
throw new Error(payload.error.code + ': ' + payload.error.message);
}
const result = payload.data;
// Every state source on the page, largest first, whether or not it was scoped.
for (const source of result.found) {
console.log(source.name, source.variable, source.bytes);
}
// The values are the site's own, so they can be used as they are.
console.log(result.data.product.price);Python - Temui dahulu, kemudian hadkan
import os
import requests
URL = 'https://crawlforge.dev/api/v1/tools/extract_embedded_state'
HEADERS = {
'X-API-Key': os.environ['CRAWLFORGE_API_KEY'],
'Content-Type': 'application/json',
}
# 1. Discover what the page carries. Nothing is truncated, so this can be big.
discovery = requests.post(
URL,
headers=HEADERS,
json={'url': 'https://example.com/products/widget'},
).json()
for source in discovery['data']['found']:
print(source['name'], source['variable'], source['bytes'])
for warning in discovery['data']['warnings']:
print('warning:', warning)
# 2. Ask again for just the branch you want.
scoped = requests.post(
URL,
headers=HEADERS,
json={
'url': 'https://example.com/products/widget',
'path': 'next_data.props.pageProps.product',
},
)
payload = scoped.json()
if not scoped.ok:
error = payload['error']
raise RuntimeError(f"{error['code']}: {error['message']}")
print(payload['data']['bytes'], 'bytes')
print(payload['data']['data'])Contoh Respons
{ "success": true, "data": { "url": "https://example.com/products/widget", "found": [ { "name": "next_data", "variable": "__NEXT_DATA__", "bytes": 412880 } ], "path": null, "bytes": 412893, "data": { "next_data": { "buildId": "KfC_3GF1zuM", "props": { "pageProps": { "product": { "sku": "WID-9001", "price": 149.99, "currency": "USD", "inStock": true } } } } }, "warnings": [ "Result is 412893 bytes; \"next_data\" alone is 412880. Re-run with path to scope it, e.g. path:\"next_data.props\"." ] }, "credits_used": 2, "credits_remaining": 998, "processing_time": 980}data.foundSetiap sumber keadaan pada halaman, dengan objek asal ia dibaca dan saiz bersirinyadata.pathLaluan yang digunakan, atau null apabila keseluruhan muatan dipulangkandata.bytesSaiz bersiri bagi apa yang dipulangkan - selepas dihadkan, apabila path diberikandata.dataKeadaan itu sendiri, diindeks mengikut nama sumberdata.warningsSumber yang hadir tetapi tidak boleh dihuraikan sebagai JSON, dan petunjuk saiz yang mencadangkan penggunaan pathPengendalian Ralat
Laluan tidak dapat diselesaikan (400 Bad Request)
path tidak wujud dalam keadaan yang diekstrak. Mesejnya menamakan tempat ia berhenti dan kunci yang ada di situ, jadi kesilapan taip boleh terus dibetulkan. Tiada credits dikenakan. Jalankan panggilan sekali tanpa path untuk melihat apa yang sebenarnya dibawa oleh halaman itu.
Disekat oleh robots.txt (403 Forbidden)
robots.txt tapak sasaran tidak membenarkan laluan ini untuk CrawlForge. Tetapkan respect_robots: false untuk menggantikannya jika anda mempunyai perjanjian sendiri dengan sasaran - penggantian itu direkodkan terhadap API key anda. Penggantian ini tidak sampai kepada hos dalam senarai keluar kekal CrawlForge, yang ditolak apa pun nilai respect_robots.
Respons terlalu besar (413 Payload Too Large)
HTML halaman melebihi had badan 25MB. Had itu dikenakan pada halaman seperti yang dihidangkan, bukan pada keadaan yang diekstrak daripadanya. Tiada apa-apa dikenakan.
Sasaran tidak menjawab (504 Gateway Timeout)
Tapak itu tidak menjawab dalam timeout. Halaman yang sarat keadaan adalah besar; naikkan timeout ke arah siling 60000 sebelum menganggapnya sebagai kegagalan. Tiada apa-apa dikenakan.