No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Convierte tus certificados en títulos universitarios en USA

Antes: $249

Currency
$209

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

19 Días
16 Hrs
26 Min
5 Seg

Aplicando lo aprendido

16/21
Recursos

Aportes 292

Preguntas 10

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Una opción que descubrí mientras hacía debuging de la expresión Xpath para el Stock Availability, fue copiar la ruta Xpath directamente desde el código HTML en Google Chrome, de la siguiente manera:

  1. Con la flecha del inspector de elementos, selecciona el punto al que te gustaría hacerle scrapping. Ello te llevará al punto en el código HTML para que investigues su ruta.
  2. Al hacer click derecho sobre esa porción de código HTML, selecciona Copy y luego Copy Xpath
    .

    .
  3. Luego copialo en la cónsola y sólo tendrías que adaptarle el formato para que lo obtengas como deseas.

IMPORTANTE: Al usar este método puedes perder legibilidad del código, lo que podría dificultar la colaboración de otro compañero y/o dificultar que puedas mantener el código tiempo después. Por lo que lo vería más como un complemento que como una solución definitiva para Xpath.

No existe una única forma de resolver el reto, y de hecho puede reducirse muchisimo el tamaño de la expresión si identificamos lo indispensable, tal como en el caso del stock en el siguiente ejemplo:

//Description
$x('//article[@class="product_page"]/p/text()').map(x=>x.wholeText)

//Stock available
$x('//article[@class="product_page"]/div[@class="row"]/div[@class="col-sm-6 product_main"]/p[@class="instock availability"]/text()[2]').map(x=>x.wholeText)
$x('//p[@class="instock availability"]/text()[2]').map(x=>x.wholeText)```

El stock :

$x('//table[@class="table table-striped"]/tbody/tr[6]/td/text()').map(x => x.wholeText)

La descripción

$x('//article[@class="product_page"]/p/text()').map(x => x.wholeText.trim())

:

RESUMEN :

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

  • Realizar expresiones Xpath para:
  • Descripción:
$x('//article/p/text()').map(x => x.wholeText)
["It's hard to imagine a world without A Light in th…for you. Shel, you never sounded so good. ...more"]
  • Stock
$x('//article[@class="product_page"]//p[@class="instock availability"]/text()').map(x=>x.wholeText)

  • Precio
$x('//article[@class="product_pod"]/div[@class="product_price"]/p[@class="price_color"]/text()').map(x=>x.wholeText)
#Devuelve: (20) ["£51.77", "£53.74", "£50.10", "£47.82", "£54.23", "£22.65", "£33.34", "£17.93", "£22.60", "£52.15", "£13.99", "£20.66", "£17.46", "£52.29", "£35.02", "£57.25", "£23.88", "£37.59", "£51.33", "£45.17"]
  • Barra lateral izquierda categorías :
$x('//div[@class="side_categories"]//a[@href]/text()').map(x=>x.wholeText)

// ejemplos de https://books.toscrape.com/index.html

$x('//article[@class="product_pod"]/h3/a/@title') // trayendo todos los titulos de los libros

$x('//article[@class="product_pod"]/h3/a/@title').map(x => x.value)

$x('//article[@class="product_pod"]/div[@class="product_price"]/p[@class="price_color"]/text()') // tdoos los precios de los libros

$x('//article[@class="product_pod"]/div[@class="product_price"]/p[@class="price_color"]/text()').map(x => x.wholeText)

$x('//div[@class="side_categories"]/ul[@class="nav nav-list"]/li/ul/li/a/text()') // todas las categorias de libros

$x('//div[@class="side_categories"]/ul[@class="nav nav-list"]/li/ul/li/a/text()').map(x => x.wholeText.trim())

// RETO

/*
Extraer descripcion de libros

https://books.toscrape.com/catalogue/sapiens-a-brief-history-of-humankind_996/index.html
*/
$x('//article[@class="product_page"]/p[position()=1]/text()')

$x('//article[@class="product_page"]/p[position()=1]/text()')[0].wholeText


/*
Extraer stock de libros
*/

$x('//table[@class="table table-striped"]/tbody/tr/td/.')[5]

$x('//table[@class="table table-striped"]/tbody/tr[6]/td/text()')[0].wholeText

Para obtener las categorías de libros limpias podemos usar una expresión regular.

$x('//div[@class="side_categories"]/ul[@class="nav nav-list"]/li/ul/li/a/text()').map(i => i.data.replace(/[_\W]+/g, ""))

Descripcion

$x('//article[@class="product_page"]/p/text()').map(x => x.wholeText)

Stock

$x('//article[@class="product_page"]/div[@class="row"]/div[@class="col-sm-6 product_main"]/p[@class="instock availability"]/text()').map(x => x.wholeText.trim())

En el último ejercicio se puede usar $x(’//div[@class=“side_categories”]/ul[@class=“nav nav-list”]/li/ul/li/a/text()’).map(x => x.wholeText.trim()) para tener los textos sin espacios innecesarios.

Estos fueron mis resultados les comparto por si alguien quiere comprar o si talvez lo hicieron de una manera distinta.

Stock Available:

$x('//article[@class = "product_page"]/div[@class = "row"]/div[@class = "col-sm-6 product_main"]/p[@class = "instock availability"]/text()[last()]').map(x => x.wholeText.trim())

Product Description

$x('//article[@class = "product_page"]/p/text()').map(x => x.wholeText)

Como me salio a mi

Para retornar el stock
$x('//p[@class="instock availability"]/text()').map(x => x.wholeText)

Para traer la descripcion

$x('//article[@class="product_page"]/p/text()').map(x => x.wholeText)```

