En este artículo voy a comentar como hacer un scraping a un documento XML.
Usaré el plugin HTTP de Aymen y UBot, aunque también podríamos utilizar el plugin de xpath de bot-factory.
Como ejemplo he elegido un XML de la página w3schools, que contiene un pequeño listado de desayunos de un restaurante.
Veremos como extraer datos como: nombre, precio, descripción y calorías de cada uno, para luego mostrarlos en una tabla.
Fuente: https://www.w3schools.com/xml/simple.xml
<?xml version="1.0" encoding="UTF-8"?> <breakfast_menu> <food> <name>Belgian Waffles</name> <price>$5.95</price> <description>Two of our famous Belgian Waffles with plenty of real maple syrup</description> <calories>650</calories> </food> <food> <name>Strawberry Belgian Waffles</name> <price>$7.95</price> <description>Light Belgian waffles covered with strawberries and whipped cream</description> <calories>900</calories> </food> <food> <name>Berry-Berry Belgian Waffles</name> <price>$8.95</price> <description>Light Belgian waffles covered with an assortment of fresh berries and whipped cream</description> <calories>900</calories> </food> <food> <name>French Toast</name> <price>$4.50</price> <description>Thick slices made from our homemade sourdough bread</description> <calories>600</calories> </food> <food> <name>Homestyle Breakfast</name> <price>$6.95</price> <description>Two eggs, bacon or sausage, toast, and our ever-popular hash browns</description> <calories>950</calories> </food> </breakfast_menu>
Como siempre, este sencillo ejemplo se puede extrapolar a otras tareas, como pueda ser la obtención de un feed (RSS) de noticias, procesar el XML con el stock de un proveedor, etc.
El algoritmo es muy sencillo, recorremos primero los nodos para saber cuantos elementos tenemos que iterar y luego extraemos la información con un bucle.
Siempre podemos tener algún contratiempo con la codificación de caracteres o encoding, pero te muestro la configuración más habitual para salir del paso.
Comenzamos estableciendo el encoding a UTF-8.
Descargamos el XML y lo almacenamos en una variable.
Hacemos una primera pasada para averiguar el número de nodos:
Y por último recorremos con un loop, capturamos los datos con XPath y los almacenamos en una tabla.
Este sería el código completo:
plugin command("HTTP post.dll", "http set encoding", "UTF8") set(#xml_entrada,$plugin function("HTTP post.dll", "$http text encoder", "html decode", $plugin function("HTTP post.dll", "$http get", "https://www.w3schools.com/xml/simple.xml", "", "", "", "")),"Global") clear list(%desayunos) add list to list(%desayunos,$plugin function("HTTP post.dll", "$xpath parser", #xml_entrada, "//breakfast_menu/food", "InnerText", "XML"),"Don\'t Delete","Global") clear table(&tabla) set(#contador,1,"Global") loop($list total(%desayunos)) { set(#nombre,$plugin function("HTTP post.dll", "$xpath parser", #xml_entrada, "(//breakfast_menu/food/name)[{#contador}]", "InnerText", "XML"),"Global") set(#precio,$plugin function("HTTP post.dll", "$xpath parser", #xml_entrada, "(//breakfast_menu/food/price)[{#contador}]", "InnerText", "XML"),"Global") set(#descripcion,$plugin function("HTTP post.dll", "$xpath parser", #xml_entrada, "(//breakfast_menu/food/description)[{#contador}]", "InnerText", "XML"),"Global") set(#calorias,$plugin function("HTTP post.dll", "$xpath parser", #xml_entrada, "(//breakfast_menu/food/calories)[{#contador}]", "InnerText", "XML"),"Global") set table cell(&tabla,$subtract(#contador,1),0,#nombre) set table cell(&tabla,$subtract(#contador,1),1,#precio) set table cell(&tabla,$subtract(#contador,1),2,#descripcion) set table cell(&tabla,$subtract(#contador,1),3,#calorias) increment(#contador) }
Es interesante recordar la sintaxis para acceder a uno de los nodos:
//breakfast_menu/food/name
nos motraría todos los elementos del documento bajo esa ruta.
Si queremos seleccionar el primero, tendríamos que ponerlo entre paréntesis y elegir el elemento, poniendo el índice entre corchetes.
(//breakfast_menu/food/name)[1]
Para poder iterarlo con UBot, sustituimos el índice por el contador/iterador del loop.
La sintaxis de $xpath parser es:
set(#nombre,$plugin function("HTTP post.dll", "$xpath parser", #xml_entrada, "(//breakfast_menu/food/name)[{#contador}]", "InnerText", "XML"),"Global")
Y si usamos la de bot-factory (plugin gratuito) sería muy similar:
set(#titulo,$plugin function("XpathPlugin.dll", "$Generic Xpath Parser", #xml_entrada, "(//breakfast_menu/food/name)[{#contador}]", "InnerText", "False"),"Global")
El resultado sería una tabla como la siguiente:
Con esto hemos cubierto lo más básico para el scraping de documentos XML.
Si ya usabas el comando $xpath parser la única peculiaridad que quizá habías pasado por alto es que también puedes usarlo para procesar archivos XML, pero la forma de trabajar te habrá resultado familiar y no es muy enrevesada.