“WEB SCRAPING” CON PYTHON

En este post voy a hacer una pequeña práctica de ‘web scraping’, que sería un análisis web con python de la estructura html y como poder extraer diferentes datos.

La idea concreta es buscar alguna página con datos publicados sobre algún tema. En un pricipio iba a usar la página del INE (instituto nacional de estadística), pero la estructura del árbol html me dio algunos problemas con algunos tags y no podía extraer toda la información de las tablas. Igual cuando empecé, hace unos cuatro días, me faltaba alguna dato o conocimiento de como navegar bien por las etiquetas, puesto que primero encontraba la tabla buscándola por la clase “general” (és el nombre de la clase en todas las tablas del INE que he visto), y una vez la encontraba, accedia al subtag llamado tbody (que contiene el cuerpo de la tabla, sin las cabeceras) y este tiene todas las filas guardadas con los tags “tr” y estos contenían los datos de cada línea con el tag “td”, y de los datos que extraía, me faltaban algunos td’s, putos td’s de mierda, entoces yo aquí con mi poca paciencia busqué otra fuente de información como MarketWatch que proporciona datos sobre el mercado de valores, pero al ser un tem del que no controlo pensé que me sería más complicado desarroyar esto. Entonces al final topé con la wikipedia, y en concreto con una sección en la que tiene diferentes url’s con los datos de los atentados que hubo en el mundo en los últimos 40 años: https://en.wikipedia.org/wiki/List_of_terrorist_incidents_in_February_2019.

Y abajo de todo, en esa web, hay otra tabla en la que todos los años de los que se tienen registros de incidentes terroristas, no vamos a usar todos ya lo adelanto.

No es el principal tema que había pensado, ya que es delicado, pero como en la wikipedia me gustaba su forma de estructurar las tablas, probé y pude extraer mejor la información, decidí usarla para probar este tipo de uso de python con grandes cantidades de datos, no demasiadas en este ejemplo, hay bases de datos muy grandes en comparación y otras webs, pero también digo que mi ordenador tampoco es una patata y las últimas comparaciones (en concreto solo los últimos cuatro años) me tardaban en compilar y ejecutar (python es un lenguaje interpretado, hace las dos con única orden y casi al mismo tiempo) unos 30 segundos, aunque es cierto que esta lentitud era debida a las diferentes peticiones a las web, lo cual ralentiza mogollón el proceso de elaborarlo.

Último inciso en lo de las tablas:

 

 

– supongamos que este es Juan, Juan cayó un poco de cabeza al nacer y se enfadó con el mundo, entonces, ya él en su plenitud, decide que la mejor forma de joderlo será o fingir un brote de canibalismo y empezar a comer gente por la calle, o aprender a hacer MAL tablas, y que con suerte le fiche el INE, para hacer sus tablas, que su legado se expanda a la vez que aterra. Entonces tiró una moneda y salió la B, la opción 2, entonces yo tuve que usar la wikipedia. –

Como partida uso Uso Ubuntu 18.04.2, una distribución linux, de 64 bits, y mi editor de texto será sublime text, me parece cómodo y te remarca algunas palabrejas (como todos pero bueno…). La versión de Python será la 2.7, es verdad que hace ya más de diez años que se empezó a desarrollar python 3 y actualmente no se si irán por la versión 3.8 ya casi. También que pyhton 2.x dejará de tener soporte no en mucho tiempo. Aún así para el tamaño del programa tampoco sería demasiado complicada la migración a un python 3.6 por ejemplo (el que tengo instalado ahora también) principalmente cambiar que print se tratará ahora como una función de verdad, es decir, recibe sus parámetro entre paréntesis, bastaría con añadirle paréntesis, cosa que ya le puse porque funciona igualmente en esta versión 2.7, sólo que también saca los paréntesis por consola, que no es agradable pero tampoco demasiado incómodo. Tipo long pasa a ser un int, no se que cambios de los diccionarios y algunas cosas más con las excepciones, de las cuales tampoco hago uso. No es tampoco para un uso directo con un usuario, si no de obtención y simplificación de datos. Es objetivo en si serían los datos, tratamiento de grandes datos, el programa es sólo el medio.

