Clase 9: Usos de APIs

Web Scraping y acceso a datos desde la web


Cristián Ayala
Director DESUC

4 de julio de 2023

Motivación

  • Utilizar puertas provistas por servicios web para acceder a su información.

    • Wikipedia, Spotify, Mastodon.
  • Revisar paquetes ya desarrollados para acceder a servicios populares.

Paquetes para la clase de hoy

Grupo de paquetes interrelacionados:

  • WikipediR: Empaqueta la API de MediaWiki para bajar datos de Wikipedia.

  • spotifyr: Empaqueta la API de Spotify para bajar datos.

  • rtoot: Permite interactuar con la API de Mastodon.

Wikipedia

El software sobre el que está montada Wikipedia —MediaWiki— cuenta con una API para acceder al contenido almacenado en sus bases de datos.

Veamos la documentación y como crear llamados en la sandbox disponible

Wikipedia: API

Revisemos la API de Wikipedia.

  • Revisión de acciones disponibles.
    • Search: Buscar páginas.

    • Parse: Obtener contenido de una página.

    • Query: Obtener información de páginas.

Captura de página sobre web scraping en español.

Wikipedia: API buscar API: Search 1

Construcción de GET para la acción Search.

resp <- GET('https://es.wikipedia.org/w/api.php',
            query = list(action = 'query',
                         list = 'search',
                         srsearch = 'web scraping',
                         srlimit = 5,
                         format = 'json'),
            add_headers('Accept-Encoding' = 'gzip'))

# Leo el json que está dentro de la respuesta a la petición.
df <- content(resp, as = 'text') |> 
  jsonlite::fromJSON()

df |> str()
List of 3
 $ batchcomplete: chr ""
 $ continue     :List of 2
  ..$ sroffset: int 5
  ..$ continue: chr "-||"
 $ query        :List of 2
  ..$ searchinfo:List of 1
  .. ..$ totalhits: int 25
  ..$ search    :'data.frame':  5 obs. of  7 variables:
  .. ..$ ns       : int [1:5] 0 0 0 0 0
  .. ..$ title    : chr [1:5] "Web scraping" "Screen scraping" "Scrapy" "HtmlUnit" ...
  .. ..$ pageid   : int [1:5] 5544299 1194524 9214341 4481985 6269318
  .. ..$ size     : int [1:5] 11181 1116 2195 3644 2186
  .. ..$ wordcount: int [1:5] 1454 153 142 309 124
  .. ..$ snippet  : chr [1:5] "<span class=\"searchmatch\">Web</span> <span class=\"searchmatch\">scraping</span> o raspado <span class=\"sear"| __truncated__ "casos, es al contrario, como en los sistemas de captcha). La traducción aproximada de screen <span class=\"sear"| __truncated__ "por Scrapinghub Ltd., una empresa que ofrece productos y servicios de <span class=\"searchmatch\">web</span>-<s"| __truncated__ "páginas <span class=\"searchmatch\">web</span>, pero a veces se puede utilizar para <span class=\"searchmatch\""| __truncated__ ...
  .. ..$ timestamp: chr [1:5] "2023-07-03T06:13:52Z" "2019-07-13T13:59:58Z" "2021-10-08T07:29:04Z" "2019-08-05T20:58:33Z" ...

Wikipedia: API buscar API: Search 2

Transformación de los resultados a una tibble. La información que interesa está en query ↘️ search.

df$query$search |> as_tibble()
# A tibble: 5 × 7
     ns title            pageid  size wordcount snippet                timestamp
  <int> <chr>             <int> <int>     <int> <chr>                  <chr>    
1     0 Web scraping    5544299 11181      1454 "<span class=\"search… 2023-07-…
2     0 Screen scraping 1194524  1116       153 "casos, es al contrar… 2019-07-…
3     0 Scrapy          9214341  2195       142 "por Scrapinghub Ltd.… 2021-10-…
4     0 HtmlUnit        4481985  3644       309 "páginas <span class=… 2019-08-…
5     0 Beautiful Soup  6269318  2186       124 "Por lo tanto, esta b… 2022-09-…

Wikipedia: API contenido API: Parse 1

Obtención del contenido de página. GET para la acción Parse.

resp <- GET('https://es.wikipedia.org/w/api.php',
            query = list(action = 'parse',
                         page = 'Web scraping', # contenido de título de página
                         prop = 'text', # html de retorno
                         format = 'json'),
            add_headers('Accept-Encoding' = 'gzip'))

df <- content(resp, as = 'text') |> jsonlite::fromJSON()

str(df, 3)
List of 1
 $ parse:List of 3
  ..$ title : chr "Web scraping"
  ..$ pageid: int 5544299
  ..$ text  :List of 1
  .. ..$ *: chr "<div class=\"mw-parser-output\"><p><i><b>Web scraping</b></i> o <b>raspado web</b>, es una técnica utilizada me"| __truncated__

Wikipedia: API contenido API: Parse 2

El texto de contenido en parse ↘️ text ↘️ *.

df$parse$text$`*` |> 
  read_html() |> html_text() |> 
  cat()