Me gustaría agregar que en el primer ejemplo cuando el toma el título del libro, lo hace con el atributo value, esto lo hace porque lo esta tomando directamente de el atributo title=“título”.

En el segundo caso, como lo toma directamente del texto que está dentro de p, se usa text()

Algo interesante que acabo de notar realizando el reto es que si un elemento tiene 2 clases, como por ejemplo “col-sm-6 product_main”. Es necesario que al extraerlo con Xpath incluyas ambas clases. Con los css selector se puede tomar por solo una de ellas pero en Xpath no.

Para que le salga sin espacion con JS es asi.

$x('//div[@class="side_categories"]/ul/li/ul/li/a/text()').map(x => x.wholeText.trim())

Challenges XPath 🕵️

Extract the description of a book 📑

$x('//article[@class="product_page"]/p/text()').map(x => x.wholeText)

“WICKED above her hipbone, GIRL across her heart Words are like a road map …”

.

Extract stock from a book 📑

$x('//div[@class="col-sm-6 product_main"]/p[@class="instock availability"]/text()[2]').map(x => x.wholeText)


Result= [’\n \n In stock (20 available)\n \n’]

Yo lo hice de la siguiente forma:

$x('//p[@class="instock availability" and contains(., "stock")] | //div[@id="product_description"]/following-sibling::p').map(x=>x.innerText)

Y obtuve un array con los dos datos:

Array [ " In stock (22 available)", "It's hard to imagine a world without A Light in the Attic. This now-classic collection of poetry and drawings from Shel Silverstein celebrates its 20th anniversary with this special edition. Silverstein's humorous and creative verse can amuse the dowdiest of readers. Lemon-faced adults and fidgety kids sit still and read these rhythmic words and laugh and smile and love th It's hard to imagine a world without A Light in the Attic. This now-classic collection of poetry and drawings from Shel Silverstein celebrates its 20th anniversary with this special edition. Silverstein's humorous and creative verse can amuse the dowdiest of readers. Lemon-faced adults and fidgety kids sit still and read these rhythmic words and laugh and smile and love that Silverstein. Need proof of his genius? RockabyeRockabye baby, in the treetopDon't you know a treetopIs no safe place to rock?And who put you up there,And your cradle, too?Baby, I think someone down here'sGot it in for you. Shel, you never sounded so good. ...more" ]

Por cierto, en este caso aproveché el atributo de innerText de los nodos del DOM para obtener la información en un formato más cercano al que se visualiza en la pantalla.

Otra forma de escribirlo:
A mi me han recomendado que siempre intente construir mis XPath Expressions yendo directo a la etiqueta que quiero extraer ya que si cito a toda la ruta que lleva hasta el nodo que quiero, es muy probable que a futuro mi xpath expression no funcione.
¿Por qué?
Suele ocurrir que se hagan adaptaciones en el código y si nuestra expresion es muy extensa, es mayor la probabilidad de verse dañada al corto plazo.

¿Qué opinan ustedes?

Para los que utilizan el “Copy Xpath” de Chrome y tienen problema con los espacios en blanco de los textos, agregar al final el comando .trim

Para las etiquetas por ejemplo:

$x('/html/body/div/div/div/aside/div[2]/ul/li/ul/li/a/text()').map(x => x.wholeText.trim())
  1. Web a scrapear.
  2. Ver el nodo de interés.
  3. Ver en que atributo está.
  4. Saber que debo extraer el nodo padre.
  5. $x(’ Expresión[Predicados]/nodos/nodo_extraer/@atributo’)