Intentaré que el código sea bastante claro y simple, siguiendo convenciones y estándares de documentos de python, no en todo obviamente, pero si en lo más básico. Primero, ya que python carece de llaves para agrupar funciones o bucles, lo que usa es la identación, pues esta se hará con espacios (NO tabulaciones), y agrupados de cuatro en cuatro. Tampoco realizar múltiples asignaciones en la misma línea, ni dejar espacios en blanco por doquier, y entre funciones usar un sólo espacio. Los nombres de las clases serán con notación CamelCase: ‘nombreClase’, pero eso da igual puesto que no me ha hecho falta usar clases. Y en las funciones y variables usaré barra baja para separar las palabras de su nombre: ‘nombre_funcion’.

Un apunte sobre las tablas de la wikipedia. Por ejemplo en este caso las tablas desde el año 2015 las url’s engloban los datos de cada mes, y además tienen una estructura excatamente igual, lo que simplifica muchisísimo el trabajo. antes de 2015 se agrupaban por cada cinco meses mas o menos y antes de 2010 cada año, alguna de estos años tambien se pudo analizar con alguna columna menos (con el mismo programa me refiero, siempre se puede hacer uno concreto para otra url concreta, pero lo ideal es que uno te sirva para lo máximo posible).

La primera función es descargar_pagina(url), que como se ve recibe una url y haciendo uso de la librería ‘urllib2’ usa el método urlopen para abrir la página web y devolviendo el arbol html. Hay diversos ejemplos y está bastante estandarizado el uso de las librerías requests (para hacer la petición GET a la página), y beautifulsoup (que sirve para analizar y navegar por el árbol html de la página descargada). A pesar de que parecían más intuitivas he usado las otras dos: urllib2 y lxml.html (sin complementar con la beautifulsoup), puesto que son las que nos relacionaban en un ejemplo en clase, y así ya voy trasteando algo con ellas.

La función devolverá el tag raiz a través del método getroot(). Ahora apoyandonos en la función extraer que recibe algo de tipo htmlElement es decir un tag de html, y le pasamos el obtenido anteriormente.

def descargar_pagina(url):

parsed = html.parse(urllib2.urlopen(url))

return parsed.getroot()

def extraer(doc):

tabla = doc.find_class(“wikitable”)

print(“tabla —>”, len(tabla), tabla, type(tabla))

