# Ejemplos de instrucciones de análisis

El siguiente fragmento de HTML se analiza usando instrucciones de análisis de ejemplo en las secciones siguientes.

### HTML de ejemplo <a href="#sample-html" id="sample-html"></a>

```html
<body>
    <div id="products">
        <div class="product" id="shoes">
            <div class="title">Shoes</div>
            <div class="price">223.12</div>
            <div class="description">
                <ul>
                    <li class="description-item">Super</li>
                </ul>
            </div>
        </div>
        <div class="product" id="pants">
            <div class="title">Pants</div>
            <div class="price">60.12</div>
            <div class="description">
                <ul>
                    <li class="description-item">Amazing</li>
                    <li class="description-item">Quality</li>
                </ul>
            </div>
        </div>
        <div class="product" id="socks">
            <div class="title">Socks</div>
            <div class="price">123.12</div>
            <div class="description">
                <ul>
                    <li class="description-item">Very</li>
                    <li class="description-item">Nice</li>
                    <li class="description-item">Socks</li>
                </ul>
            </div>
        </div>
    </div>
</body>
```

### Mínimo imprescindible <a href="#bare-minimum" id="bare-minimum"></a>

{% hint style="info" %}
Caso de uso: quieres extraer el texto de todos **shoes** **description** **elementos**.
{% endhint %}

*Ejemplo 1. Selección de los elementos de descripción de shoes usando XPath.*

```json
{
    "shoes_description": {
        "_fns": [
            {
                "_fn": "xpath",
                "_args": [
                    ".//div[@id='shoes']//li[@class='description-item']/text()"
                ]
            }
        ]
    }
}
```

El `xpath` la función encontrará un único elemento y lo pondrá en una lista como cadena:

```json
{
    "shoes_description": [
        "Super"
    ]
}
```