Caso empírico

$x('//div/div[@class="page_inner"]/div[@class="content"]/div[2]/article/div[1]/div[last()]/p[2]/text()').map(x => x.wholeText)

Caso Ayuda con el navegador

$x('//*[@id="content_inner"]/article/div[1]/div[2]/p[2]/text()').map(x => x.wholeText)

el resultado es el mismo

Scraping https://books.toscrape.com/catalogue/set-me-free_988/index.html

$x('//div[@class = "content"]/div[@id = "content_inner"]/article[@class = "product_page"]/p/text()').map(x => x.wholeText)```



$x(’//div[@class = “content”]/div[@id = “content_inner”]/article[@class = “product_page”]/div[@class = “row”]/div[@class = “col-sm-6 product_main”]/p[@class = “instock availability”]/text()’).map(x => x.wholeText)```

una opcion corta para los titulos puede ser esta

//a[@title]/@title

Los Xpath de la descripción y el stock

$x('//article[@class="product_page"]/p/text()').map(x => x.wholeText)

$x('//table[@class="table table-striped"]/tbody/tr[6]/td/text()').map(x => x.wholeText)
$x('//article[@class="product_page"]/p/text()').map(x=>x.wholeText)
["It's hard to imagine a world without A Light in th…for you. Shel, you never sounded so good. ...more"]0: "It's hard to imagine a world without A Light in the Attic. This now-classic collection of poetry and drawings from Shel Silverstein celebrates its 20th anniversary with this special edition. Silverstein's humorous and creative verse can amuse the dowdiest of readers. Lemon-faced adults and fidgety kids sit still and read these rhythmic words and laugh and smile and love th It's hard to imagine a world without A Light in the Attic. This now-classic collection of poetry and drawings from Shel Silverstein celebrates its 20th anniversary with this special edition. Silverstein's humorous and creative verse can amuse the dowdiest of readers. Lemon-faced adults and fidgety kids sit still and read these rhythmic words and laugh and smile and love that Silverstein. Need proof of his genius? RockabyeRockabye baby, in the treetopDon't you know a treetopIs no safe place to rock?And who put you up there,And your cradle, too?Baby, I think someone down here'sGot it in for you. Shel, you never sounded so good. ...more"length: 1__proto__: Array(0)
$x('//table[@class="table table-striped"]/tbody/tr/td[starts-with(.,"In")]/text()').map(x=>x.wholeText)
["In stock (22 available)"]
# Stock
$x('//table[@class="table table-striped"]/tbody/tr[contains (., "Availability")]/td/text()').map(x => x.wholeText)

R/: ["In stock (22 available)"]

# Descripcion
$x('//meta[@name="description"]/@content').map(x => x.value)

R/: ["↵    It's hard to imagine a world without A Light …or you. Shel, you never sounded so good. ...more↵"]

Practica:
Para obtener el titulo es con:

