# Dicas para escrever expressões XPath

## A estrutura HTML pode diferir entre o documento raspado e o carregado pelo 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>

Ao লিখনা funções de seleção de elementos HTML, **certifique-se de trabalhar com documentos raspados em vez da versão do site ao vivo carregada no seu navegador**, pois os documentos podem ser diferentes. O principal motivo por trás desse problema é a renderização JavaScript. Quando um site é aberto, seu navegador é responsável por carregar documentos adicionais, como folhas de estilo CSS e scripts JavaScript, que podem alterar a estrutura do documento HTML inicial. Ao fazer o parsing de HTMLs raspados, o Custom Parser não carrega o documento HTML da mesma forma que os navegadores fazem (os parsers ignoram instruções JavaScript), portanto a árvore HTML pode diferir entre o que o parser e o navegador renderizam.

Como exemplo, veja o seguinte 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>
```

Se você abrir o documento pelo navegador, ele mostrará o preço que você pode selecionar usando a seguinte expressão XPath `//p[@id="price"]`:

<figure><img src="/files/dc4e010b09af93975ea6def9558cee08a3a691af" alt=""><figcaption></figcaption></figure>

Agora, se você desativar a renderização JavaScript no navegador, o site será renderizado da seguinte forma:

<figure><img src="/files/ab75bde67f6bed9cd482a49972a31192c4806b88" alt=""><figcaption></figcaption></figure>

A mesma `//p[@id="price"]` expressão XPath não corresponderá mais ao preço, pois ele não é renderizado.

## Certifique-se de escrever todos os seletores HTML possíveis para o elemento de destino <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 vários motivos, a mesma página raspada duas vezes pode ter layouts diferentes (diferentes User Agents usados na raspagem, o site de destino fazendo testes A/B, etc.).

Para lidar com esse problema, sugerimos definir `parsing_instructions` para o documento raspado inicialmente e testar essas instruções imediatamente com vários outros resultados de jobs raspados da mesma página.

