--- name: llm_propose_scraping_schema kind: function lang: py domain: infra version: "1.0.0" purity: impure signature: "def llm_propose_scraping_schema(url: str, ax_tree: list, max_chunks: int = 5, max_chars_per_chunk: int = 25000) -> dict" description: "Orquesta trim_ax_tree -> chunk_ax_tree -> N llamadas a Claude CLI -> merge. Propone schema de scraping (fields, selectors, types) a partir del AX tree de una pagina." tags: [navegator, ai, llm, scraping, schema] uses_functions: [trim_ax_tree_py_core, chunk_ax_tree_py_core, claude_cli_prompt_py_infra] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: [json, re, sys, os] params: - name: url desc: "URL de la pagina (se incluye en el prompt a Claude para contexto)." - name: ax_tree desc: "AX tree como lista de dicts obtenida via CDP (cdp_get_ax_tree)." - name: max_chunks desc: "Maximo de chunks a procesar. Default 5. Si hay mas, truncated=True." - name: max_chars_per_chunk desc: "Caracteres maximos por chunk de AX tree enviado a Claude. Default 25000." output: "dict {schema: [{field, selector, sample_value, type, source_role}], notes: str, chunks_processed: int, truncated: bool}" tested: false tests: [] test_file_path: "" file_path: "python/functions/infra/llm_propose_scraping_schema.py" --- ## Ejemplo ```python import sys sys.path.insert(0, "python/functions") from infra.llm_propose_scraping_schema import llm_propose_scraping_schema # ax_tree obtenido previamente con cdp_get_ax_tree result = llm_propose_scraping_schema( url="https://shop.example.com/products", ax_tree=ax_tree, max_chunks=3, ) # {"schema": [{"field": "price", "selector": ".product-price", ...}], "notes": "...", ...} for field in result["schema"]: print(field["field"], "->", field["selector"]) ``` ## Cuando usarla Cuando tienes el AX tree de una pagina y quieres que Claude proponga automaticamente que campos extraer y con que selectores CSS. Paso de discovery antes de escribir la recipe YAML a mano o de forma asistida. ## Gotchas - Requiere `claude` CLI instalado y disponible en PATH (validado por `claude_cli_prompt`). - Cada chunk genera una llamada a Claude (coste de tokens). Usar `max_chunks` conservador en paginas muy grandes. - La respuesta de Claude se parsea tolerando fenced code blocks (```json ... ```). Si Claude devuelve prosa sin JSON, el chunk se omite con nota de error. - Dedup por `field`: primera ocurrencia gana si el mismo campo aparece en varios chunks. - No accede a red directamente — delega en `claude_cli_prompt`.