$x('//h3/a/text()').map(x=>x.wholeText)```
Para obtener el precio es con:


$x(’//p[@class=“price_color”]/text()’).map(x=>x.wholeText)


Para obtener la descripción es con:


$x(’//article[@class=“product_page”]/p/text()’).map(x=>x.wholeText)

Para obtener el Stock es con:


$x(’//p[@class=“instock availability”]/text()’).map(x=>x.wholeText)


$x (’//div[@id=“content_inner”]/article[@class=“product_page”]/p/text()’).map(x => x.wholeText)
["“Erotic and absorbing…Written with starling powe…on to each other and their affair begins. …more”]0: "“Erotic and absorbing…Written with starling power.”–"The New York Times Book Review " Nan King, an oyster girl, is captivated by the music hall phenomenon Kitty Butler, a male impersonator extraordinaire treading the boards in Canterbury. Through a friend at the box office, Nan manages to visit all her shows and finally meet her heroine. Soon after, she becomes Kitty’s “Erotic and absorbing…Written with starling power.”–"The New York Times Book Review " Nan King, an oyster girl, is captivated by the music hall phenomenon Kitty Butler, a male impersonator extraordinaire treading the boards in Canterbury. Through a friend at the box office, Nan manages to visit all her shows and finally meet her heroine. Soon after, she becomes Kitty’s dresser and the two head for the bright lights of Leicester Square where they begin a glittering career as music-hall stars in an all-singing and dancing double act. At the same time, behind closed doors, they admit their attraction to each other and their affair begins. …more"length: 1__proto__: Array(0)
$x (’//div[@id=“content_inner”]/article[@class=“product_page”]/div[@class=“row”]/div[@class=“col-sm-6 product_main”]/p[@class=“instock availability”]/text()’).map(x => x.wholeText)
(2) ["↵ ", “↵ ↵ In stock (20 available)↵ ↵”]0: "↵ "1: "↵ ↵ In stock (20 available)↵ ↵"length: 2__proto__: Array(0)

<code>

Obtener nombre de los productos

$x('//article/h3/a[@title]/text()').map(x => x.data)

La gran lección es que es mejor trabajar con dos pantallas !

Para la descripción utilicé following-sibling para traer nodos hermanos

$x('//div[@id="product_description"]/following-sibling::p/text()')

Para la descripción del libro:

Para el stock:

$x("//table[@class= 'table table-striped']//tr/td[starts-with(.,'I')]/text()").map(x => x.wholeText)

les comparto mi codigo.
me esforcé mucho por aplicar lo aprendido en la clase.
dale que puedes, no te desanimes.
si ves que es un poco complicado, leelo lentamente y compara algo con lo tuyo.
al final, NO hay una sola forma de extraer la informacion, y cada quien eligue como hacerlo segun experiencia y comodidad.
dale.

Solución del reto.

  • Extraer la descripción de un libro: $x(’//article[@class=“product_page”]/p/text()’)

  • Extraer el stock disponible de un libro: $x(’//article[@class=“product_page”]/div[@class=“row”]/div[@class=“col-sm-6 product_main”]/p[@class=“instock availability”]/text()[2]’)

$x('//article/p/text()').map(x => x.wholeText)
$x('//table/tbody/tr/td[contains (., "stock")]/text()').map(x => x.wholeText)


Así me quedó

Stock:

$x(’//p[@class=“instock availability”]/text()’).map (x => x.wholeText)

Description:

$x(’//article[@class=“product_page”]/p/text()’).map (x => x.wholeText)

Disponible
$x(’//article[@class=“product_page”]/table[@class=“table table-striped”]/tbody/tr[6]/td/text()’).map(x=>x.wholeText)

dentro del libro para sacar el stock disponible seria

x('//*[@id="content_inner"]/article/div[1]/div[2]/p[2]/text()')
  .map(x => x.wholeText.trim())
  .filter(x => x.includes('In stock (20 available)'));

y para sacar la descripcion seria

$x('//*[@id="content_inner"]/article/p/text()').map(x => x.wholeText)

Mi solucion al reto:

[
    $x('//article[@class="product_page"]/p/text()').map(x => x.wholeText.trim())[0],
    parseInt($x('//div[@class="row"]//p[@class="instock availability"]/text()[2]').map(x => x.wholeText.trim())[0].match(/\d+/)[0])
]

Devuelve un array donde el primer elemento es la descripcion y el segundo es la cantidad disponible. Para este último use expresiones regulares para obrtener el numero y luego castearlo a int.

Les comparto el código del reto.

$x('//div[@class="container-fluid page"]/div[@class="page_inner"]/div[@class="content"]/div[@id="content_inner"]/article[@class="product_page"]/div[@class="row"]/div[@class="col-sm-6 product_main"]/p[@class="instock availability"]/text()[2]').map(x => x.wholeText)

Toca ir practicando, asi se va aprendiendo mejor!

si conocemos algo de JavaScript podemos utilizar la expresion innerHTML para extraer lo que está dentro de la etiquita seleccionada, así evitamos tener que traer el text() ojo esto es solo JS aquí un ejemplo

$x(’//article[@class=“product_pod”]/div[@class=“product_price”]/p[1]’).map(x=>x.innerHTML)

Expresión para traer la descripción del libro Tipping the Velvet:

$x('//article[@class="product_page"]/p/text()').map(x => x.wholeText)

Expresión para obtener el stock:

$x('//article[@class="product_page"]/div[@class="row"]/div[@class="col-sm-6 product_main"]/p[@class="instock availability"]/text()').map(x => x.wholeText)

Tambien podemos quitar los

espacios directamente en javascript, dentro de la funcion de map solo agregen “.trim()” despues de wholeText

map(texto => texto.wholeText.trim())

De esta forma nos quedan los nombres de las categorias limpias

$x('//p[@class="instock availability"]/text()').map(x=>x.wholeText)
(2) ['\n    ', '\n    \n        In stock (22 available)\n    \n']

Doy mis aportes hoy 23 Febrero de 2023, este codigo funciona:

import requests 
import lxml.html as html 
import os
import datetime


HOME_URL= 'https://www.larepublica.co/'
XPATH_LINK_TO_ARTICLE= '//text-fill[not(@class)]/a/@href'
XPATH_TITLE = '//div[@class="mb-auto"]//span/text()'
XPATH_SUMMARY='//div[@class="lead"]/p/text()'
XPATH_BODY='//div[@class="html-content"]/p/text()'


def parse_notice(link, today):
    try:
        response = requests.get(link)
        if response.status_code == 200:
            notice = response.content.decode('utf-8')
            parsed = html.fromstring(notice)

            try:
                title = parsed.xpath(XPATH_TITLE)[0]
                title = title.replace('\"','')
                summary = parsed.xpath(XPATH_SUMMARY)[0]
                body = parsed.xpath(XPATH_BODY)
            except IndexError:
                return

            with open(f'{today}/{title}.txt','w',encoding='utf-8') as f:
            #with open('{}/{}.txt'.format(today,title), 'w',encoding='utf-8') as f:
                f.write(title)    
                f.write('\n\n')
                f.write(summary)
                f.write('\n\n')
                for p in body:
                    f.write(p)
                    f.write('\n')
        else:
            raise ValueError(response.status_code)
    except ValueError as ve:
        print(ve)


def parse_home():
    try:
        response = requests.get(HOME_URL)
        if response.status_code == 200:
            home = response.content.decode('utf-8')
            parsed= html.fromstring(home)
            links_to_notices = parsed.xpath(XPATH_LINK_TO_ARTICLE)
            #print(links_to_notices)

            today = datetime.date.today().strftime('%d-%m-%Y')
            if not os.path.isdir(today):
                os.mkdir(today)

                for link in links_to_notices:
                    parse_notice(link, today)


        else:
            raise ValueError(f'ERROR: {response.status_code}')
    except ValueError as ve:
        print(ve)
      
def run():
    parse_home()

if __name__ =='__main__':
    run()

El libro que seleccione fue:
It’s Only the Himalayas
para extraer la descripción del producto:

$x('//article[@class = "product_page" ]/p/text()').map(x => x.wholeText)

para extraer el stock:

$x('//div[@class = "col-sm-6 product_main"]/p[@class="instock availability"]/text()').map(x => x.wholeText)

Mi solución fue

$x('//h3/a/text()').map(x => x.wholeText)

La manera en que se puede solucionar el ejercicio puede ser muy variada dado que se puede recorrer las diferentes etiquetas (para mayor comprensión) o ir directo.

Mi solución fue:

  • Descripción del libro
    $x(’//article[@class=“product_page”]/p/text()’).map(x=>x.wholeText)
  • Cantidades en stock
    $x(’//table[@class=“table table-striped”]/tbody/tr[6]/td/text()’).map(x=>x.wholeText)

Adjunto mi aporte al reto planteado:

<Descripcion de pelicula (Escogi la primera 'A Light in the Attic')>

$x('//div/article[@class = "product_page"]/p/text()').map(x => x.wholeText)

<Stock Disponible>

$x('//div/article[@class = "product_page"]/table[@class = "table table-striped"]/tbody/tr/td/text()').map(x => x.wholeText)[5].slice(10, -1)

Descripcion

$x('//article[@class = "product_page"]/p/text()').map(x => x.wholeText)

stock

$x('//div[@class = "col-sm-6 product_main"]/p[@class = "instock availability"]/text()').map(x => x.wholeText)

https://books.toscrape.com/catalogue/sharp-objects_997/index.html

// Descripcion del Libro
$x(’//article[@class=“product_page”]/p[position()=1]/text()’)[0].wholeText

// Stock de Libro
$x(’//table[@class=“table table-striped”]/tbody/tr[6]/td/text()’)[0].wholeText

descripción del producto
//div[@class=“content”]/div[2]/article[@class=“product_page”]//h2/font/font/text()
//[@id=“content_inner”]/article/p/font/font[1]
en stock:
//
[@id=“content_inner”]/article/table/tbody/tr[6]/td/font/font

Estas son mis soluciones. No busque optimizar sino comprender el mecanismo.

Obtener titulo:

$x(’//article[@class= “product_page”]/div/div/h1/text()’).map(x => x.wholeText)

O

$x(’//div[@class= “col-sm-6 product_main”]/h1/text()’).map(x => x.wholeText)

Obtener Precio

$x(’//div[@class= “col-sm-6 product_main”]/p[1]/text()’).map(x => x.wholeText)

Obtener Stock

$x(’//div[@class= “col-sm-6 product_main”]/p[2]/text()’).map(x => x.wholeText)

Obtener Descripción

$x(’//article[@class= “product_page”]/p/text()’).map(x => x.wholeText)

Solucion del reto:

Con este extraemos la sinapsis del libro:

$x('//article[@class="product_page"]/p/text()').map(x => x.wholeText)

Con este extraemos el stock del libro:

$x('//table[@class="table table-striped"]/tbody/tr/td[contains(.,"In stock")]/text()').map(x => x.wholeText)

Ejercicio:

Descripcion:

$x('//article[@class="product_page"]/p/text()')[0]

Stock:

$x('//article[@class="product_page"]/div[@class="row"]//p[@class="instock availability"]/text()')[1].wholeText.trim()

Aquí mi solución:
$x('//article[@class="product_page"]/p/text()').map(x => x.wholeText) - Descripción

$x('//table[@class="table table-striped"]/tbody/tr[6]/td/text()').map(x => x.wholeText) - Stock

$x(’//h1/text()’).map(x=>x.wholeText)
[‘A Light in the Attic’]

$x(’//p[@class=“instock availability”]/text()’).map(x=>x.wholeText)
 [’\n ', ‘\n \n In stock (22 available)\n \n’]

$x(’//div[@class=“side_categories”]//a/text()’).map(x=>x.wholeText)

Noto que para hacer buenas extracciones de una pagina en especifica también depende mucho de que la estructura HTML tenga buena practica y una buena organización de sus etiquetas.

Descripcion

$x('//article[@class="product_page"]/p/text()').map(x => x.wholeText)

Stock
$x(’//p[@class=“instock availability”]/text()’).map(x => x.wholeText)

<code> 

Después de ver las soluciones de los demás me doy cuenta que podría haberlo hecho mucho mas corto xD
$x(’//div[@class=“container-fluid page”]/div[@class=“page_inner”]/div[@class=“content”]/div[@id=“content_inner”]/article[@class=“product_page”]/p/text()’).map(x => x.wholeText)

Gracias al aporte del compañero Oscar, me di cuenta que se reduce significativamente el tamaño de la expresión. Creo que la descripción todos lo resolvimos fácil, pero dense cuenta del stock

$x('//*[@id="content_inner"]/article/div[1]/div[2]/p[2]/text()[2]').map(x => x.wholeText.trim())

Descripción del libro

$x('//article[@class="product_page"]/p/text()').map(x => x.wholeText)

Stock disponible

$x('//article[@class="product_page"]//tr[last()-1]/td/text()').map(x => x.wholeText)

Reto

Página: Producto de Amazón

  • Trayendo descripción una página web, ejemplo: Amazón
$x('//div[@id="dp"]/div[@id="dp-container"]/div[@id="ppd"]/div[4]/div[@id="productOverview_feature_div"]/div[@class="a-section a-spacing-small a-spacing-top-small"]//text()').map(x => x.wholeText) 
  • Trayendo la cantidad del stock
 $x('//div[@id="dp"]/div[@id="dp-container"]/div[@id="ppd"]/div/div[4]/div/div/div/div/form/div/div/div/div/div[3]/div/div[9]/div/div/span/div/div/span/span/span/span/span/text()').map(x => x.wholeText) 

Hola ✌🏽, estas son las expresiones que me salieron

Expresión para sacar la descripción

$x('//div[@id="content_inner"]/article[@class="product_page"]/p/text()').map(x => x.wholeText)

Expresión para extraer el número en Stock

$x('//div[@id="content_inner"]/article[@class="product_page"]/div[@class="row"]/div[@class="col-sm-6 product_main"]/p[@class="instock availability"]/text()').map(x => x.wholeText)

Las expresiones del Reto me salieron así:

// Para la Descripción
$x('//article[@class="product_page"]/p/text()').map(x => x.wholeText)
['"Erotic and absorbing...Written with starling poweon to each other and their affair begins. ...more']


// Para el stock disponible
$x('//div[@class="row"]//p[@class="instock availability"]/text()').map(x => x.wholeText)
(2['\n    ', '\n    \n        In stock (20 available)\n    \n']

Aquí les comparto el código que utilicé:

#Este es el código que utilicé para sacar la descripción.
$x('//article[@class="product_page"]/p/text()').map(x => x.wholeText)

#Este es el código que utilicé para sacar el stock
$x('//article[@class="product_page"]/div/div[@class="col-sm-6 product_main"]/p[@class="instock availability"]/text()').map(x => x.wholeText)

//description
$x(’//article[@class=“product_page”]/p/text()’).map(e=>e.wholeText)
//stock
$x(’//div[@class=“col-sm-6 product_main”]/p[@class=“instock availability”]/text()[2]’).map(e=>e.wholeText.trim())

Para el stock:

$x(’//article[@class=“product_page”]//p[@class=“instock availability”]/text()’).map(x=>x.wholeText)

Para la descripción del libro:

$x(’//article[@class=“product_page”]/p/text()’).map(x=>x.wholeText)

Stock

$x('//div[@class = "col-sm-6 product_main"]/p[@class = "instock availability"]/text()').map(x => x.wholeText)

Descripción

$x('//article[@class="product_page"]/p/text()').map(x => x.wholeText)

buenos dias, aqui dejando mi aporte al desafio:
descripción:

$x('//article[@class="product_page"]/p/text()').map(x => x.wholeText)

stock:

$x('//div[@class="col-sm-6 product_main"]/p[@class="instock availability"]/text()[2]').map(x => x.wholeText)

Mi aporte.

Stock:

$x('//article[@class="product_page"]/div[@class="row"]/div[@class="col-sm-6 product_main"]/p[@class="instock availability"]/font//text()[last()]').map(x => x.wholeText.trim())

Descripción:

$x('//*[@id="content_inner"]/article/p//font/text()').map(x => x.wholeText)
// Mostrar la lista de categorias sin los espacios en blanco y sin el caracter "\n" 
$x('//div[@class="side_categories"]/ul[@class="nav nav-list"]/li/ul/li/a').map(x => x.innerText)

Reto:

//Obtener descripcion del producto
$x('//article[@class="product_page"]//div[@class="col-sm-6 product_main"]/h1')[0].innerText

//Obtener el precio del producto
$x('//article[@class="product_page"]//div[@class="col-sm-6 product_main"]/p[@class="price_color"]')[0].innerText

Me divertí mucho en esta clase.

Los retos no están muy complicado, tomate tus minutos para resolverlos:

$x(’//article[@class=“product_page”]/p/text()’).map(x =>x.wholeText)

$x(’//table[@class=“table table-striped”]/tbody/tr[6]/td/text()’).map(x => x.wholeText)

Aqué comparto mis Xpath
Descripción del libro:
$x(’//article[@class=“product_page”]/p/text()’).map(x => x.wholeText)

Stock disponible:
$x(’//article[@class=“product_page”]/div[@class=“row”]/div[@class=“col-sm-6 product_main”]/p[@class=“instock availability”][1]/text()’).map(x => x.wholeText)

Reto:
Descripción

$x('//div[@id="content_inner"]/*/p/node()').map(x => x.wholeText)

Stock

$x('//div[@id="content_inner"]/*/table[@class="table table-striped"]/*/tr[6]/td/node()').map(x => x.wholeText)
  • Description
$x('//*[@id="content_inner"]/article/p/text()').map( x => x.wholeText)

$x('//*[@id="content_inner"]/article/p/text()').map( x => x.wholeText)

  • Price
$x('//*[@id="content_inner"]/article/div[1]/div[2]/p[1]/text()').map(x => x.wholeText)


$x('//div[@class="col-sm-6 product_main"]/p[@class="price_color"]/text()').map(x => x.wholeText)

Existe un complemento para Chrome que ayuda a obtener la ruta de cualquier HTML con un solo click!

https://chrome.google.com/webstore/detail/xpath-helper/hgimnogjllphhhkhlmebbmlgjoejdpjl/related

$x('//article[@class = "product_page"]/p/text()').map(x=>x.wholeText)

“It’s hard to imagine a world without A Light in the Attic. This now-classic collection of poetry and drawings from Shel Silverstein celebrates its 20th anniversary with this special edition. Silverstein’s humorous and creative verse can amuse the dowdiest of readers. Lemon-faced adults and fidgety kids sit still and read these rhythmic words and laugh and smile and love th It’s hard to imagine a world without A Light in the Attic. This now-classic collection of poetry and drawings from Shel Silverstein celebrates its 20th anniversary with this special edition. Silverstein’s humorous and creative verse can amuse the dowdiest of readers. Lemon-faced adults and fidgety kids sit still and read these rhythmic words and laugh and smile and love that Silverstein. Need proof of his genius? RockabyeRockabye baby, in the treetopDon’t you know a treetopIs no safe place to rock?And who put you up there,And your cradle, too?Baby, I think someone down here’sGot it in for you. Shel, you never sounded so good. …more”

$x('//article[@class = "product_page"]/table[@class = "table table-striped"]/tbody/tr/td[contains(.,"In stock")]/text()').map(x=>x.wholeText)

In stock (22 available)

(21) [’¿Qué es el web scraping?’, ‘¿Por qué aprender web scraping hoy?’, ‘Python: el lenguaje más poderoso para extraer datos’, ‘Entender HTTP’, ‘¿Qué es HTML?’, ‘Robots.txt: permisos y consideraciones al hacer web scraping’, ‘XML Path Language’, ‘Tipos de nodos en XPath’, ‘Expresiones en XPath’, ‘Predicados en Xpath’, ‘Operadores en Xpath’, ‘Wildcards en Xpath’, ‘In-text search en Xpath’, ‘XPath Axes’, ‘Resumen de XPath’, ‘Aplicando lo aprendido’, ‘Un proyecto para tu portafolio: scraper de noticias’, ‘Construcción de las expresiones de XPath’, ‘Obteniendo los links de los artículos con Python’, ‘Guardando las noticias en archivos de texto’, ‘Cómo continuar tu ruta de aprendizaje’]

$x('//div[@class = "Syllabus-class-container-text"]/p/text()').map(x=>x.wholeText)

Para el stock

<$x('//article[@class="product_page"]/table[@class="table table-striped"]/tbody/tr/td[contains(., "stock")]/text()').map(x => x.wholeText)
['In stock (22 available)']> 

Para la descripcion

<$x('//article[@class="product_page"]/p/text()').map(x=> x.wholeText)> 

descripción sin espacios

$x('//article/h3/a/text()').map(x => x.data.replace(/[_\W]+/g,""))

Descripcion del libro A Light in the Attic:
$x(’//*[@id=“content_inner”]/article/p/text()’).map(x=>x.wholeText)

Stock:
$x(’//*[@id=“content_inner”]/article/div[1]/div[2]/p[2]/text()’).map(x=>x.wholeText)

  • Descripción del producto:
$x('//article/p/text()').map(x => x.wholeText)
  • Stock disponible:
$x('//article/table[@class="table table-striped"]//tr//td[contains(.,"In")]/text()').map(x => x.wholeText)

Ejemplo resumido para obtener las categorías:

$x('//a[@href[contains(.,"/category/books/")]]/text()')

Resumi un ejemplo para obtener los precios:

$x('//*/text()[contains(.,"£")]').map(x=>x.wholeText)

Descripción:

$x('//div[@class="content"]//article[@class="product_page"]/p/text()').map(x => x.wholeText)
["It's hard to imagine a world without A Light in thfor you. Shel, you never sounded so good. ...more"]

Stock:

$x('//div[@class="content"]//article[@class="product_page"]/div/div[@class="col-sm-6 product_main"]/p[@class="instock availability"]/text()[2]').map(x => x.wholeText.trim())
['In stock (22 available)']

Hola, comparto una alternativa al código del profe:

$x('//article[@class="product_pod"]/div/p[@class="price_color"]/node()').map(x => x.wholeText)

Para hallar el stock se puede hacer así:

$x(’//tbody/tr[last()-1]/td/text()’).map(x => x.wholeText)

$x('//article[@class="product_page"]/p/text() | //p[@class="instock availability"]/text() ').map(x=>x.wholeText)
  • Descripción :
$x('//article[@class="product_page"]/p/text()').map(x => x.wholeText)

  • En Stock :
$x('//article[@class="product_page"]/div[@class="row"]/div[@class="col-sm-6 product_main"]/p[@class="instock availability"]/text()').map(x => x.wholeText)

El primero fue mas facil

$x('//article[@class="product_page"]/p/text()').map(x=>x.nodeValue)

El segundo me costo mas 😕

$x('//article[@class="product_page"]/div[@class="row"]/div[@class="col-sm-6 product_main"]/p[@class="instock availability"]/text()[last()]').map(x=>x.nodeValue)

Stock:

$x('//p[@class="instock availability"]/text()[2]').map(x => x.wholeText.trim())

Description:

$x('//article[@class="product_page"]/p/text()').map(x => x.wholeText())

Para sacar las unidades disponibles:

$x('//div[@class="col-sm-6 product_main"]/p[@class="instock availability"]/node()').map(x => x.wholeText)

Y para sacar la descripción:

$x('//article[@class="product_page"]/p/text()').map(x => x.wholeText)

Desafíos

Reto
Disponibilidad:

$x('//article[@class="product_page"]/table[@class="table table-striped"]/tbody/tr[6]/td/text()').map(x => x.wholeText)

Descripcion:

$x('//article[@class="product_page"]/p/text()').map(x => x.wholeText)