As funções de seletor HTML (`xpath`/`xpath_one`) suportam [**fallbacks de seletor**](/products/pt-br/web-scraper-api/features/custom-parser/writing-instructions-manually/list-of-functions/function-examples.md#xpath).

## Fluxo sugerido para escrever seletores HTML <a href="#suggested-html-selector-writing-flow" id="suggested-html-selector-writing-flow"></a>

1. Raspe o documento HTML da página de destino usando o Scraper API.
2. Desative o JavaScript e abra o HTML raspado localmente no seu navegador. Se o JavaScript for desativado **depois** de o HTML ser aberto, certifique-se de recarregar a página para que o HTML possa ser recarregado sem JavaScript.
3. [**Use as ferramentas de desenvolvedor do navegador**](https://www.computerhope.com/issues/ch002153.htm).

<figure><img src="/files/ffc269c29ef62fa44b9ac6332e52a23646eaba01" alt=""><figcaption></figcaption></figure>

### Como escrever instruções de parsing  <a href="#how-to-write-parsing-instructions-inlineextension" id="how-to-write-parsing-instructions-inlineextension"></a>

Digamos que você tenha a seguinte página para fazer parsing:

```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">Bom</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="/files/8e84cc4ed7d9d4625c170d9d66bb68b1202cb44c" alt=""><figcaption></figcaption></figure>

### Parsear o título do produto

Crie um novo objeto JSON e atribua a ele um novo campo.

Você pode nomear o campo como preferir, com algumas exceções (o nome de campo definido pelo usuário não pode começar com um sublinhado `_` , por exemplo, `"_title"`).&#x20;

O nome do campo será exibido no resultado parseado.

O novo campo deve conter um valor do tipo objeto JSON:

```json
{
    "title": {}  // definindo um campo title para ser parseado
} 
```

Se você fornecer essas instruções ao Custom Parser, ele não fará nada ou enviará uma reclamação de que você não forneceu nenhuma instrução.

Para realmente fazer parse do título no `title` campo, você deve definir um pipeline de processamento de dados dentro do `title` objeto usando a propriedade reservada `_fns` (que é sempre do tipo array):

```json
{
    "title": {
        "_fns": []  // definindo pipeline de processamento de dados para o campo title
    }
}
```

Para o Custom Parser selecionar o texto do título, você pode utilizar a função de seletor HTML `xpath_one`. Para usar a função no documento HTML, ela deve ser adicionada ao pipeline de processamento de dados. A função é definida como um objeto JSON com o obrigatório `_fn` (nome da função) e os obrigatórios `_args` (argumentos da função) campos. Veja a lista completa de definições de funções [**aqui**](/products/pt-br/web-scraper-api/features/custom-parser/writing-instructions-manually/list-of-functions.md).

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

As instruções de parsing acima devem produzir o seguinte resultado:

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

### Parsear a descrição

Da mesma forma, nas instruções de parsing, você pode definir outro campo onde o contêiner da descrição do produto, o título da descrição e os itens serão parseados. Para que o título e os itens da descrição fiquem aninhados sob o `descrição` objeto, a estrutura das instruções deve ser a seguinte:

```json
{
    "title": {...},
    "description": { // contêiner da descrição
        "title": {}, // título da descrição
        "items": {} // itens da descrição
    } 
}
```

A estrutura dada das instruções de parsing implica que `description.title` e `description.items` serão parseados com base no `descrição` elemento. Você pode definir um pipeline para o `descrição` campo. Nesse caso, isso é feito primeiro, pois simplificará a expressão XPath do título da descrição.

```json
{
    "title": {...},
    "description": {
        "_fns": [
            {
                "_fn": "xpath_one",
                "_args": ["//div[@id='description-container']"]
            }
        ],  // O resultado do pipeline será usado ao fazer parsing de `title` e `items`.
        "title": {},
        "items": {}
    }
}
```

No exemplo, o `description._fns` pipeline selecionará o `description-container` elemento HTML, que será usado como ponto de referência para fazer parsing do título e dos itens da descrição.

Para fazer parsing dos campos restantes da descrição, adicione dois pipelines diferentes para os campos `description.items`, e `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()"
                    ]
                }
            ]
        }
    }
}
```

Observe como a `xpath` função é usada em vez de `xpath_one` para extrair todos os itens que correspondem à expressão XPath.

As instruções de parsing produzem o seguinte resultado:

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

### Parsear variantes do produto

O exemplo a seguir mostra a estrutura das instruções se você quiser parsear informações no campo `product_variants` que conterá uma lista de objetos de variante. Nesse caso, o objeto de variante tem `price` e `color` campos.

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

Comece selecionando todos os elementos de variante do produto:

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

Para fazer `product_variants` uma lista contendo objetos JSON, você terá que iterar pelas variantes encontradas usando `_items` iterador:

```json
{
    "title": {...},
    "description": {...},
    "product_variants": {
        "_fns": [
            {
                "_fn": "xpath",
                "_args": ["//div[@class='variant']"]
            }
        ],
        "_items": { // com isso, você está instruindo o processamento dos elementos encontrados um por um
            // instruções dos campos a serem descritas aqui
        } 
    }
}
```

Por fim, defina instruções sobre como parsear os `color` e `price` campos:

```json
{
    "title": {...},
    "description": {...},
    "product_variants": {
        "_fns": [
            {
                "_fn": "xpath",
                "_args": [
                    "//div[@class='variant']"
                ]
            }
        ],
        "_items": {
            "color": {
                "_fns": [
                    {
                        "_fn": "xpath_one",
                        "_args": [
                            // Como estamos usando expressões XPath relativas,
                            // certifique-se de que o XPath comece com um ponto (.)
                            ".//p[@class='color']/text()"
                        ]
                    }
                ]
            },
            "price": {
                "_fns": [
                    {
                        "_fn": "xpath_one",
                        "_args": [
                            ".//p[@class='price']/text()"
                        ]
                    }
                ]
            }
        }
    }
}
```

Com o endpoint `product_variants` como descrito, as instruções finais ficarão assim:

```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()"
                        ]
                    }
                ]
            }
        }
    }
}
```

O que produzirá a seguinte saída:

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

Você pode encontrar mais exemplos de instruções de parsing aqui: [**Exemplos de instruções de parsing**](/products/pt-br/web-scraper-api/features/custom-parser/writing-instructions-manually/parsing-instruction-examples.md).


---

# Agent Instructions: 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:

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

The question should be specific, self-contained, and written in natural language.
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.