El comportamiento exacto de la `xpath` función se describe [**aquí**](https://developers.oxylabs.io/documentation/es/soluciones-de-scraping/web-scraper-api/features/custom-parser/writing-instructions-manually/list-of-functions).

### Instrucciones de análisis anidadas <a href="#nested-parsing-instructions" id="nested-parsing-instructions"></a>

{% hint style="info" %}
Caso de uso: quieres analizar toda la información relacionada con shoes. Además, el resultado analizado debe representar la estructura del documento del HTML proporcionado.
{% endhint %}

Estás apuntando a esta parte del HTML de ejemplo:

```html
<div class="product" id="shoes">
    <div class="title">Shoes</div>
    <div class="price">223.12</div>
    <div class="description">
        <ul>
            <li class="description-item">Super</li>
        </ul>
    </div>
</div>
```

Y te gustaría que el resultado analizado tuviera la siguiente estructura:

```json
{
    "shoes": {
        "title": "Shoes",
        "price": "223.12",
        "description": [
            "Super"
        ]
    }
}
```

Las instrucciones de análisis se verían de la siguiente manera.

*Ejemplo 2. Se usan instrucciones de análisis para extraer* `shoes` *información.*

```json
{
    "shoes": {
        "title": {
            "_fns": [
                {
                    "_fn": "xpath_one",
                    "_args": ["//div[@id='shoes']/div[@class='title']/text()"]
                }
            ]
        },
        "price": {
            "_fns": [
                {
                    "_fn": "xpath_one",
                    "_args": ["//div[@id='shoes']/div[@class='price']/text()"]
                }
            ]
        },
        "description": {
            "_fns": [
                {
                    "_fn": "xpath",
                    "_args": ["//div[@id='shoes']//li[@class='description-item']/text()"]
                }
            ]
        }
    }
}
```

`xpath_one` funciona de forma similar a `xpath`, pero en lugar de devolver una lista con todas las coincidencias, **devuelve el primer elemento coincidente**.

En el ejemplo anterior, la `shoes` propiedad es la única propiedad definida en el ámbito de instrucciones más externo. La `shoes` propiedad contiene instrucciones de análisis anidadas.

El `shoes` el ámbito de instrucciones no tiene un pipeline definido (`_fns` la propiedad falta). Esto significa que los pipelines definidos en `title`, `price`, y `description` los ámbitos usarán el documento en análisis como entrada del pipeline.

En el Ejemplo 2, puedes ver una repetición de `//div[@id='shoes']` en las expresiones XPath. La repetición puede evitarse definiendo un pipeline en `shoes` ámbito:

*Ejemplo 3. Definir un pipeline en las instrucciones del* `shoes` *ámbito para evitar la repetición de expresiones XPath.*

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

Usando las instrucciones de análisis proporcionadas en el Ejemplo 3, Custom Parser:

1. Comenzará procesando `shoes._fns` el pipeline, que producirá el `shoes` elemento HTML;
2. Tomará la salida del `shoes._fns` pipeline y la usará como entrada para los pipelines definidos en `title`, `price`, y `description` ámbitos;
3. Procesará los `title`, `price`, y `description` pipelines para producir los valores finales.

El resultado se verá igual que el resultado del Ejemplo 2:

```json
{
    "shoes": {
        "title": "Shoes",
        "price": "223.12",
        "description": [
            "Super"
        ]
    }
}
```

La diferencia principal entre el Ejemplo 2 y el Ejemplo 3 es que en el Ejemplo 3, el pipeline está definido en el `shoes` ámbito. **Este pipeline adicional selecciona el elemento de shoes y lo pasa a pipelines posteriores que se encuentran más abajo en la jerarquía de instrucciones.**

### Lista de objetos anidados <a href="#list-of-nested-objects" id="list-of-nested-objects"></a>

{% hint style="info" %}
**Caso de uso:** Anteriormente, querías analizar solo la información de `shoes` Ahora quieres analizar la información de todos los productos en el HTML.
{% endhint %}

El [**HTML de ejemplo**](#sample-html) se usa nuevamente como el documento en análisis.

Si quieres que tu resultado analizado se vea así:

```json
{
    "products": [
        {
            "title": "Shoes",
            "price": "223.12",
            "description": [
                "Super"
            ]
        },
        {
            "title": "Pants",
            "price": "60.12",
            "description": [
                "Amazing",
                "Quality"
            ]
        },
        {
            "title": "Socks",
            "price": "123.12",
            "description": [
                "Very",
                "Nice",
                "Socks"
            ]
        }
    ]
}
```

Las instrucciones de análisis se verían así:

*Ejemplo 4. Analizar todos los productos encontrados en el documento HTML.*

```json
{
    "products": {
        "_fns": [
            {
                "_fn": "xpath",
                "_args": ["//div[@class='product']"]
            }
        ],
        "_items": {
            "title": {
                "_fns": [
                    {
                        "_fn": "xpath_one",
                        "_args": ["./div[@class='title']/text()"]
                    }
                ]
            },
            "price": {
                "_fns": [
                    {
                        "_fn": "xpath_one",
                        "_args": ["./div[@class='price']/text()"]
                    }
                ]
            },
            "description": {
                "_fns": [
                    {
                        "_fn": "xpath",
                        "_args": [".//li[@class='description-item']/text()"]
                    }
                ]
            }
        }
    }
}
```

La estructura de las instrucciones de análisis es similar a la del Ejemplo 3. Sin embargo, hay dos excepciones principales:

1. `xpath` se usa en lugar de `xpath_one` en `products._fns` pipeline. `products._fns` el pipeline ahora devolverá una lista de todos los elementos que coincidan con la expresión XPath proporcionada (una lista de elementos product).
2. `_items` la propiedad reservada se usa para indicar que quieres formar una lista iterando por cada elemento de la salida del `products._fns` pipeline y **pasando/procesando cada elemento de la lista por separado** a través del ámbito del pipeline.

Si la propiedad `_items` reservada no se hubiera usado en las instrucciones de análisis del Ejemplo 4, el resultado analizado se vería así:

```json
{
    "products": {
        "title": [
            "Shoes",
            "Pants",
            "Socks"
        ],
        "price": [
            "223.12",
            "60.12",
            "123.12"
        ],
        "description": [
            [
                "Super"
            ],
            [
                "Amazing",
                "Quality"
            ],
            [
                "Very",
                "Nice",
                "Socks"
            ]
        ]
    }
}
```

{% hint style="warning" %}
`_items` se usa para especificar que Custom Parser debe pasar ***elementos de lista separados*** en lugar de la ***lista completa*** a través de las instrucciones de análisis.
{% endhint %}

### Seleccionar el enésimo elemento de una lista  <a href="#select-n-th-element-from-a-list" id="select-n-th-element-from-a-list"></a>

Esta sección demuestra la flexibilidad de los pipelines. El mismo problema puede abordarse de distintas maneras.

Se pueden usar múltiples opciones para seleccionar el enésimo elemento de una lista de valores cualquiera.

{% hint style="info" %}
**Caso de uso:** quieres seleccionar el precio del segundo producto de la página.
{% endhint %}

El [**HTML de ejemplo**](#sample-html) se usa nuevamente como ejemplo. Tienes varias opciones para seleccionar el 2.º producto.

#### Opción 1 <a href="#option-1" id="option-1"></a>

Puedes utilizar el selector XPath `[]` y definir la selección en la expresión XPath.

*Ejemplo 5. Seleccionar el 2.º precio usando el selector XPath \[].*

```json
{
    "second_price": {
        "_fns": [
            {
                "_fn": "xpath",
                "_args": [
                    "(//div[@class='price'])[2]/text()"
                ]
            }
        ]
    }
}
```

Resultado:

```json
{
    "second_price": [
        "60.12"
    ]
}
```

#### Opción 2 <a href="#option-2" id="option-2"></a>

También puedes usar la función `xpath` para encontrar todos los precios y encadenarla a la función `select_nth`, que selecciona el n-ésimo elemento de la lista extraída de precios.

*Ejemplo 6. Seleccionar el 2.º valor usando la función \`select\_nth\`.*

```json
{
    "second_price": {
        "_fns": [
            {
                "_fn": "xpath",
                "_args": [
                    "//div[@class='price']/text()"
                ]
            },
            {
                "_fn": "select_nth",
                "_args": 1
            }
        ]
    }
}
```

Resultado:

```json
{
    "second_price": "60.12"
}
```

{% hint style="warning" %}
Observa cómo la función `select_nth` devuelve un elemento de una lista mientras que la función `xpath` devuelve una lista de elementos, incluso si se encuentra un solo elemento.
{% endhint %}

#### Opción 3  <a href="#option-3" id="option-3"></a>

Puedes usar `select_nth` con cualquier tipo de lista, incluidas listas de elementos HTML:

*Ejemplo 7. Seleccionar todos los elementos HTML de producto con* `class="product"` *==> seleccionar el 2.º elemento de producto de la lista ==> extraer el texto del precio del elemento HTML de producto seleccionado*.

```json
{
    "second_price": {
        "_fns": [
            {
                "_fn": "xpath",
                "_args": ["//div[@class='product']"]
            },
            {
                "_fn": "select_nth",
                "_args": 1
            },
            {
                "_fn": "xpath",
                "_args": ["./div[@class='price']/text()"]
            }
        ]
    }
}
```

Resultado:

```json
{
    "second_price": ["60.12"]
}
```

### Manejo de errores <a href="#error-handling" id="error-handling"></a>

Dado el siguiente fragmento de HTML:

```html
<div class="product" id="shoes">
    <div class="title">Nice Shoes</div>
    <div class="price">223.12</div>
    <div class="description">Super</div>
</div>
```

Y tratando de analizarlo con las siguientes instrucciones de análisis:

```json
{
    "product": {
        "_fns": [
            {
                "_fn": "xpath_one",
                "_args": ["//div[@id='shoes']"]
            }
        ],
        "price": {
            "_fns": [
                {
                    "_fn": "xpath_one",
                    "_args": ["//div[@class='price']/text()"]
                }
            ]
        },
        "title": {
            "_fns": [
                {
                    "_fn": "xpath_one",
                    "_args": ["//div[@class='title']/text()"]
                }
            ]
        },
        "description": {
            "_fns": [
                {
                    "_fn": "xpath_one",
                    "_args": ["//div[@class='description']/text()"]
                },
                {
                    "_fn": "convert_to_float"
                }
            ]
        }
    }
}
```

Custom Parser devolverá un resultado analizado donde `price` y `title` se analizaron normalmente, pero la `description` no se pudo analizar debido a la función `convert_to_float` que falló al convertir `string` to `float`:

```json
{
    "product": {
        "price": "223.12",
        "title": "Shoes",
        "description": null
    },
    "_warnings": [
        {
            "_fn": "convert_to_float",
            "_fn_idx": 1,
            "_msg": "Failed to process function.",
            "_path": ".product.description"
        }
    ]
}
```

Por defecto, todos los errores se consideran advertencias y se colocan dentro de la lista `_warnings` . Si deseas ignorar los errores al analizar un campo, puedes suprimir advertencias/errores con `"_on_error": "suppress"` parámetro:

```json
{
    "product": {
        ...,
        "description": {
            "_on_error": "suppress",
            "_fns": [
                {
                    "_fn": "xpath_one",
                    "_args": ["//div[@class='description']/text()"]
                },
                {
                    "_fn": "convert_to_float"
                }
            ]
        }
    }
}
```

Lo cual producirá el siguiente resultado:

```json
{
    "product": {
        "price": "223.12",
        "title": "Shoes",
        "description": null
    }
}
```

### Matriz de matrices <a href="#array-of-arrays" id="array-of-arrays"></a>

Custom Parser permite arrays N-dimensionales en los resultados analizados. Como ejemplo, usemos el siguiente fragmento de HTML:

```html
<div class="row">
    <div class="column">1</div>
    <div class="column">2</div>
    <div class="column">3</div>
</div>
<div class="row">
    <div class="column">4</div>
    <div class="column">5</div>
    <div class="column">6</div>
</div>
<div class="row">
    <div class="column">7</div>
    <div class="column">8</div>
    <div class="column">9</div>
</div>
```

Digamos que quieres analizar el documento de modo que el resultado sea una matriz 2D 3x3 de enteros:

```json
{
    "table": [
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9],
    ]
}
```

Para convertir el HTML en el JSON anterior, puedes usar las siguientes instrucciones de análisis:

```json
{
    "table": {
        "_fns": [
            {
                "_fn": "xpath",
                "_args": ["//div[@class='row']"]
            },
            {
                "_fn": "xpath",
                "_args": [".//div[@class='column']/text()"]
            },
            {
                "_fn": "convert_to_int"
            }
        ]
    }
}
```