Web scraping o raspado web, es una técnica utilizada mediante programas de software para extraer información de sitios web.[1]​ Usualmente, estos programas simulan la navegación de un humano en la World Wide Web ya sea utilizando el protocolo HTTP manualmente, o incrustando un navegador en una aplicación.
El web scraping está muy relacionado con la indexación de la web, la cual indexa la información de la web utilizando un robot y es una técnica universal adoptada por la mayoría de los motores de búsqueda. Sin embargo, el web scraping se enfoca más en la transformación de datos sin estructura en la web (como el formato HTML) en datos estructurados que pueden ser almacenados y analizados en una base de datos central, en una hoja de cálculo o en alguna otra fuente de almacenamiento. Alguno de los usos del web scraping son la comparación de precios en tiendas, la monitorización de datos relacionados con el clima de cierta región, la detección de cambios en sitios webs y la integración de datos en sitios webs. También es utilizado para obtener información relevante de un sitio a través de los rich snippets. 
En los últimos años el web scraping se ha convertido en una técnica muy utilizada dentro del sector del posicionamiento web gracias a su capacidad de generar grandes cantidades de datos para crear contenidos de calidad.[2]​

Técnicas[editar]
Web scraping es el proceso de recopilar información de forma automática de la Web. Es un campo con desarrollos activos, compartiendo un propósito en común con la visión de la Web semántica. Utiliza soluciones prácticas basadas en tecnologías existentes que son comúnmente ad hoc. Existen distintos niveles de automatización que las existentes tecnologías de Web Scraping pueden brindar:

«Copiar y pegar» humano: algunas veces incluso las mejores técnicas de web scraping no pueden reemplazar el examen manual de un humano, y a veces esta puede ser la única vía de solución cuando el sitio que tenemos en mente pone ciertas barreras para prevenir que se creen softwares para realizar tareas automáticas en este.
Uso de expresiones regulares: una posible vía para extraer información de páginas webs pueden ser las expresiones regulares, aunque comúnmente no se recomienda utilizarlas para parsear el formato HTML.
Protocolo HTTP: páginas webs estáticas y dinámicas pueden ser obtenidas haciendo peticiones HTTP al servidor remoto utilizando sockets, etc.
Algoritmos de minería de datos: muchos sitios webs tienen grandes colecciones de páginas generadas dinámicamente a partir de una base de datos. Datos de la misma categoría aparecen usualmente en páginas similares mediante un script o una plantilla. En la minería de datos, un programa detecta estas plantillas en un contexto específico y extrae su contenido.
Parsers de HTML: Algunos lenguajes, como XQuery y HTQL pueden ser utilizados para parsear documentos, recuperar y transformar el contenido de documentos HTML.
Aplicaciones para web scraping: existen muchas aplicaciones disponibles que pueden ser utilizadas para personalizar soluciones de Web Scraping. Estas aplicaciones podrían reconocer automáticamente la estructura de cierta página o brindar una interfaz al usuario donde este pudiera seleccionar los campos que son de interés dentro del documento. De esta forma no es necesario escribir manualmente código para realizar estas tareas.
Reconocimiento de información semántica: las páginas que son analizadas podrían incluir metadatos o cierta información semántica como anotaciones o comentarios, los cuales pueden ser usados comúnmente. Si estas anotaciones están en las mismas páginas, como sucede con los microformatos, estas podrían ser de utilidad cuando parseamos el DOM del documento. En otro caso, las anotaciones, organizadas en una capa semántica, son almacenadas y manejadas de forma separada desde otras páginas, por lo que los scrapers pueden recuperar estos esquemas y las instrucciones desde esta capa antes de analizar los documentos.[3]​Cuestiones legales[editar]
El web scraping pudiera ir en contra de los términos de uso de algunos sitios webs. El cumplimiento de estos términos no está totalmente claro.[4]​ Mientras que la duplicación de expresiones originales puede ser en muchos casos ilegal, en Estados Unidos la corte dictó en el caso Feist Publications v. Rural Telephone Service que la duplicación de hechos es permitida. Las cortes de Estados Unidos en ciertas ocasiones han reconocido que ciertos usos de los scrapers no deberían estar permitidos. Podría considerarse una computadora como una propiedad personal, y de esta forma el scraper estaría entrando sin autorización en esta propiedad. En el caso más conocido, eBay vs Bidder's Edge, la segunda empresa tuvo que parar de realizar peticiones automáticas al sitio de eBay. En este caso, Bidder's Edge pujaba automáticamente por ciertos productos en este sitio.
Uno de las principales pruebas de scraping involucró a American Airlines y a una empresa llamada FareChase. American Airlines ganó esta batalla, haciendo que FareChase parara de vender un software que le permitía a los usuarios comparar tarifas en línea si el sitio de American Airlines era incluido. La aerolínea dijo que las búsquedas de FareChase entraban sin autorización en los servidores cuando recopilaban la información públicamente disponible.
Aunque las decisiones actualmente tomadas no son uniformes, es difícil ignorar que un patrón está emergiendo, en el cual podemos ver que las cortes están preparándose para proteger el contenido propietario en sitios webs comerciales, previendo de esta forma que este sea utilizado sin el consentimiento de los propietarios de los sitios. Sin embargo, el grado de protección de estos contenidos aún no está establecido, y dependerá del tipo de acceso realizado por los scrapers, de la cantidad de información recopilada y del grado en el que afecten estos factores al propietario del sitio web.

Medidas para detener a los scrapers[editar]
El administrador de un sitio web puede utilizar varias técnicas para detener o disminuir los pedidos de los scrapers. Algunas técnicas incluyen:

Añadir entradas al fichero robots.txt. Algunos bots pueden ser detenidos de esta forma. Hay personas que piensan que el bot de Google puede ser detenido así, cosa que el propio buscador ha negado.
Bloquear la dirección IP. Esto también bloqueará todos los accesos desde esa misma IP, por lo que los usuarios no podrán navegar por el sitio web si acceden desde esta.
Deshabilitar cualquier interfaz de programación de aplicaciones que el sitio web pudiera estar brindando.
Los bots o scrapers algunas veces declaran quienes son, y gracias a esto pueden ser bloqueados. «Googlebot» es un ejemplo. Algunos scrapers no hacen lo que el bot de G., para que no se pueda distinguir entre un navegador común y ellos.
Monitorear el exceso de tráfico proveniente de cierta IP.
Añadir un captcha u otro sistema de verificación manual al sitio web. No se garantiza el completo bloqueo de los scrapers, pero mediante esta técnica se dificulta el acceso de los mismos a los sitios webs.
Servicios comerciales antibots: algunas empresas ofrecen servicios antibots y antiscraping.[5]​
Incrementar el uso de JavaScript y AJAX. De esta forma es más difícil para los scrapers simular las peticiones como si fueran un navegador común, aunque hará que usuarios legítimos dejen de poder ver la página.La mayoría de estos métodos suponen una merma importante en la usabilidad del sitio web en cuestión y los beneficios pueden ser muy puntuales.

Beneficios[editar]
Pese al planteamiento negativo de ciertos sectores, el rastreo automático y scraping son muy importantes para mantener la historia de Internet. Las iniciativas de archivado web se basan mayoritariamente en esta técnica.

Herramientas notables[editar]

UIPath
Apache Camel
Automation Anywhere
Convertigo
cURL
Data Toolbar
Firebug
Greasemonkey
HtmlUnit
Node.js
HTTrack
iMacros
Aptana Jaxer
nokogiri
watir
Wget
WSO2 Mashup Server
HtmlAgilityPack
BeautifulSoup
Scrapy

Véase también[editar]
Minería de datos
Mashup (aplicación web híbrida)
Spamdexing
Corpus lingüístico
Araña web
Metadato
Screen scraping.Referencias[editar]
↑  Martí, Marq (8 de abril de 2016). «¿Qué es el Web scraping? Introducción y herramientas» (html). Sitelab España. Archivado desde el original el 29 de julio de 2017. Consultado el 30 de marzo de 2020. «El web scraping es una técnica que sirve para extraer información de páginas web de forma automatizada. Si traducimos del inglés su significado vendría a significar algo así como “escarbar una web”. »  

↑  Martí, Marq (8 de abril de 2016). «¿Qué es el Web scraping? Introducción y herramientas» (html). Sitelab España. Archivado desde el original el 29 de julio de 2017. Consultado el 30 de marzo de 2020. «Para controlar la imagen y la visibilidad de nuestra marca en internet: a través de un scrapeo podemos automatizar la posición por la que varios artículos de nuestra web se posicionan en Google o, por ejemplo, controlar la presencia del nombre de nuestra marca en determinados foros. Ejemplo: rastrear la posición en Google de todas las entradas de nuestro blog. »  

↑ http://www.gooseeker.com/en/node/knowledgebase/freeformat

↑ https://web.archive.org/web/20020308222536/http://www.chillingeffects.org/linking/faq.cgi#QID596

↑ https://s3.us-west-2.amazonaws.com/research-papers-mynk/Breaking-Fraud-And-Bot-Detection-Solutions.pdf


