> For the complete documentation index, see [llms.txt](https://developers.oxylabs.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers.oxylabs.io/products/es/web-scraper-api/features/custom-parser/writing-instructions-manually/tips-for-writing-xpath-expressions.md).

# Consejos para escribir expresiones XPath

Aprende a escribir expresiones XPath eficaces para Custom Parser con técnicas probadas y buenas prácticas que garantizan una extracción precisa de datos.

## La estructura HTML puede diferir entre el documento raspado y el cargado por el navegador <a href="#html-structure-may-differ-between-scraped-and-browser-loaded-document" id="html-structure-may-differ-between-scraped-and-browser-loaded-document"></a>

Al escribir funciones de selección de elementos HTML, **asegúrese de trabajar con documentos raspados en lugar de la versión activa del sitio web cargada en su navegador**, ya que los documentos pueden diferir. La razón principal de este problema es la renderización de JavaScript. Cuando se abre un sitio web, su navegador es responsable de cargar documentos adicionales, como hojas de estilo CSS y scripts de JavaScript, que pueden cambiar la estructura del documento HTML inicial. Al analizar HTML raspado, Custom Parser no carga el documento HTML de la misma manera que lo hacen los navegadores (los analizadores ignoran las instrucciones de JavaScript), por lo que el árbol HTML puede diferir entre lo que renderiza el analizador y el navegador.

Como ejemplo, eche un vistazo al siguiente documento HTML:

```html
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div>
        <h3>This is a product</h3>
        <div id="price-container">
            <p>This is the price:</p>
        </div>
        <p>And here is some description</p>
    </div>
    <script>
        const priceContainer = document.querySelector("#price-container");
        const priceElement = document.createElement("p");
        priceElement.textContent = "123";
        priceElement.id = "price"
        priceContainer.insertAdjacentElement("beforeend", priceElement);
    </script>
</body>
</html>
```

Si abre el documento en el navegador, mostrará el precio que puede seleccionar usando la siguiente expresión XPath `//p[@id="price"]`:

<figure><img src="https://2786356907-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FBQ7Zf9paoN3FTeGcyfY1%2Fuploads%2Fgit-blob-263311afb3c0140c55bab8281e45bb78e75cad75%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

Ahora, si desactiva la renderización de JavaScript en el navegador, el sitio web se renderizará de la siguiente manera:

<figure><img src="https://2786356907-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FBQ7Zf9paoN3FTeGcyfY1%2Fuploads%2Fgit-blob-ba30964ee602e0f3a01ee0d7491618f2136e6366%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

La misma `//p[@id="price"]` expresión XPath ya no coincide con el precio, ya que no se renderiza.

## Asegúrese de escribir todos los selectores HTML posibles para el elemento objetivo <a href="#make-sure-to-write-all-possible-html-selectors-for-the-target-element" id="make-sure-to-write-all-possible-html-selectors-for-the-target-element"></a>

Por varias razones, la misma página raspada dos veces puede tener diseños diferentes (diferentes agentes de usuario usados al raspar, el sitio web objetivo realizando pruebas A/B, etc.).

Para abordar este problema, sugerimos definir `parsing_instructions` para el documento raspado inicialmente y probar estas instrucciones de inmediato con otros resultados raspados del mismo tipo de página.

Las funciones de selector HTML (`xpath`/`xpath_one`) admiten [**alternativas de selector**](/products/es/web-scraper-api/features/custom-parser/writing-instructions-manually/list-of-functions/function-examples.md#xpath).

## Flujo sugerido para escribir selectores HTML <a href="#suggested-html-selector-writing-flow" id="suggested-html-selector-writing-flow"></a>

1. Raspe el documento HTML de la página objetivo usando Scraper API.
2. Desactive JavaScript y abra el HTML raspado localmente en su navegador. Si JavaScript está desactivado **después de** abrir el HTML, asegúrese de recargar la página para que el HTML pueda recargarse sin JavaScript.
3. [**Use las herramientas de desarrollo del navegador**](https://www.computerhope.com/issues/ch002153.htm).

<figure><img src="https://2786356907-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FBQ7Zf9paoN3FTeGcyfY1%2Fuploads%2Fgit-blob-c8d8e66b5e65191bf42b835faeb8f13ac66b5241%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

### Cómo escribir instrucciones de análisis <a href="#how-to-write-parsing-instructions-inlineextension" id="how-to-write-parsing-instructions-inlineextension"></a>

Supongamos que tiene la siguiente página para analizar:

```html
`<!doctype html>
<html lang="en">
<head></head>
<body>
<style>
.variant {
  display: flex;
  flex-wrap: nowrap;
}
.variant p {
  white-space: nowrap;
  margin-right: 20px;
}
</style>
<div>
    <h1 id="title">This is a cool product</h1>
    <div id="description-container">
        <h2>This is a product description</h2>
        <ul>
            <li class="description-item">Durable</li>
            <li class="description-item">Nice</li>
            <li class="description-item">Sweet</li>
            <li class="description-item">Spicy</li>
        </ul>
    </div>
    <div id="price-container">
        <h2>Variants</h2>
        <div id="variants">
            <div class="variant">
                <p class="color">Red</p>
                <p class="price">99.99</p>
            </div>
            <div class="variant">
                <p class="color">Green</p>
                <p class="price">87.99</p>
            </div>
            <div class="variant">
                <p class="color">Blue</p>
                <p class="price">65.99</p>
            </div>
            <div class="variant">
                <p class="color">Black</p>
                <p class="price">99.99</p>
            </div>
        </div>
    </div>
</div>
</body>
</html>
```

<figure><img src="https://2786356907-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FBQ7Zf9paoN3FTeGcyfY1%2Fuploads%2Fgit-blob-2be44ded8fc6df9110f5a6a47ba23f2ccfb8e627%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

### Analizar el título del producto

Cree un nuevo objeto JSON y asígnele un nuevo campo.

Puede nombrar el campo como prefiera, con algunas excepciones (el nombre de campo definido por el usuario no puede comenzar con un guion bajo `_` , por ejemplo, `"_title"`).

El nombre del campo se mostrará en el resultado analizado.

El nuevo campo debe contener un valor de tipo objeto JSON:

```json
{
    "title": {}  // defining a title field to be parsed
} 
```

Si proporciona estas instrucciones a Custom Parser, no haría nada o enviaría una queja indicando que no ha proporcionado ninguna instrucción.

Para analizar realmente el título en el `title` campo, debe definir una canalización de procesamiento de datos dentro del `title` objeto usando la propiedad reservada `_fns` propiedad (que siempre es de tipo array):

```json
{
    "title": {
        "_fns": []  // defining data processing pipeline for the title field
    }
}
```

Para que Custom Parser seleccione el texto del título, puede utilizar la función de selector HTML `xpath_one`. Para usar la función en el documento HTML, debe agregarse a la canalización de procesamiento de datos. La función se define como un objeto JSON con los campos obligatorios `_fn` (nombre de la función) y campos obligatorios `_args` (argumentos de la función). Consulte la lista completa de definiciones de funciones [**aquí**](/products/es/web-scraper-api/features/custom-parser/writing-instructions-manually/list-of-functions.md).

```json
{
    "title": {
        "_fns": [
            {
                "_fn": "xpath_one",
                "_args": ["//h1/text()"]
            }
        ]
    }
}
```

Las instrucciones de análisis anteriores deberían producir el siguiente resultado:

```json
{
    "title": "This is a cool product"
}
```

### Analizar la descripción

De manera similar, en las instrucciones de análisis, puede definir otro campo donde se analizarán el contenedor de la descripción del producto, el título de la descripción y los elementos. Para que el título y los elementos de la descripción queden anidados bajo el `descripción` objeto, la estructura de las instrucciones debe ser la siguiente:

```json
{
    "title": {...},
    "description": { // description container
        "title": {}, // description title
        "items": {} // description items
    } 
}
```

La estructura dada de las instrucciones de análisis implica que `description.title` y `description.items` se analizarán en función del `descripción` elemento. Puede definir una canalización para el `descripción` "\_args": \["//div\[@id='description-container']"]

```json
{
    "title": {...},
    "description": {
        "_fns": [
            {
                "_fn": "xpath_one",
                ],  // Pipeline result will be used when parsing `title` and `items`.
            }
        "title": {},
        "items": {}
        "items": {}
    }
}
```

En el ejemplo, la `description._fns` canalización `description-container` elemento HTML, que se utilizará como punto de referencia para analizar el título y los elementos de la descripción.

Para analizar los campos restantes de la descripción, agregue dos canalizaciones diferentes para los campos `description.items`, y `description.title`:

```json
{
    "title": {...},
    "description": {
        "_fns": [
            {
                "_fn": "xpath_one",
                "_args": [
                    "//div[@id='description-container']"
                ]
            }
        ],
        "title": {
            "_fns": [
                {
                    "_fn": "xpath_one",
                    "_args": [
                        "//h2/text()"
                    ]
                }
            ]
        },
        "items": {
            "_fns": [
                {
                    "_fn": "xpath",
                    "_args": [
                        "//li/text()"
                    ]
                }
            ]
        }
    }
}
```

Fíjate en cómo la `xpath` se usa en lugar de `xpath_one` para extraer todos los elementos que coinciden con la expresión XPath.

Las instrucciones de análisis producen el siguiente resultado:

```json
{
    "title": {...},
    "description": {
        "title": "This is description about the product",
        "items": [
            "Durable",
            "Nice",
            "Sweet",
            "Spicy"
        ]
    }
}
```

### Analizar variantes del producto

El siguiente ejemplo muestra la estructura de las instrucciones si desea analizar información en el `product_variants` campo, que contendrá una lista de objetos de variante. En este caso, el objeto de variante tiene `precio` y `color` campos.

```json
{
    "title": {...},
    "description": {...},
    "product_variants": [
        {
            "price": ...,
            "color": ...
        },
        {
            ...
        },
        ...
    ]
}
```

Comience seleccionando todos los elementos de variante del producto:

```json
{
    "title": {...},
    "description": {...},
    "product_variants": {
        "_fns": [
            {
                "_fn": "xpath",
                "_args": ["//div[@class='variant']"]
            }
        ]
    }
}
```

Para convertir `product_variants` en una lista que contenga objetos JSON, deberá iterar sobre las variantes encontradas usando `_items` iterador:

```json
{
    "title": {...},
    "description": {...},
    "product_variants": {
        "_fns": [
            {
                "_fn": "xpath",
                "_args": ["//div[@class='variant']"]
            }
        ],
        "_items": { // with this, you are instructing to process found elements one by one
            // field instructions to be described here
        } 
    }
}
```

Por último, defina las instrucciones sobre cómo analizar los `color` y `precio` campos:

```json
{
    "title": {...},
    "description": {...},
    "product_variants": {
        "_fns": [
            {
                "_fn": "xpath",
                "_args": [
                    "//div[@class='variant']"
                ]
            }
        ],
        "_items": {
            "color": {
                "_fns": [
                    {
                        "_fn": "xpath_one",
                        "_args": [
                            // As we are using relative XPath expressions,
                            // make sure XPath starts with a dot (.)
                            ".//p[@class='color']/text()"
                        ]
                    }
                ]
            },
            "price": {
                "_fns": [
                    {
                        "_fn": "xpath_one",
                        "_args": [
                            ".//p[@class='price']/text()"
                        ]
                    }
                ]
            }
        }
    }
}
```

Con `product_variants` descritas, las instrucciones finales se verán así:

```json
{
    "title": {
        "_fns": [
            {
                "_fn": "xpath_one",
                "_args": [
                    "//h1/text()"
                ]
            }
        ]
    },
    "description": {
        "_fns": [
            {
                "_fn": "xpath_one",
                "_args": [
                    "//div[@id='description-container']"
                ]
            }
        ],
        "title": {
            "_fns": [
                {
                    "_fn": "xpath_one",
                    "_args": [
                        "//h2/text()"
                    ]
                }
            ]
        },
        "items": {
            "_fns": [
                {
                    "_fn": "xpath",
                    "_args": [
                        "//li/text()"
                    ]
                }
            ]
        }
    },
    "product_variants": {
        "_fns": [
            {
                "_fn": "xpath",
                "_args": [
                    "//div[@class='variant']"
                ]
            }
        ],
        "_items": {
            "color": {
                "_fns": [
                    {
                        "_fn": "xpath_one",
                        "_args": [
                            ".//p[@class='color']/text()"
                        ]
                    }
                ]
            },
            "price": {
                "_fns": [
                    {
                        "_fn": "xpath_one",
                        "_args": [
                            ".//p[@class='price']/text()"
                        ]
                    }
                ]
            }
        }
    }
}
```

Lo que producirá el siguiente resultado:

```json
{
    "title": "This is a cool product",
    "description": {
        "title": "This is a product description",
        "items": [
            "Durable",
            "Nice",
            "Sweet",
            "Spicy"
        ]
    },
    "product_variants": [
        {
            "color": "Red",
            "price": "99.99"
        },
        {
            "color": "Green",
            "price": "87.99"
        },
        {
            "color": "Blue",
            "price": "65.99"
        },
        {
            "color": "Black",
            "price": "99.99"
        }
    ]
}
```

Puede encontrar más ejemplos de instrucciones de análisis aquí: [**Ejemplos de instrucciones de análisis**](/products/es/web-scraper-api/features/custom-parser/writing-instructions-manually/parsing-instruction-examples.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://developers.oxylabs.io/products/es/web-scraper-api/features/custom-parser/writing-instructions-manually/tips-for-writing-xpath-expressions.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
