¿Alguna vez os habéis preguntado las relaciones entre los lenguajes de programación o cuánta influencia tiene cada uno? En el equipo de innovación sí, así que nos hemos puesto manos a la obra.
Para resolver estas cuestiones hemos desarrollado un programa que usa web scraping, una técnica para extraer información de la web, la mayor fuente de datos existente.
En cuanto a la parte técnica, el script está desarrollado en Python 3.5, y hace uso de las librerías:
- BeautifulSoup4: permite parsear el HTML y utilizar selectores tipo JQuery.
- Requests: abstrae la librería vainilla urllib, facilitando las peticiones HTTP.
Tenemos las herramientas, pero no los datos. La solución como siempre… ¡Wikipedia! En esta entrada tenemos un listado de los lenguajes de programación, accedamos a la de Python y… ¡BINGO! En la parte derecha observamos una ficha técnica, y en ella el apartado “Influenced”, justo lo que necesitábamos.
Os estaréis preguntando por qué no vamos a utilizar el campo “Influenced by”, porque es simétrico y por tanto redundante. Por ejemplo: Python influencia a JavaScript, y JavaScript ha sido influenciado por Python.
Ahora que sabemos cómo se han influenciado los lenguajes entre sí, falta por conocer la influencia de cada uno, preguntaremos a Google (como siempre). La importancia vendrá dada por el número de resultados de la búsqueda.
Hasta este momento no hemos tratado la legalidad de todo esto, especialmente interesante porque no todos los sitios permiten utilizar robots ¿Cómo podemos saber si una web permite el scraping? Mirando las condiciones de uso, documento que todos nos leemos. En nuestro caso, Google y Wikipedia sí que lo permiten, siempre y cuando seamos respetuosos, un eufemismo para referirse a los ataques de denegación de servicio, también conocidos como DOS o DDOS.
Queda una última cuestión, ¿qué vamos a hacer con estos datos? Los representaremos en un grafo dirigido, donde las aristas indicarán la presencia de una relación y los nodos los lenguajes de programación, que serán más grandes contra mayor influencia tengan y más rojos contra más relaciones. El grafo lo generaremos mediante Gephi, un software de visualización, exploración y manipulación de todo tipo de grafos.
A continuación, pasaremos a la parte más interesante, la del código, apartado en el que Python destaca por su elegancia.
Imports
from bs4 import BeautifulSoup
from urllib.parse import quote_plus
import csv, re, requests
Constantes
LANGS = 'https://en.wikipedia.org/wiki/List_of_programming_languages'
Funciones
langsWikipedia: recorre el listado de los lenguajes de programación del post de Wikipedia, devolviendo una lista de elementos con esta forma: lenguaje, URL Wikipedia.
def langsWikipedia():
res = []
html = requests.get(LANGS).text
soup = BeautifulSoup(html, 'html.parser')
for div in soup.find_all(class_='div-col'):
for a in div.find_all('a'):
URL = 'https://en.wikipedia.org' + a['href']
res.append((a.text, URL))
return res
edges: este método se encarga de crear las aristas del grafo. Utiliza el método anterior para acceder a los posts de los lenguajes. Para cada uno, la función buscará la ficha técnica y dentro de ella el campo ‘Influenced’, añadiendo a los resultados la relación correspondiente. Recordemos que tanto la ficha como el campo no tienen por qué existir.
def edges():
res = []
for lang, URL in langsWikipedia():
html = requests.get(URL).text
soup = BeautifulSoup(html, 'html.parser')
table = soup.find('table', class_='infobox')
if table:
tr = table.find_all('tr')
for i in range(len(tr)):
if tr[i].th and tr[i].th.text == 'Influenced':
for a in tr[i + 1].td.find_all('a', recursive=False):
res.append((lang, a.text))
break
return list(set(res))
googleResults: dado un lenguaje devuelve el número de resultados que tiene en Google
def googleResults(lang):
query = lang + ' programming language'
URL = 'https://www.google.es/search?q=' + quote_plus(query)
html = requests.get(URL).text
soup = BeautifulSoup(html, 'html.parser')
div = soup.find('div', id='resultStats')
return int(''.join(re.findall(r'd+', div.text.split()[1])))
nodes: pasándole las aristas, esta función devuelve los nodos del grafo junto con el número de resultados de cada lenguaje.
def nodes(edges):
langs = list(set([lang for edge in edges for lang in edge]))
return [(lang, googleResults(lang)) for lang in langs]
toCSV: crea un CSV a partir de una lista.
def toCSV(path, rows, header):
with open(path, 'w', newline='') as fh:
writer = csv.writer(fh)
writer.writerow(header)
for row in rows:
try:
writer.writerow(row)
except:
pass
Main
Obtenemos las aristas y los nodos del grafo
e = edges()
n = nodes(e)
Por último escribimos estos resultados en un CSV
toCSV('C:\Users\marco.canora\Desktop\edges.csv', e, ('Source', 'Target'))
toCSV('C:\Users\marco.canora\Desktop\nodes.csv', n, ('Id', 'Results'))
Ahora que tenemos los datos, pasamos a cargarlos en Gephi. Tras procesar el grafo con algunos métodos del propio programa, el resultado es el siguiente:
Para el lenguaje Python (el padre de muchos otros), las relaciones son las siguientes:
En este apartado dejaremos a un lado el problema original para mencionar otros casos de uso. A nosotros se nos han ocurrido estos:
- Extraer las respuestas del Twitter de Sothis (@sothis ¡Seguidnos!) para realizar sentiment analisis y ver lo que la sociedad opina de nosotros.
- Monitorización de los precios de la competencia.
- Extraer noticias de periódicos digitales para observar nuevas tendencias, encontrar noticias relacionadas sobre un tema… Esto estaría acompañado de técnicas relacionadas con el procesamiento del lenguaje natural (NLP, en inglés).
Esperamos que este artículo os haya resultado de interés, en innovación estamos ansiosos por mostraros nuestra capacidad y os garantizamos que escribiremos nuevos posts pronto.
¿Quienes somos?
El equipo de innovación nació de un esfuerzo de Sothis para adaptarse al mundo moderno, uno cuya moneda de cambio son los datos. Lo que ofrecemos al cliente es conocimiento a través de la explotación, análisis y correlación de sus datos con otras fuentes de información externas.