.mw-parser-output .mw-authority-control{margin-top:1.5em}.mw-parser-output .mw-authority-control .navbox table{margin:0}.mw-parser-output .mw-authority-control .navbox hr:last-child{display:none}.mw-parser-output .mw-authority-control .navbox+.mw-mf-linked-projects{display:none}.mw-parser-output .mw-authority-control .mw-mf-linked-projects{display:flex;padding:0.5em;border:1px solid #c8ccd1;background-color:#eaecf0;color:#222222}.mw-parser-output .mw-authority-control .mw-mf-linked-projects ul li{margin-bottom:0}Control de autoridades
Proyectos Wikimedia
 Datos: Q665452
 Datos: Q665452

Wikipedia: API información API: Query 1

Información de varias páginas. GET para la acción Query.

resp <- GET('https://es.wikipedia.org/w/api.php',
            query = list(action = 'query',
                         titles = 'Web scraping|Python', # Varios títulos a la ves.
                         prop = 'info|categories|iwlinks', # Información a obtener.
                         format = 'json'),
            add_headers('Accept-Encoding' = 'gzip'))

df <- content(resp, as = 'text') |> jsonlite::fromJSON()

str(df, 3)
List of 2
 $ continue:List of 2
  ..$ clcontinue: chr "2330|Wikipedia:Artículos_con_datos_por_trasladar_a_Wikidata"
  ..$ continue  : chr "||info|iwlinks"
 $ query   :List of 1
  ..$ pages:List of 2
  .. ..$ 2330   :List of 12
  .. ..$ 5544299:List of 11

Wikipedia: API información API: Query 2

df$query$pages |> 
  enframe() |> 
  unnest_wider(value)
# A tibble: 2 × 13
  name     pageid    ns title     contentmodel pagelanguage pagelanguagehtmlcode
  <chr>     <int> <int> <chr>     <chr>        <chr>        <chr>               
1 2330       2330     0 Python    wikitext     es           es                  
2 5544299 5544299     0 Web scra… wikitext     es           es                  
# ℹ 6 more variables: pagelanguagedir <chr>, touched <chr>, lastrevid <int>,
#   length <int>, categories <list>, iwlinks <list>

Wikipedia: usando WikipediR 1

WikipediR: lo mismo, pero más fácil.

  • page_info: información sobre una página específica.

  • page_content: contenido de una página específica.

  • page_links: links disponibles en una página específica.

library(WikipediR)

info_wiki <- page_info(
  language = 'es', 
  project = 'wikipedia', 
  page = 'Web_scraping|Python') 
str(info_wiki, 3)
List of 2
 $ batchcomplete: chr ""
 $ query        :List of 2
  ..$ normalized:List of 1
  .. ..$ :List of 2
  ..$ pages     :List of 2
  .. ..$ 2330   :List of 17
  .. ..$ 5544299:List of 17
 - attr(*, "class")= chr "pageinfo"

Wikipedia: usando WikipediR 2

Resultado de la búsqueda.

info_wiki$query$pages |> 
  enframe() |> 
  unnest_wider(value)
# A tibble: 2 × 18
  name     pageid    ns title     contentmodel pagelanguage pagelanguagehtmlcode
  <chr>     <int> <int> <chr>     <chr>        <chr>        <chr>               
1 2330       2330     0 Python    wikitext     es           es                  
2 5544299 5544299     0 Web scra… wikitext     es           es                  
# ℹ 11 more variables: pagelanguagedir <chr>, touched <chr>, lastrevid <int>,
#   length <int>, protection <lgl>, restrictiontypes <list>, talkid <int>,
#   fullurl <chr>, editurl <chr>, canonicalurl <chr>, displaytitle <chr>

Wikipedia: usando WikipediR 3

Captura de página sobre web scraping en español.

cont_wiki <-  page_content(language = 'es', 
                           project = 'wikipedia', 
                           page_name = 'Web_scraping')

str(cont_wiki) # Una lisa parse con 4 elementos dentro
List of 1
 $ parse:List of 4
  ..$ title : chr "Web scraping"
  ..$ pageid: int 5544299
  ..$ revid : int 152238389
  ..$ text  :List of 1
  .. ..$ *: chr "<div class=\"mw-parser-output\"><p><i><b>Web scraping</b></i> o <b>raspado web</b>, es una técnica utilizada me"| __truncated__
 - attr(*, "class")= chr "pcontent"

Wikipedia: usando WikipediR 4

Texto sobre Web scraping.

cont_wiki$parse$text$`*` |> # Texto del requerimiento
  read_html() |> html_text() |> 
  cat()
Web scraping o raspado web, es una técnica utilizada mediante programas de software para extraer información de sitios web.[1]​ Usualmente, estos programas simulan la navegación de un humano en la World Wide Web ya sea utilizando el protocolo HTTP manualmente, o incrustando un navegador en una aplicación.
El web scraping está muy relacionado con la indexación de la web, la cual indexa la información de la web utilizando un robot y es una técnica universal adoptada por la mayoría de los motores de búsqueda. Sin embargo, el web scraping se enfoca más en la transformación de datos sin estructura en la web (como el formato HTML) en datos estructurados que pueden ser almacenados y analizados en una base de datos central, en una hoja de cálculo o en alguna otra fuente de almacenamiento. Alguno de los usos del web scraping son la comparación de precios en tiendas, la monitorización de datos relacionados con el clima de cierta región, la detección de cambios en sitios webs y la integración de datos en sitios webs. También es utilizado para obtener información relevante de un sitio a través de los rich snippets. 
En los últimos años el web scraping se ha convertido en una técnica muy utilizada dentro del sector del posicionamiento web gracias a su capacidad de generar grandes cantidades de datos para crear contenidos de calidad.[2]​

Técnicas[editar]
Web scraping es el proceso de recopilar información de forma automática de la Web. Es un campo con desarrollos activos, compartiendo un propósito en común con la visión de la Web semántica. Utiliza soluciones prácticas basadas en tecnologías existentes que son comúnmente ad hoc. Existen distintos niveles de automatización que las existentes tecnologías de Web Scraping pueden brindar:

«Copiar y pegar» humano: algunas veces incluso las mejores técnicas de web scraping no pueden reemplazar el examen manual de un humano, y a veces esta puede ser la única vía de solución cuando el sitio que tenemos en mente pone ciertas barreras para prevenir que se creen softwares para realizar tareas automáticas en este.
Uso de expresiones regulares: una posible vía para extraer información de páginas webs pueden ser las expresiones regulares, aunque comúnmente no se recomienda utilizarlas para parsear el formato HTML.
Protocolo HTTP: páginas webs estáticas y dinámicas pueden ser obtenidas haciendo peticiones HTTP al servidor remoto utilizando sockets, etc.
Algoritmos de minería de datos: muchos sitios webs tienen grandes colecciones de páginas generadas dinámicamente a partir de una base de datos. Datos de la misma categoría aparecen usualmente en páginas similares mediante un script o una plantilla. En la minería de datos, un programa detecta estas plantillas en un contexto específico y extrae su contenido.
Parsers de HTML: Algunos lenguajes, como XQuery y HTQL pueden ser utilizados para parsear documentos, recuperar y transformar el contenido de documentos HTML.
Aplicaciones para web scraping: existen muchas aplicaciones disponibles que pueden ser utilizadas para personalizar soluciones de Web Scraping. Estas aplicaciones podrían reconocer automáticamente la estructura de cierta página o brindar una interfaz al usuario donde este pudiera seleccionar los campos que son de interés dentro del documento. De esta forma no es necesario escribir manualmente código para realizar estas tareas.
Reconocimiento de información semántica: las páginas que son analizadas podrían incluir metadatos o cierta información semántica como anotaciones o comentarios, los cuales pueden ser usados comúnmente. Si estas anotaciones están en las mismas páginas, como sucede con los microformatos, estas podrían ser de utilidad cuando parseamos el DOM del documento. En otro caso, las anotaciones, organizadas en una capa semántica, son almacenadas y manejadas de forma separada desde otras páginas, por lo que los scrapers pueden recuperar estos esquemas y las instrucciones desde esta capa antes de analizar los documentos.[3]​Cuestiones legales[editar]
El web scraping pudiera ir en contra de los términos de uso de algunos sitios webs. El cumplimiento de estos términos no está totalmente claro.[4]​ Mientras que la duplicación de expresiones originales puede ser en muchos casos ilegal, en Estados Unidos la corte dictó en el caso Feist Publications v. Rural Telephone Service que la duplicación de hechos es permitida. Las cortes de Estados Unidos en ciertas ocasiones han reconocido que ciertos usos de los scrapers no deberían estar permitidos. Podría considerarse una computadora como una propiedad personal, y de esta forma el scraper estaría entrando sin autorización en esta propiedad. En el caso más conocido, eBay vs Bidder's Edge, la segunda empresa tuvo que parar de realizar peticiones automáticas al sitio de eBay. En este caso, Bidder's Edge pujaba automáticamente por ciertos productos en este sitio.
Uno de las principales pruebas de scraping involucró a American Airlines y a una empresa llamada FareChase. American Airlines ganó esta batalla, haciendo que FareChase parara de vender un software que le permitía a los usuarios comparar tarifas en línea si el sitio de American Airlines era incluido. La aerolínea dijo que las búsquedas de FareChase entraban sin autorización en los servidores cuando recopilaban la información públicamente disponible.
Aunque las decisiones actualmente tomadas no son uniformes, es difícil ignorar que un patrón está emergiendo, en el cual podemos ver que las cortes están preparándose para proteger el contenido propietario en sitios webs comerciales, previendo de esta forma que este sea utilizado sin el consentimiento de los propietarios de los sitios. Sin embargo, el grado de protección de estos contenidos aún no está establecido, y dependerá del tipo de acceso realizado por los scrapers, de la cantidad de información recopilada y del grado en el que afecten estos factores al propietario del sitio web.

Medidas para detener a los scrapers[editar]
El administrador de un sitio web puede utilizar varias técnicas para detener o disminuir los pedidos de los scrapers. Algunas técnicas incluyen:

Añadir entradas al fichero robots.txt. Algunos bots pueden ser detenidos de esta forma. Hay personas que piensan que el bot de Google puede ser detenido así, cosa que el propio buscador ha negado.
Bloquear la dirección IP. Esto también bloqueará todos los accesos desde esa misma IP, por lo que los usuarios no podrán navegar por el sitio web si acceden desde esta.
Deshabilitar cualquier interfaz de programación de aplicaciones que el sitio web pudiera estar brindando.
Los bots o scrapers algunas veces declaran quienes son, y gracias a esto pueden ser bloqueados. «Googlebot» es un ejemplo. Algunos scrapers no hacen lo que el bot de G., para que no se pueda distinguir entre un navegador común y ellos.
Monitorear el exceso de tráfico proveniente de cierta IP.
Añadir un captcha u otro sistema de verificación manual al sitio web. No se garantiza el completo bloqueo de los scrapers, pero mediante esta técnica se dificulta el acceso de los mismos a los sitios webs.
Servicios comerciales antibots: algunas empresas ofrecen servicios antibots y antiscraping.[5]​
Incrementar el uso de JavaScript y AJAX. De esta forma es más difícil para los scrapers simular las peticiones como si fueran un navegador común, aunque hará que usuarios legítimos dejen de poder ver la página.La mayoría de estos métodos suponen una merma importante en la usabilidad del sitio web en cuestión y los beneficios pueden ser muy puntuales.

Beneficios[editar]
Pese al planteamiento negativo de ciertos sectores, el rastreo automático y scraping son muy importantes para mantener la historia de Internet. Las iniciativas de archivado web se basan mayoritariamente en esta técnica.

Herramientas notables[editar]

UIPath
Apache Camel
Automation Anywhere
Convertigo
cURL
Data Toolbar
Firebug
Greasemonkey
HtmlUnit
Node.js
HTTrack
iMacros
Aptana Jaxer
nokogiri
watir
Wget
WSO2 Mashup Server
HtmlAgilityPack
BeautifulSoup
Scrapy

Véase también[editar]
Minería de datos
Mashup (aplicación web híbrida)
Spamdexing
Corpus lingüístico
Araña web
Metadato
Screen scraping.Referencias[editar]
↑  Martí, Marq (8 de abril de 2016). «¿Qué es el Web scraping? Introducción y herramientas» (html). Sitelab España. Archivado desde el original el 29 de julio de 2017. Consultado el 30 de marzo de 2020. «El web scraping es una técnica que sirve para extraer información de páginas web de forma automatizada. Si traducimos del inglés su significado vendría a significar algo así como “escarbar una web”. »  

↑  Martí, Marq (8 de abril de 2016). «¿Qué es el Web scraping? Introducción y herramientas» (html). Sitelab España. Archivado desde el original el 29 de julio de 2017. Consultado el 30 de marzo de 2020. «Para controlar la imagen y la visibilidad de nuestra marca en internet: a través de un scrapeo podemos automatizar la posición por la que varios artículos de nuestra web se posicionan en Google o, por ejemplo, controlar la presencia del nombre de nuestra marca en determinados foros. Ejemplo: rastrear la posición en Google de todas las entradas de nuestro blog. »  

↑ http://www.gooseeker.com/en/node/knowledgebase/freeformat

↑ https://web.archive.org/web/20020308222536/http://www.chillingeffects.org/linking/faq.cgi#QID596

↑ https://s3.us-west-2.amazonaws.com/research-papers-mynk/Breaking-Fraud-And-Bot-Detection-Solutions.pdf


.mw-parser-output .mw-authority-control{margin-top:1.5em}.mw-parser-output .mw-authority-control .navbox table{margin:0}.mw-parser-output .mw-authority-control .navbox hr:last-child{display:none}.mw-parser-output .mw-authority-control .navbox+.mw-mf-linked-projects{display:none}.mw-parser-output .mw-authority-control .mw-mf-linked-projects{display:flex;padding:0.5em;border:1px solid #c8ccd1;background-color:#eaecf0;color:#222222}.mw-parser-output .mw-authority-control .mw-mf-linked-projects ul li{margin-bottom:0}Control de autoridades
Proyectos Wikimedia
 Datos: Q665452
 Datos: Q665452

Spotify

Uno de los mayores proveedores de servicio de música del mundo. Tiene disponible una API para la integración de su servicio con otras aplicaciones. Podemos usarla para obtener información.

Spotify dashboard

Spotify: API 1

Revisemos la API de Spotify. Acciones de interés.

Spotify: API 2

Búsqueda de género metal usando la API directamente.

Pedí el token de acceso usando spotifyr.

s_met <- GET('https://api.spotify.com/v1/search',
             query = list(q = 'genre:metal', 
                          market = 'CL', 
                          type = 'artist', 
                          limit = 8),
             accept_json(),
             add_headers(Authorization = str_glue("Bearer {spotifyr::get_spotify_access_token()}")))

df_met <- s_met |> content('text') |> 
  jsonlite::fromJSON()

df_met$artists$items |> 
  as_tibble() |> unpack(followers, names_repair = 'minimal') |>
  select(id, name, popularity, total)
# A tibble: 8 × 4
  id                     name                  popularity    total
  <chr>                  <chr>                      <int>    <int>
1 5eAWCfyUhZtHHtBdNk56l1 System Of A Down              79  9337537
2 6XyY86QOPPrYVGvF9ch6wz Linkin Park                   84 23820849
3 2ye2Wgw4gimLv2eAKyk1NB Metallica                     82 25209913
4 3qm84nBOXUEQ2vnTfUTTFC Guns N' Roses                 79 29190618
5 0L8ExT028jH3ddEcZwqJJ5 Red Hot Chili Peppers         82 19834109
6 05fG473iIaoy82BF1aGhL8 Slipknot                      78  9783405
7 6Ghvu1VvMGScGpOUJBAHNH Deftones                      77  4073355
8 58lV9VcRSjABbAbfWS6skp Bon Jovi                      77 12377897

Spotify: spotifyr 1

Envuelve los llamados a la API de Spotify en funciones de R. Puede verse su referencia

Búsqueda análoga a la anterior:

library(spotifyr)

df_met <- get_genre_artists('metal', limit = 8)
df_met |> 
  select(id, name, popularity, followers.total)
# A tibble: 8 × 4
  id                     name                  popularity followers.total
  <chr>                  <chr>                      <int>           <int>
1 6XyY86QOPPrYVGvF9ch6wz Linkin Park                   84        23820849
2 6Ghvu1VvMGScGpOUJBAHNH Deftones                      77         4073355
3 2ye2Wgw4gimLv2eAKyk1NB Metallica                     82        25209913
4 5eAWCfyUhZtHHtBdNk56l1 System Of A Down              79         9337537
5 05fG473iIaoy82BF1aGhL8 Slipknot                      78         9783405
6 0L8ExT028jH3ddEcZwqJJ5 Red Hot Chili Peppers         82        19834109
7 0nmQIMXWTXfhgOBdNzhGOs Avenged Sevenfold             76         6329809
8 3RNrq3jvMZxD9ZyoOZbQOD Korn                          75         6425886

Spotify: spotifyr 2

Cambiamos los criterios de búsqueda para encontrar podcasts.

df_pod <- search_spotify(q = 'podcast', type = 'show', market = 'CL', limit = 10)

df_pod |> 
  select(id, name, total_episodes, description)
# A tibble: 10 × 4
   id                     name                        total_episodes description
   <chr>                  <chr>                                <int> <chr>      
 1 0sGGLIDnnijRPLef7InllD Entiende Tu Mente                      289 "Entiende …
 2 2xV7Vx7NQgAC8vMt2vZNnE El Podcast de Marian Rojas…             31 "Marian Ro…
 3 20ch3IIqtWSSM4nfy11ZzP Caso 63                                 37 "Año 2022.…
 4 4OtyxH4rxMjxXwk0cUKoQ8 Primerizas El Podcast                   17 "Quieres a…
 5 0L9Cojg81OdapnXF7aIVee Motivación, Éxito y Lidera…             40 "Nuevo Pod…
 6 2nAf8IDQG1sPEwAKdG2DyM Despertando Podcast                    812 "¿Qué pasa…
 7 6S7DckQZ7RzFVbvUF8rY1k Presentaciones Felipe Avel…             20 "Distintas…
 8 5ycEEouNP3fB4emhae3tGE Decretum Podcast                       118 "Bienvenid…
 9 17dk0hYDmVq7EzGXC8y4u6 Filosofía, Psicología, His…            253 "Relatos b…
10 1w9Me4TrRiDOuK3OsJ2VAW Durmiendo Podcast                      557 "¡Despídet…

Spotify: spotifyr listas

Exploremos las características de canciones gracias a la lista top 50 canciones en Chile.

df_top <- get_playlist('37i9dQZEVXbL0GavIqMTeb') # ID de la lista.
df_top_track <- df_top$tracks$items |> as_tibble()

suppressMessages(
  # Seleccionar y limpiar solo alguna de las variables disponibles
  df_top_track_sel <- df_top_track |> 
    mutate(track.id, track.name, track.popularity, track.album.release_date, 
           name = map(track.album.artists, 'name'),
           .keep = 'none') |> 
    unnest_wider(col = name, names_sep = '_')
)

df_top_track_sel |> head()
# A tibble: 6 × 7
  track.id      track.name track.popularity track.album.release_…¹ name_1 name_2
  <chr>         <chr>                 <int> <chr>                  <chr>  <chr> 
1 7ABLbnD53cQK… LALA                     84 2023-03-23             Myke … <NA>  
2 3tiJUOfAEqIr… Un Finde …               91 2023-04-04             Big O… FMK   
3 3MBzcfMRsUvA… EL AMOR D…               77 2023-06-15             Gino … Jairo…
4 6UR1k5NGqgNG… Cabaña                   68 2023-06-24             El Jo… Ugly …
5 3jYFhbevv3MU… Una en un…               80 2023-05-18             Jere … <NA>  
6 6XSqqQIy7Lm7… Classy 101               97 2023-03-31             Feid   Young…
# ℹ abbreviated name: ¹​track.album.release_date
# ℹ 1 more variable: name_3 <chr>

Spotify: spotifyr canciones 1

Con el id de las canciones, podemos obtener características musicales de las canciones.

df_track_af <- get_track_audio_features(df_top_track_sel$track.id)

head(df_track_af)
# A tibble: 6 × 18
  danceability energy   key loudness  mode speechiness acousticness
         <dbl>  <dbl> <int>    <dbl> <int>       <dbl>        <dbl>
1        0.708  0.737     1    -4.04     1      0.0436       0.0739
2        0.499  0.519    11    -8.20     1      0.0595       0.109 
3        0.796  0.819    10    -5.69     0      0.0463       0.14  
4        0.73   0.751    11    -5.51     1      0.0511       0.121 
5        0.669  0.707     2    -6.43     0      0.0576       0.0109
6        0.859  0.658    11    -4.79     1      0.159        0.145 
# ℹ 11 more variables: instrumentalness <dbl>, liveness <dbl>, valence <dbl>,
#   tempo <dbl>, type <chr>, id <chr>, uri <chr>, track_href <chr>,
#   analysis_url <chr>, duration_ms <int>, time_signature <int>

Spotify: spotifyr canciones 2

Gráfico con la posición relativa de las canciones según 5 características.

df_top_track_sel <- bind_cols(df_top_track_sel, 
                              df_track_af)

gg <- df_top_track_sel |> 
  mutate(pos = row_number()) |>
  pivot_longer(cols = c(danceability, 
                        energy, 
                        speechiness, 
                        acousticness, 
                        liveness),
               names_to = 'variable', 
               values_to = 'valor') |> 
  ggplot(aes(x = variable, 
             y = valor, 
             colour = track.popularity)) +
  geom_point(aes(size = rev(pos)),
             alpha = 0.5,
             show.legend = FALSE) + 
  theme_minimal() +
  labs(title = 'Características de las 100 canciones en Chile',
       subtitle = 'Lista Top 50 — Chile, Spotify', 
       x = NULL)
gg

Mastodon: API

La API de Mastodon se puede consultar acá.

  • Es de uso abierto y gratuito.

  • Packete: rtoot

Mastodon: rtoot 1

Instalar versión en desarrollo:

install.packages("rtoot")
library(rtoot)

custom_instance <- 'lile.cl'

lile_instance <- get_instance_general(instance = custom_instance, anonymous = TRUE)

lile_instance |> str(2)
List of 16
 $ uri              : chr "lile.cl"
 $ title            : chr "Lile"
 $ short_description: chr "Servidor chileno de Mastodon cuyo nombre hace referencia a un ave nativa del país. Aspiramos a ser una comunida"| __truncated__
 $ description      : chr "Servidor experimental de Mastodon.\r\n\r\nEl nombre viene de una ave nativa del país: <a href=\"https://www.ave"| __truncated__
 $ email            : chr "contacto@lile.cl"
 $ version          : chr "4.1.0"
 $ urls             :List of 1
  ..$ streaming_api: chr "wss://lile.cl"
 $ stats            :List of 3
  ..$ user_count  : int 3054
  ..$ status_count: int 409820
  ..$ domain_count: int 20082
 $ thumbnail        : chr "https://lile.cl/system/site_uploads/files/000/000/005/@1x/877f7d9c81d94e15.png"
 $ languages        :List of 1
  ..$ : chr "es"
 $ registrations    : logi TRUE
 $ approval_required: logi FALSE
 $ invites_enabled  : logi FALSE
 $ configuration    :List of 4
  ..$ accounts         :List of 1
  ..$ statuses         :List of 3
  ..$ media_attachments:List of 6
  ..$ polls            :List of 4
 $ contact_account  :List of 23
  ..$ id             : chr "109311144305293045"
  ..$ username       : chr "lile"
  ..$ acct           : chr "lile"
  ..$ display_name   : chr "Lile"
  ..$ locked         : logi FALSE
  ..$ bot            : logi FALSE
  ..$ discoverable   : logi TRUE
  ..$ group          : logi FALSE
  ..$ created_at     : chr "2022-11-09T00:00:00.000Z"
  ..$ note           : chr "<p>Cuenta oficial de comunicaciones de lile.cl</p><p>-----</p><p>Pato chileno, también conocido como Cormorán L"| __truncated__
  ..$ url            : chr "https://lile.cl/@lile"
  ..$ avatar         : chr "https://lile.cl/system/accounts/avatars/109/311/144/305/293/045/original/00941123303f1ca5.jpeg"
  ..$ avatar_static  : chr "https://lile.cl/system/accounts/avatars/109/311/144/305/293/045/original/00941123303f1ca5.jpeg"
  ..$ header         : chr "https://lile.cl/system/accounts/headers/109/311/144/305/293/045/original/af94d90915dba11c.jpg"
  ..$ header_static  : chr "https://lile.cl/system/accounts/headers/109/311/144/305/293/045/original/af94d90915dba11c.jpg"
  ..$ followers_count: int 979
  ..$ following_count: int 0
  ..$ statuses_count : int 44
  ..$ last_status_at : chr "2023-06-29"
  ..$ noindex        : logi FALSE
  ..$ emojis         : list()
  ..$ roles          :List of 1
  ..$ fields         :List of 4
 $ rules            :List of 5
  ..$ :List of 2
  ..$ :List of 2
  ..$ :List of 2
  ..$ :List of 2
  ..$ :List of 2
 - attr(*, "headers")= tibble [1 × 3] (S3: tbl_df/tbl/data.frame)

Mastodon: rtoot 2

Listado de instancias de Mastodon

lile_peers <- get_instance_peers(instance = custom_instance, token = NULL, anonymous = TRUE)

head(lile_peers)
[1] "social.piewpiew.se"                "videos.cemea.org"                 
[3] "www.lexicomancia.com"              "barrow.social"                    
[5] "tube-maternelle.apps.education.fr" "m.bohlenlabs.com"                 

Instancias con “chile” en su nombre:

lile_peers[grepl('chile', lile_peers)]
[1] "epicyon.chilemasto.casa"   "devschile.social"         
[3] "chilemasto.casa"           "friendica.chilemasto.casa"

Buscar la instancia oficial:

lile_peers[grepl('mastodon.social', lile_peers)]
[1] "snowmastodon.social"      "mastodon.socialspill.com"
[3] "swedishmastodon.social"   "mastodon.social"         
[5] "mastodon.socialistra.org"

Mastodon: rtoot 3

get_instance_trends(
  instance = custom_instance,
  token = NULL,
  limit = 10,
  anonymous = TRUE
)
# A tibble: 70 × 5
   name       url                             day        accounts  uses
   <chr>      <chr>                           <date>        <int> <int>
 1 5juegos    https://lile.cl/tags/5juegos    2023-07-04        4     4
 2 5juegos    https://lile.cl/tags/5juegos    2023-07-03       17    17
 3 5juegos    https://lile.cl/tags/5juegos    2023-07-02        0     0
 4 5juegos    https://lile.cl/tags/5juegos    2023-07-01        0     0
 5 5juegos    https://lile.cl/tags/5juegos    2023-06-30        0     0
 6 5juegos    https://lile.cl/tags/5juegos    2023-06-29        0     0
 7 5juegos    https://lile.cl/tags/5juegos    2023-06-28        0     0
 8 Fotomontag https://lile.cl/tags/Fotomontag 2023-07-04        3     3
 9 Fotomontag https://lile.cl/tags/Fotomontag 2023-07-03       22    22
10 Fotomontag https://lile.cl/tags/Fotomontag 2023-07-02        2     2
# ℹ 60 more rows

Mastodon: rtoot 5, stream

if(interactive()) {
  stream_timeline_public(
    timeout = 30,
    local = FALSE,
    file_name = 'slides/class_9/class_9_files/stream_lile_public.json',
    append = TRUE,
    instance = custom_instance,
    token = NULL,
    anonymous = FALSE,
    verbose = TRUE
  )
  
  parse_stream("slides/class_9/class_9_files/stream_lile_public.json")
}

En el próximo taller…

  • chromote.

  • repaso.

Presentación y código en GitHub:
https://github.com/caayala/web_scraping_soc40XX_2023
https://caayala.github.io/web_scraping_soc40XX_2023


¡Gracias!


Cristián Ayala
https://blog.desuc.cl/
http://github.com/caayala