body = tabla[0].findall(“.//tbody”)

print(“body —>”, len(body), body, type(body))

filas = body[0].findall(“.//tr”)

print(“filas —>”, len(filas))

array = []

for f in filas:

elements = f.findall(“.//td”)

for e in elements:

array.append(e.text_content().strip())

return array

Una vez con esto vamos a acceder a la tabla que nos interesa, y haciendo uso del conocimiento de la estructura del html de la página (opción proporcionada por el navegador), podemos ver que la tabla esta en un tag llamado ‘table’, pero como tienen más de un tag ‘table’ la web, lo vamos a extraer por el atributo ‘class’ ‘wikitable sortable jquery-tablesorter’. Una vez obtenida ya podemos acceder al cuerpo en el tag ‘tbody’, y a su vez a cada filas, guardada con el tag ‘tr’, que cada una contendrá ocho tags ‘td’ con los ocho datos de cada fila contiene:

 

 

Ahora el siguiente paso supongo que es fácil de ver. Extraer los datos que queramos analizar de cada columna de la tabla, y en este caso voy a introducirlos en listas, recalco que al utilizar python, que es un lenguaje muy abierto en el sentido que no hace falta definir el tipo de las variables, simplemente les asignas valores y traga con todo, esto es muy cómodo, y más en las listas que no tienen que ser de un tipo definido, si no que puede ser que una misma lista contenga strings, ints, booleans o incluso otra lista.

En la primera extracción de los datos a las listas los pasa todos como strings (str), pero más adelante esta ventaja se notará sobretodo en la columna dead puesto que mezcla ints con strings.

Las columnas que pensé que sería más útil comparar fueron date, dead, location y perpetration, por lo que hice una función para cada una que devuelva una lista con los datos correspondientes. Un primer apunte importante para luego comparar, és que al ser de la misma tabla la longitud de las listas será la misma. Ejemplo de una función para crear la lista donde:

def donde(lista):

a=0

t = []

for i in lista:

if (multiple_rest(a,8) == 4):

t.append(i)

a = a + 1

return t

Lo que recibe la función es la tabla con los datos extraídos, contenidos elemento a elemento en una lista. Igual no era la mejor manera puesto que es una lista enorme y con poco orden en los datos, y por ejemplo justo ahora se me está ocurriendo que en la propia función extraer() podría haber devuelto ya las listas simplemente haciendo uso de un contador, pero bueno ahora ya hace cinco días que he empezado y no se me ocurrió pero tal y como está ahora es exactamente igual de válido. Hago uso de una función auxiliar multiple_rest(x,y) que devuelve el resto de una división, y esto nos es útil porque si nos fijamos en la lista , cada ocho elementos empieza una fila nueva, entonces gracias a esta lógica en la estructura, obteniendo el resto de dividir la posición actual al recorrer la lista entre ocho, sabemos a que columna pertenece. Segundo apunte importante para posteriormente comparar datos, las lista están ordenadas exactamente igual que en la tabla original, que es un orden cronológico, las ordena por días.

El siguiente paso es pensar que datos nos puede ser interesante comparar directamente, por ejemplo estamos orientando esto a la extracción en un sólo mes de un sólo año, que ya adelanto que desgraciadamente son muchísimos y hasta va a haber que reducir el tamaño de las gráficas. También en la comparativa por ejemplo con tablas de los años 70, 80 y 90 pues estas son bastante más pequeñas, pero sin saber mucho de esto creo que esto podría no deberse al número real de atentados realizados, si no a la facilidad de obtener información en los últimos años. Por lo que haré comparativas con tablas de este año o el pasado por ejemplo, contando que estoy escribiendo esto a 7 de marzo de 2019.

Y bien los datos que se valorarán en las dos primeras gráficas serán el número de atentados y el número de muertos por cada grupo terrorista, reitero que es un tema escalofriante y nada agradable, pero bueno hay gente se dedicará profesionalmente a manejar estos datos y realmente es necesario hacer estudios estadísticos, ya no de esto, si no de TODO en la vida si se quiere destapar los problemas reales, es la base para después sacar conclusiones y teorías. En eso ya no me meto, simplemente elegí este tema sin tener conocimiento previo y fue algo casi aleatorio, me era más fácil el manejo de tablas, y como total es un tutorialillo simple, nada que ver con procesos que realmente extraen cantidades realmente grandes de datos y con garantías de fiabilidad. Pero bueno en realidad me fió de la wikipedia, yo creo que todos la hemos usado más de una vez y nos hemos fiado y usado sus datos y sus fuentes, y viendo que siga una mínima coherencia, pues a tope con la wikipedia veña.

La tercera y cuarta gráfica serán lo mismo, número de atentados y muertos, pero esta vez por cada ciudad. Ya digo que un experto lo haría mejor, y he pensado en más datos aparte que estos y seguramente podrían influir a la hora de valorar, por ejemplo la última columna, que no uso, sería la que dice en que contexto tiene ese atentado, es decir si forma parte de alguna guerra o conflicto en un país o región, puesto que es más probable un atentado en estas condiciones que en un país en el que se viva una época de paz. Otra columna que no uso es la de ‘injured’, y no es que no tenga repercusión, obvio que la tiene, es más el mero hecho de no alargar con gráficas y gráficas esto y porque también usar matrices de tres listas ya era bastante para representar como para añadir más listas, complicando así las gráficas, que aparte no tenía conocimiento de como crear estas y decidí no usar el mismo formato, con barras. Prácticamente iguales, sólo cambiando los datos.

Más adelante haré una segunda iteración del programa en la que compararé los datos de los últimos cinco años mes a mes, puesto que las progresiones cronológicas es de lo más común que se suele encontrar uno si busca gráficas por ahí. Pero sin más dilación ahora sigamos con esta primera iteración.

Una vez que tenemos las listas que vamos a querer a usar, pensé que sería buena idea agruparlas en una matriz para ordenar los datos::

def matriz_quien_dead(list_quien, list_dead):

dic_quien = {}

for l in list_quien:

if ((l in dic_quien) == True):

dic_quien[l] = (dic_quien.get(l) + 1)

else:

dic_quien[l] = 1

 

x = 0

for i in list_dead:

if ((list_quien[x] in dic_quien_dead) == True):

dic_quien_dead[list_quien[x]] = (dic_quien_dead.get(list_quien[x]) + list_dead[x])

else:

dic_quien_dead[list_quien[x]] = list_dead[x]

x = x + 1

x=0

m_quien_dead = [[‘WHO’],[‘TIMES’],[‘DEAD’]]

for i in dic_quien:

for x in range(0,(len(dic_quien)-1)):

if i in m_quien_dead[0]:

None

else:

m_quien_dead[0].append(i)

m_quien_dead[1].append(dic_quien.get(i))

m_quien_dead[2].append(dic_quien_dead.get(i))

return m_quien_dead

Por ejemplo esta es la primera función para crear una matriz de que contiene tres listas, quien ha perpetuado el atentado, el número de veces que lo ha hecho y el número de víctimas. En esta última columna he de decir que alguna vez muy muy muy escasa aparece unkown, osea que no se tienen datos, por lo que lo he cuantificado como cero, más que nada porque para operar enteros, un requisito es que ambos sean del mismo tipo, enteros (obviamente se puede permutar entre floats), pero si no, dará error. En algunas columnas aparece el (+x) que también he obviado para posteriormente convertir los datos en ints, y Vendrían representando los terroristas que fueron victimas mortales o heridos. Ni siquiera la wikipedia los ha incluido en el número, yo tampoco, y bueno una víctima siempre es serio da igual quien sea, pero no está justificado realizar estos actor ni siquiera por causas justas, siempre hay otras vías, y por encima si se mira un poco por encima las descripciones encuentras la palabra civiles no un número bajo de veces, que realmente son las víctimas más injustas que puede haber (da igual que se hayan ocasionado por ataques no dirigidos a ellos, no justifica nada), y no tienen igual de condiciones ni de poder para hacer frente a estos ataques, es ir a lo fácil. Ataca a un gobierno o a un ejército, que por encima son los responsables de que se este viviendo un conflicto, no a la gente normal (pero bueno como digo que nadie ataque a nadie por dios…).

Siguiendo con la propia función lo primero (los dos primeros bucles) vamos a agrupar el quien y el cuantos atentados por un lado, y el quien y el cuantas víctimas por otro, en dos diccionarios. Aquí si que he visto como ideal el uso de diccionarios, puesto que son agrupaciones de valores con la lógica clave-valor, en la cual nunca puede haber dos claves iguales, cosa que nos interesa, (valores si que puede haber repetidos), y los datos se pueden filtrar por clave y actualizarlas fácilmente, él sólo ya se encarga de mirar de si la clave accedida existe, y actualiza su valor, o crea una nueva. Una vez hechos los diccionarios, recorremos uno, da igual cual porque los diccionarios tienen el mismo tamaño entre sí, no es igual al de las listas puesto que aquí agrupamos los comunes, pero como rellenamos con diccionarios únicamente, da igual. Con tal de que sean consistentes entre sí es suficiente para no desordenar los datos. La matriz resultante, la que retornará la función, tiene en la primera lista el nombre del grupo terrorista, en la segunda el número de atentados de todo el mes, y en la tercera el número de víctimas totales.

Bueno una vez obtenida la matriz, se podría representar ya en una gráfica, pero en este caso tenemos 52 filas de datos, y si nos fijamos, muchas de ellas tienes unos valores de 0, 1, 2 y 3 para las listas de atentados y muertos, mientras que otras manejan valores de veinte veces más grandes en tamaño. Si me hubiesen cabido las hubiese representado en su totalidad, y seguro que existe alguna forma elegante de representarlos todos en vez de las barras, pero digamos que no ha sido mi fuerte mirar demasiado la librería matplotlib. He optado por ordenar la matriz entorno a la lista dead y quedarme con los valores más altos, para representarlos.

Aquí reconozco que ha sido la única función que no me ha salido. Por lo que busqué algún pseudocódigo por ahí y lo adapte para matrices, porque recordemos que si cambio un elemento de posición en una lista, tengo que cambiar los de las otras listas a la misma posición, porque la clave de esto que no mezclar datos y que sigan siendo consistentes. Esto se debe a que he decidido mejor por no optar por algoritmos que intercambien elementos adyacentes como son la ordenación por inserción o selección, que rondan tiempos de una complejidad temporal de O(n^2), que en listas muy grandes acabarán pasando factura puesto que una lista de n elementos la acaban recorriendo n veces cada elemento, por eso el n^2. Ya que van comparando con los elementos que tienen inmediatamente al lado. Entre otros que pude elegir estaba el quicksort, que es si no el más famosillo, se basa en ir dividiendo el vector en dos, manteniendo un pivote en medio, y ordenarlos por separado, como si de listas más pequeñas se tratase y así sucesivamente. Muy parecido a este es el de fusión, ambos basados en la técnica divide y vencerás, pero en este caso no hay pivote y la ordenación se produce a la hora de fusionar las listas, darse cuenta que clave de esto es que cuando la divides tanto que llegas a una lista pequeña (tres, cuatro, cinco elementos los que uno considere), pues vas recorriendo ambas listas y fusionándolas en otra que contenga las dos listas pequeñas, pero ordenada. Sería como el algoritmo de inserción, pero si nos fijamos las listas cada vez que son más grandes, van a estar más ordenadas, y una característica de inserción es que da buenos tiempos para listas casi ordenadas. Estos dos los descarte porque si bien creo que llegan a mejorar al Shell, o al menos para listas bastante desordenadas, en las que Shell flojea con tiempos cuadráticos O(n^2), es verdad que en la complejidad espacial Shell es mejor ya que en estos hace falta hacer uso de listas más pequeñas independientes cuando estas se dividen sucesivamente, mientras que con Shell puedes ir ordenando en la propia lista original, cosa que me ha beneficiado mucho teniendo en cuenta que trabajo con una matriz con tres listas, y los cambios de una se deben ver reflejados en las otras como dije anteriormente, por lo que aquí con una sencilla función intercambiar(), que el único espacio a mayores que usa es una variable auxiliar por cada lista en cada intercambio, funcionaría. Otro sería el de ordenación por montículos, que usa montículos para ir subiendo nodos y recolocándolos en el montículo, como los anteriores tendría complejidad O(nlogn) y quizá sea el que tengo más olvidado.

El algoritmo por el que me decanté fue el Shell, concha, como las gasolineras:

## SHELL:

def ordenar_matriz(m_quien_dead):

frontera = 2

incremento = len(m_quien_dead[0]) / 2

# incrementos: 25, 23, 21, 19, 17…

while (incremento > 0):

for inicio in range(0,incremento):

for i in range(inicio+incremento, len(m_quien_dead[0]), incremento):

posicion = i

valor_actual = m_quien_dead[2][i]

while(posicion >= incremento) and (m_quien_dead[2][posicion-incremento]

intercambiar(m_quien_dead,(posicion-incremento),posicion)

incremento = incremento – 2

Puede que no me explique bien porque es algo lioso explicarlo sin dibujarlo, pero lo que haría sería a partir de unos incrementos, que serán la separación entre los elementos que se van a comparar, ir comparando los elementos siguientes uno a uno manteniendo distancias proporcionales a este incremento, de manera que si el de mas atrás es más bajo, intercambiarlo. Ejemplo, lista de 50 elementos, incremento actual de 25, se comparará el elemento 0 con el 25, el 26 con el 1, el 27 con el 2, y así continuando la sucesión hasta completar el incremento. En este caso quiero ordenarlos de mayor a menor, si fuera al revés, es cambiar un > por un < y listo. En fin buscadlo por ahí porque me parece que de poco ha servido explicarlo. En este caso primero probé reduciendo los incrementos de mitad en mitad, pero no quedaba demasiado bien ordenado, si nos fijamos cuantos más incrementos haya más iteraciones y por lo tanto más ordenado va a quedar, por lo que en vez de dividir, fui restando de dos en dos (mirar la sucesión del comentario) me dio una matriz casi ordenada. Puede ser que haya cometido algún pequeño fallo a la hora de desarrollar el algoritmo, por eso no ordena del todo, pero para lo que voy hacer quedó suficientemente ordenado:

 

 

Como se ve en la imagen, en la tercera columna, que es por la que han sido ordenados, pues no está ordenado del todo, pero si se puede considerar que va siguiendo alguna especie de progresión decreciente: 142, 114, 130, 69, 29, 63, 29, 46, 28, 29, 14, 24, 12, 18, 9…

Podría haberlo ordenado mejor, total por tiempo en este caso no será, me tarda milisegundos, son listas de 50 elementos nada más, pero a la hora de representar gráficas con barras la verdad es que quedaba bien no tenerlos perfectamente ordenados, ya se verá.

Voy a poner el código principal de la primera iteración, yo le llamé primer_raspado() (scraping = raspado, en la primera entrada de google), y así nos ponemos otra vez en contexto:

def primer_raspado():

#url = ‘https://en.wikipedia.org/wiki/List_of_terrorist_incidents_in_January_2017′

#anho=’ 2017 ‘

#mes=’ Enero ‘

#url = ‘https://en.wikipedia.org/wiki/List_of_terrorist_incidents_in_February_2017′

#anho=’ 2017 ‘

#mes=’ Febrero ‘

url = ‘https://en.wikipedia.org/wiki/List_of_terrorist_incidents_in_February_2019′

anho=’ 2019 ‘

mes=’ Febrero ‘

#url = ‘https://en.wikipedia.org/wiki/List_of_terrorist_incidents_in_March_2019′

#anho=’ 2019 ‘

#mes=’ Marzo ‘

document = descargar_pagina(url)

lista = extraer(document)

list_dias = dias(lista)

#print(list_dias)

list_tipo = tipo(lista)

#print(list_tipo)

list_dead = dead(lista)

#print(list_dead)

list_quien = quien(lista)

#print(list_quien)

list_donde = donde(lista)

#print(list_donde)

print(“longitud listas —> “, len(list_dias), len(list_tipo), len(list_dead), len(list_quien), len(list_donde))

graficas_quien_dead(list_quien, list_dead, anho, mes)

graficas_donde_dead(list_donde, list_dead, anho, mes)

El código entero seguramente lo suba a github o algo y dejaré por ahí en enlace, aún no lo hice pero creo que es lo más cómodo.

Son las dos últimas funciones las que se encargan de crear la matriz a partir de las listas y ordenarlas, y tambien llamarán a otra función a su vez, que será la que haga las gráficas:

def grafica_quien(m, anho, mes):

plt.title(mes + anho)

plt.xlabel(“numero de atentados”)

plt.barh(m[0][1:16], m[1][1:16])

plt.show()

Por ejemplo esta es una de ellas, ya dije que las gráficas serían lo más simple y claras posible.

Representaré los nombres en el eje vertical ‘y’, puesto que así caben mejor. Como podéis ver mostraré desde el elemento uno (el cero és el título) hasta el 16 (por ejemplo) ya que de ahí en adelante los valores de los datos no pasan de 10. Aunque a ver como quedan cuando suba esto por que claro habrá que reducir la imagen y eso pero bueno, si no pongo hasta el doce o así pero malo será.

Por ejemplo esta será la salida para para la tercera gráfica de la función primer_raspado( ):

 

Febrero de 2019, en principio elegí una fecha aletoria y después probé con esta que es el último mes más cercano, y me siervió para mostrar un ejemplo. Se ve que Somalia suma diez atentados, casi tanto como el resto de paises juntos, entre ellos Nigeria, la cuidad de kajuru en concreto

Ahora miramos la cuarta gráfica que saca:

 

En cambio aquí vemos que Nigeria tiene un total de casi doscientas muertes, mientras que somalia, la que más atentados tuvo, tiene cincuenta, cuatro veces menos. Y nada puede llamar la atención entones fui a mirar a la tabla de la wikipedia de ese año y se aprecia que hubo un conflicto en concreto que tenía 142 y marcaba la casilla en rojo destacándola:

 

 

No se que pasa en esos dos países, pero no me hubiera imaginado tal catástrofe estuviera ocurriendo estos dias atrás.

 

En el caso del perpetuador, en la mayoría de los meses se ve que tiene bastante más repercusión en comparación con los otros el estado islámico. Complementándose con los de estado islámico (sospechoso), no se cuanto de sospechoso o de claro esta en estos casos pero sumándolo a lo otro da una diferencia más clara todavía.

 

 

En cambio vemos que el grupo and Adara militia es el que más muertos abarca, seguido de los talibanes y de tercero aún el estado islámico.

Ahora vamos a ver lo que sería el segundo_raspado(), en que vamos a automatizar el pricipio del primer_raspado y meterlo en una función:

def count_dead_month_year(url):

document = descargar_pagina(url)

lista = extraer(document)

list_dead = dead(lista)

print(list_dead)

return count_list(list_dead)

Recibiendo toda la url, ya hace todo el proceso, y esto lo hacemos porque de esta manera podemor meter esta función dentro de un bucle y llamarla una vez por cada mes de cada año desde 2015:

def segundo_raspado():

url = ‘https://en.wikipedia.org/wiki/List_of_terrorist_incidents_in_’

list_month = [‘January_’, ‘February_’, ‘March_’, ‘April_’, ‘May_’, ‘June_’, ‘July_’, ‘August_’, ‘September_’, ‘October_’, ‘November_’, ‘December_’]

list_years = [‘2015’, ‘2016’, ‘2017’, ‘2018’, ‘2019’]

list_month_grafic = [‘E’, ‘F’, ‘MR’, ‘AB’, ‘MY’, ‘JN’, ‘JL’, ‘AG’, ‘S’, ‘O’, ‘N’, ‘D’]

matriz = [[‘Year-Month’], [‘TIMES’],[‘DEAD’]]

for i in list_years:

x=0

for j in list_month:

if ((i == ‘2019’) and (j == ‘April_’)):

print(“LLegamos a la fecha actual”)

break

urli = url+j+i

print(‘urli —> ‘, urli)

times, count = count_dead_month_year(urli) # aqui la llamamos!

if j == ‘January_’:

matriz[0].append(list_month_grafic[x]+i[2:])

else:

matriz[0].append(list_month_grafic[x])

matriz[1].append(times)

matriz[2].append(count)

x=x+1

for i in range(0,(len(matriz[0])-1)):

print(matriz[0][i], ‘ – ‘ , matriz[1][i], ‘ – ‘ , matriz[2][i])

grafica_month_year(matriz)

grafica_month_year_dead(matriz)

Bueno aquí ya con toda la función vemos que recorremos dos bucles de strings que son los meses y los años, para así despues poder montar la url completa, anidando strings, y pasársela a la función count_dead_month_year() para así obtener el número de atentados y víctimas por cada año, haciendo diferentes consultas a la página.

 

 

Esta espero ponerla lo más grande posible porque abajo puede ser lioso. Pongo la inicial de cada mes, en las que son iguales pongo dos, y en enero marco el año del que se trata 2015, 2016, 2017, 2018 y 2019. Apreciándose una subida hasta estos meses, que parece que como mínimo se va a mantener, siendo enero y febrero de este año, sobretodo enero, de los meses con más atentados. Recalcar que en marzo, el mes actual, estamos a día 8 a las 00:30 que me encuentro acabando esto, que es el mismo día relamente, pero un poco más tarde que lo que escribí antes que estaba a 7 de marzo de 2019, que en realidad escribí casi todo, osea el artículo me llevo un rato de dos tardes, lo que me llevó cuatro días realmente fue el código. Así suena mucho pero tampoco le dediqué demasiado tiempo del día, ratos libres, aún así fue una semana bastante relajada, estando de baja siempre se descansa mejor ;).

A ver, la siguiente gráfica hace la progresión esta vez contando las víctimas:

 

 

 

Y bien se aprecia en esta última gráfica que a pesar de que hay más atentados en los dos últimos años, es el 2016 cuando hay más víctimas.

Pues por ejemplo los atentados de París de noviembre de 2015, que aquí tuvieron mucha repercusión, se aprecia que en ambas gráficas son de los datos más bajos en los último cinco años en todo el mundo.

Venga última gráfica ya y termino. Esta es la primera que que sale con la tabla de 1970:

 

 

La mayoría de los países en los que se produjo algún atentado son de América y Europa y no había tantos grupos terroristas provinientos de la países islámicos. Entre otros países que dieron cuna a grupos que cometiron atentados en la época: Argentina, chile, EEUU, Uruguay, Canadá o Colombia, o europeos como irlanda, la mayoría actuando en su propio territorio nacional. Sin embargo el mayor número de muertos son de nacionalidad suiza. El grupo que lo hizo es de origen Palestino, militares por la liberación de Palestina, que no es que fuesen hasta Suiza, si no que tenían disparadores barométricos, yo no sabía que eran, pero resulta que pueden hacer detonar una bomba al llegar a cierta altitud con un radar. Lo usaron en un avión. El vuelo, con la mayoría de Suizos dentro, se estrelló cerca de Zurich.

Bueno por fin acabo esto, a ver si lo subo mañana o pasado y me acuerdo de subir el código a Github o donde vea. Pondré una canción de fondo, que siempre me mola, no sé si alguna de las que escuché estos días que estuve más en casa. Para concentrarse mejor escuchar música suave de fondo pero a mi me da igual yo os pongo la mierda que he escuchado y que me sirvió igual o más, a volumen bajito en todo caso. Estaba entre ‘salgo a la calle’ – de los electroduendes, o ‘Navajazos por un chándal’ de el último ke zierre. Ni idea de como se ponía la música pero le preguntaré al administrador Dr. Pach, que para eso le pagamos. No, era broma, aquí nadie paga a nadie.

Yo estoy todo pajarito y ve voy a dormir ya. Boas noites.

Pd: ya tenía cuenta de github , no me acordaba, y acabo de crear el repositorio:

https://github.com/pinflamingos/web_scraping_python.git

Pink Flamingo

 

Relacionado

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Orgullosamente ofrecido por WordPress | Tema: Baskerville 2 por Anders Noren.

Subir ↑