XPath es una sintaxis que se usa para recorrer los elementos
de un documento XML
Mediante estos comandos podemos obtener cualquier nodo del
árbol de elementos.
http://www.freeformatter.com/xpath-tester.html
e introduciremos el siguiente XML:
<libro> <titulo>Libro 1</titulo> <autor>Autor 1</autor> <capitulo num="1"> Capitulo1 <parrafo> Texto 1.1 </parrafo> <parrafo destacar="si"> Texto 1.2 <enlace href="enlace">Enlace 1</enlace> Texto 1.3 </parrafo> </capitulo> <capitulo num="2" public="si" > Capitulo 2 <parrafo> Texto 2.1 </parrafo> <parrafo> Texto 2.2 <enlace href="enlace">Enlace 2</enlace> Texto 2.3 </parrafo> </capitulo> <apendice num="a" public="si"> Apéndice 1 <parrafo> Texto 3.1 </parrafo> <parrafo> Texto 3.2 <enlace href="enlace">Enlace 3</enlace> Texto 3.3 </parrafo> </apendice> </libro>
Sintaxis | Significado | Resultado |
/libro
| Seleccionaremos el elemento raíz de la estructura de elementos o nodos, y todos los nodos que cuelgan de ella | <libro> <titulo>Libro 1</titulo> <autor>Autor 1</autor> <capitulo num="1"> Capitulo1 <parrafo>Texto 1.1</parrafo> <parrafo destacar="si"> … |
/libro/capitulo | Devuelve todos los capítulos que cuelgan de Libro | <capitulo
num="1"> Capitulo1 <parrafo>Texto 1.1</parrafo> <parrafo destacar="si"> ... <capitulo num="2" public="si"> Capitulo 2 <parrafo>Texto 2.1</parrafo> … |
/libro/capitulo[2] | Devuelve el 2º capítulo de Libro | <capitulo
num="2" public="si"> Capitulo 2 <parrafo>Texto 2.1</parrafo> <parrafo> Texto 2.2 <enlace href="enlace">Enlace 2</enlace> Texto 2.3 </parrafo> </capitulo> |
//parrafo | Devuelve todos los párrafos, estén donde estén en el documento. | <parrafo>Texto
1.1</parrafo> <parrafo destacar="si"> Texto 1.2 <enlace href="enlace">Enlace 1</enlace> Texto 1.3 </parrafo> <parrafo>Texto 2.1</parrafo> <parrafo> Texto 2.2 <enlace href="enlace">Enlace 2</enlace> Texto 2.3 </parrafo> <parrafo>Texto 3.1</parrafo> <parrafo> Texto 3.2 <enlace href="enlace">Enlace 3</enlace> Texto 3.3 </parrafo> |
//parrafo/@destacar | Para un elemento párrafo que contenga el atributo “destacar”, devuelve el valor de el atributro “Destacar “ | destacar="si" |
//parrafo[@destacar] | Devuelve el párrafo que contenga un atributo “destacar”, da igual su valor | <parrafo
destacar="si"> Texto 1.2 <enlace href="enlace">Enlace 1</enlace> Texto 1.3 </parrafo> |
//parrafo[@destacar=”si”] | Devuelve el párrafo que contenga un atributo “destacar” con valor “si” | <parrafo
destacar="si"> Texto 1.2 <enlace href="enlace">Enlace 1</enlace> Texto 1.3 </parrafo> |
//capitulo[@num>=2] | Devuelve el capítulo cuyo numero sea mayor o igual que 2 | <capitulo
num="2" public="si"> Capitulo 2 <parrafo>Texto 2.1</parrafo> <parrafo> Texto 2.2 <enlace href="enlace">Enlace 2</enlace> Texto 2.3 </parrafo> </capitulo> |
//capitulo//enlace | Devuelve todos los enlaces que cuelguen de capítulos | <enlace
href="enlace">Enlace 1</enlace> <enlace href="enlace">Enlace 2</enlace> |
//capitulo[last()] | Devuelve el útlimo capítulo | <capitulo
num="2" public="si"> Capitulo 2 <parrafo>Texto 2.1</parrafo> <parrafo> Texto 2.2 <enlace href="enlace">Enlace 2</enlace> Texto 2.3 </parrafo> </capitulo> |
//capitulo[2]/text() | Devuelve el texto que hay en el capítulo 2 | Capitulo 2 |
//capitulo[position()>1] | Devuelve los capítulos a partir de la posición 2 | <capitulo
num="2" public="si"> Capitulo 2 <parrafo>Texto 2.1</parrafo> <parrafo> Texto 2.2 <enlace href="enlace">Enlace 2</enlace> Texto 2.3 </parrafo> </capitulo> |
//enlace[contains(text(),'Enlace 2')] /ancestor::capitulo | Devuelve el capítulo donde haya un enlace con valor "Enlace 3" | <capitulo
num="2" public="si"> Capitulo 2 <parrafo>Texto 2.1</parrafo> <parrafo> Texto 2.2 <enlace href="enlace">Enlace 2</enlace> Texto 2.3 </parrafo> </capitulo> |
//parrafo[contains(text(),"Texto 1.1")] /ancestor::capitulo /following-sibling::capitulo //enlace/text() | (leyendo
de derecha a izquierda) Devuelveme el texto del enlace del capítulo siguiente al capítulo donde haya un parrafo que contenga "Texto 1.1" (leyendo de izquierda a derecha) Localízame a un parrafo cuyo texto contiene "Texto 1.1", navega cualquier antepasado (padre, abuelo, etc) que sea de tipo capítulo, vete al siguiente capítulo y me devuelves el texto de todos los enlaces | Enlace 2 |
ENLACES
Podéis ampliar más información en:
- http://www.w3.org/TR/xpath Especificación del XPath
- http://www.w3schools.com/xml/xpath_intro.asp
- https://msdn.microsoft.com/en-us/library/ms256471(v=vs.110).aspx
- http://saxon.sourceforge.net/saxon6.5.3/expressions.html
Tipos de descarga de html
El HTML, al estar basado en XML, también se le puede aplicar XPath.
Antes de meternos en materia, voy a explicar un poco cómo nos llegan los datos de las páginas web.
Por HTML:
El navegador envía una petición al servidor, y en la respuesta, se devuelve HTML con los datos que queremos sacar. Este método no representa problema alguno y lo podemos atacar con XPath.
Por JavaScript:
El navegador envía una petición al servidor, y el servidor devuelve una plantilla HTML con JavaScript, y el navegador al interpretarlo, llama a unas apis que devuelven los datos, y rellenan la plantilla con los datos traídos en la segunda parte. (p.e, morningstar, finance.yahoo.com).
Este método se está poniendo de moda ya que hace algo más complicado extraer los datos, y por otra parte usa tecnologías más recientes (Ajax, Angular) que hace que la página se cargue sin postbacks.
Si estamos intentando traernos HTML por métodos que no tengan navegador (tipo funciones GSheets ImportXML, ImportHTML, HttpWebRequest en .Net ) nos traerá la plantilla HTML y los scripts JavaScript, pero estas funciones no procesan el JavaScript, por lo que no podemos obtener datos mediante este método.
Para extraer datos de este tipo de página, hay que analizar cómo se descarga los datos (con Fiddler se puede ver las llamadas que hace la web), interpretando su API, etc.
En el caso de Morningstar.com, podríamos sacar la información mediante el botón de exportar CSV
También en esta dirección hay más información de algunas llamadas a la API de Morningstar
El HTML, al estar basado en XML, también se le puede aplicar XPath.
Antes de meternos en materia, voy a explicar un poco cómo nos llegan los datos de las páginas web.
Por HTML:
El navegador envía una petición al servidor, y en la respuesta, se devuelve HTML con los datos que queremos sacar. Este método no representa problema alguno y lo podemos atacar con XPath.
Por JavaScript:
El navegador envía una petición al servidor, y el servidor devuelve una plantilla HTML con JavaScript, y el navegador al interpretarlo, llama a unas apis que devuelven los datos, y rellenan la plantilla con los datos traídos en la segunda parte. (p.e, morningstar, finance.yahoo.com).
Este método se está poniendo de moda ya que hace algo más complicado extraer los datos, y por otra parte usa tecnologías más recientes (Ajax, Angular) que hace que la página se cargue sin postbacks.
Si estamos intentando traernos HTML por métodos que no tengan navegador (tipo funciones GSheets ImportXML, ImportHTML, HttpWebRequest en .Net ) nos traerá la plantilla HTML y los scripts JavaScript, pero estas funciones no procesan el JavaScript, por lo que no podemos obtener datos mediante este método.
Para extraer datos de este tipo de página, hay que analizar cómo se descarga los datos (con Fiddler se puede ver las llamadas que hace la web), interpretando su API, etc.
En el caso de Morningstar.com, podríamos sacar la información mediante el botón de exportar CSV
También en esta dirección hay más información de algunas llamadas a la API de Morningstar
Ejemplo de construcción y uso de XPath
Vamos a extraer información financiera de las páginas de InvertirEnBolsa.info para rellenar un Google Spreadsheet.
Recordamos que GSheets posee funciones financieras propias para sacar cotizaciones, volúmenes, PER, BPA, etc)
Para crear la ruta XPath de un elemento, por ejemplo el EBITDA del 2015 de Coca-Cola:
Abrimos con chrome la página de CocaCola en IeB
http://www.invertirenbolsa.info/historicodividendos/empresa/coca-cola
Pulsamos F12 en chrome para que se nos abran las tools developer.
Con la pestaña "elements" seleccionada(1), pulsamos "seleccionar elemento"(2) y seleccionamos el elemento que queremos obtener(3), y así puedes ver el elemento HTML que queremos seleccionar(4).
En este caso, vemos que con buscar el siguiente elemento TD al TD que su texto sea "EBITDA". Fácil, no?
El Xpath sería:
Localízame un elemento TD cuyo texto sea 'EBITDA', te vas al 1er siguiente hermano.
//td[text()='EBITDA']/following-sibling::td[1]
La fórmula en el GSheets a usar sería:
=IMPORTXML("http://www.invertirenbolsa.info/historicodividendos/empresa/coca-cola"; "//td[text()='EBITDA']/following-sibling::td[1]")
El resultado es
1,58%
10.698,00
Este resultado devuelve 2 datos ya que nos está cogiendo el % ebitda que hay en otra tabla.
Para centrar bien el resultado, tenemos que afinar más la búsqueda, añadiendo la tabla a la que pertenece el elemento.
Para ello, subimos hacia arriba para ver la tabla de la que cuelga el TD, y vemos que es descendiente de un table cuya class contiene "cuarta tabla".
El XPath correcto sería:
Localízame una tabla cuyo atributo class contiene 'cuarta-tabla', y dentro de sus elemento, busca un elemento TD cuyo texto sea 'EBITDA', y me devuelves el 1er siguiente hermano.
//table[contains(@class,'cuarta-tabla')]//td[text()='EBITDA']/following-sibling::td[1]
La fórmula en el GSheets a usar sería:
=IMPORTXML("http://www.invertirenbolsa.info/historicodividendos/empresa/coca-cola"; "//table[contains(@class,'cuarta-tabla')]//td[text()='EBITDA']/following-sibling::td[1]")
El resultado es
10.698,00
Esta es una forma de componer una expresión XPath mirando directamente el HTML. Tienes más control al comprender de dónde estás cogiendo el dato, incluso modificar el xpath dinámicamente de teniendo en cuenta el año, el ticker, etc.
Otra alternativa es, al seleccionar el elemento a rescatar, con botón derecho, copiar Xpath.
Esta forma no me acaba de convencer, ya que en el momento que cambien el orden o metan algún campo más, es mayor el riesgo de que no muestre el resultado correcto.
El resultado mediante este método es
//*[@id="gkMainbody"]/div/div[3]/div/div[2]/div[3]/table/tbody/tr[7]/td[2]
También hay plugins de chrome para generar automáticamente la ruta XPath, como XPath Helper
Espero que os sea de utilidad.
Saludos.
Recordamos que GSheets posee funciones financieras propias para sacar cotizaciones, volúmenes, PER, BPA, etc)
Para crear la ruta XPath de un elemento, por ejemplo el EBITDA del 2015 de Coca-Cola:
Abrimos con chrome la página de CocaCola en IeB
http://www.invertirenbolsa.info/historicodividendos/empresa/coca-cola
Pulsamos F12 en chrome para que se nos abran las tools developer.
Con la pestaña "elements" seleccionada(1), pulsamos "seleccionar elemento"(2) y seleccionamos el elemento que queremos obtener(3), y así puedes ver el elemento HTML que queremos seleccionar(4).
En este caso, vemos que con buscar el siguiente elemento TD al TD que su texto sea "EBITDA". Fácil, no?
El Xpath sería:
Localízame un elemento TD cuyo texto sea 'EBITDA', te vas al 1er siguiente hermano.
//td[text()='EBITDA']/following-sibling::td[1]
La fórmula en el GSheets a usar sería:
=IMPORTXML("http://www.invertirenbolsa.info/historicodividendos/empresa/coca-cola"; "//td[text()='EBITDA']/following-sibling::td[1]")
El resultado es
1,58%
10.698,00
Este resultado devuelve 2 datos ya que nos está cogiendo el % ebitda que hay en otra tabla.
Para centrar bien el resultado, tenemos que afinar más la búsqueda, añadiendo la tabla a la que pertenece el elemento.
Para ello, subimos hacia arriba para ver la tabla de la que cuelga el TD, y vemos que es descendiente de un table cuya class contiene "cuarta tabla".
El XPath correcto sería:
Localízame una tabla cuyo atributo class contiene 'cuarta-tabla', y dentro de sus elemento, busca un elemento TD cuyo texto sea 'EBITDA', y me devuelves el 1er siguiente hermano.
//table[contains(@class,'cuarta-tabla')]//td[text()='EBITDA']/following-sibling::td[1]
La fórmula en el GSheets a usar sería:
=IMPORTXML("http://www.invertirenbolsa.info/historicodividendos/empresa/coca-cola"; "//table[contains(@class,'cuarta-tabla')]//td[text()='EBITDA']/following-sibling::td[1]")
El resultado es
10.698,00
Esta es una forma de componer una expresión XPath mirando directamente el HTML. Tienes más control al comprender de dónde estás cogiendo el dato, incluso modificar el xpath dinámicamente de teniendo en cuenta el año, el ticker, etc.
Otra alternativa es, al seleccionar el elemento a rescatar, con botón derecho, copiar Xpath.
Esta forma no me acaba de convencer, ya que en el momento que cambien el orden o metan algún campo más, es mayor el riesgo de que no muestre el resultado correcto.
El resultado mediante este método es
//*[@id="gkMainbody"]/div/div[3]/div/div[2]/div[3]/table/tbody/tr[7]/td[2]
También hay plugins de chrome para generar automáticamente la ruta XPath, como XPath Helper
Espero que os sea de utilidad.
Saludos.
1 comentario:
a useful article and very helpful, thanks Comrade has provided the required information.
visit also our site for those who need a web-based application.
Source Kode PHP MySQL
script php absensi siswa
script php bootstrap
script php connect mysql
script php Sistem Informasi
script php Sistem Pakar
script php Sistem Pendukung Keputusan
script php Web GIS
Publicar un comentario