por Erick Palacios, Roberto del Río y Sergio Pereo
Durante el último año hemos colaborado con el Centro ITAM Datos + Algoritmos + Sociedad, que tiene como objetivo analizar las imágenes utilizadas en las campañas de concientización del cambio climático.
Para esto utilizamos la herramienta BeautifulSoup¹. La principal fuente de información fueron bancos de imágenes, sin embargo se excluyeron las páginas: Greenpeace², FOEI, Fridays for Future y ShutterStock³.
Finalmente se trabajó con las páginas de la NASA, Minet y la página de perfil de 350org en la red social Flickr para extraer imágenes. Las bibliotecas de Python empleadas para este proyecto fueron BeautifulSoup, Flickr API, Minet, OS, Argparse, Pandas y urllib.request.
Bibliotecas OS y argparse
Las bibliotecas que se utilizaron fueron OS, y argparse y bibliotecas fueron implementadas en todos los códigos creados.
Con los siguientes comandos se puede correr el programa desde la terminal de la computadora:
parser = argparse.ArgumentParser(description=»)
parser.add_argument(‘-c’, ‘–csv’, type=str, help=»)
parser.add_argument(‘-d’, ‘–dir’, type=str, help=»)
parser.add_argument(‘-l’, ‘–limit’, type=int, help=»)
args = parser.parse_args()
Se debe insertar el siguiente comando en la terminal para poder correr el programa:
python3 nombre_archivo.py -d <lo que se pide ‘-d’> -l <lo que se pide ‘-l’> -c <lo que se pide ‘-c’>
Ambas bibliotecas permiten crear directorios y movernos en ellos para tener un mejor orden de las descargas y agrupar las imágenes en directorios diferentes.
os.chdir(«..»)
working_directory = os.getcwd()
if not os.path.exists(args.dir):
os.makedirs(args.dir)
wdif = working_directory + «/» + args.dir
os.chdir(path=wdif)
os.mkdir(‘ ‘)
NASA
Obtener imágenes de la página de la NASA fue muy sencillo, ya que no utiliza JavaScript. Las librerías usadas para este programa fueron BeautifulSoup, OS, argsparse y urllib.request. Para poder utilizarlas, es necesario descargar BeautifulSoup mediante el siguiente comando:
pip install beautifulsoup4
Una vez instalada, se pone el código muy parecido al utilizado en la sección de OS y argarse.
parser = argparse.ArgumentParser(description=’Scrap NASA!’)
parser.add_argument(‘-d’, ‘–dir’, type=str, help=’Directory name to use for saving the results’)
parser.add_argument(‘-l’, ‘–limit’, type=int, help=’Max quantity of pages, right now max is 30′)
args = parser.parse_args()
if args.dir is not None and args.limit is not None:
Creamos los directorios para tener un mejor orden de los datos. Además, creamos el documentos.csv, en el cual se obtienen los urls de las imágenes, la fecha en la que se subió el artículo que contiene la imagen y el título del artículo.
num_pags=args.limit
os.chdir(«..»)
working_directory = os.getcwd()
if not os.path.exists(args.dir):
os.makedirs(args.dir)
wdif = working_directory + «/» + args.dir
os.chdir(path=wdif)
array_terminations=[«jpg»,»jpeg», «gif», «png»]
array_images=[]
filename = «reporteNASA.csv»
f = open(filename, «w»)
headers = «img_url, date, title\n»
f.write(headers)
os.mkdir(‘images NASA’)
Después, mediante el uso de las bibliotecas urllib.request y BeautifulSoup, insertamos el link deseado con un contador dentro de un ciclo for para poder ir cambiando de páginas principales; usamos comandos de urllib.request para ingresar a las páginas y, dentro de la página, utilizamos BeautifulSoup para obtener la información de los headers requeridos dentro del código html de la página web. Cuando encontramos los headers deseados, insertamos en el .csv creado la información requerida y, posteriormente, el nombre de la imagen es guardado en un array.
for i in range(num_pags):
try:
my_url=’https://climate.nasa.gov/ask-nasa-climate/’+»?page=»+str(i+1)
uClient=uReq(my_url)
page_html = uClient.read()
uClient.close()
page_soup=soup(page_html, «html.parser»)
containers = page_soup.findAll(«article»,{«class»:»blog_entry»})
for container in containers:
title = container.a.text
date = container.span.text.strip()
article_url=»https://climate.nasa.gov»+container.a[‘href’]
subuClient=uReq(article_url)
subpage_html = subuClient.read()
subuClient.close()
subpage_soup=soup(subpage_html, «html.parser»)
subcontainers = subpage_soup.findAll(«figure»)
for subcontainer in subcontainers:
try:
img=»https://climate.nasa.gov»+subcontainer.img[‘src’]
f.write(img+ «,»+ date.replace(«,»,» «).replace(«\n», » «)+»,» +title.replace(«,»,» «).replace(«\n», » «) + «\n»)
array_images.append(img)
except:
pass
except:
pass
f.close()
Para terminar, creamos un ciclo para acceder a los nombres de las imágenes guardadas dentro del array creado. Luego cambiamos de directorio al generado en la sección de creación de directorios e hicimos la descarga de la imagen con la biblioteca urllib.request.
for image in array_images:
name=image.split(‘/’)[-1]
if not name.split(«.»)[-1] in array_terminations:
name=name+».jpg»
os.chdir(path=wdif+’/images NASA’)
img_data = requests.get(image).content
with open(name, ‘wb’) as handler:
handler.write(img_data)
os.chdir(path=wdif)
Finalmente, para poder usar el código mediante la terminal ejecutamos la siguiente línea:
python3 scrap_nasa.py -d <directorio> -l <número límite de imágenes>
En donde:
– d se pone el nombre del directorio a crear.
– l límite de albúmenes a descargar.
Como resultado de esta ejecución se crearon dos carpetas: una con el nombre del directorio dado en la línea de ejecución, y otra con las imágenes y un archivo .csv con el URL, fecha, título del artículo de donde se obtuvo la imagen.
Flickr
Flickr es una red social que se especializa en la subida de fotos sobre diversos temas. Decidimos explorar esta red social, ya que la página de 350org nos referenciaba a esta herramienta porque ahí es donde suben las fotos de sus campañas. Flickr facilita la obtención de datos mediante la creación de una biblioteca de Python llamada flickr_api. Además, utilizamos pandas, OS, argsparse y urllib.request. Para usar la librería flickr_api y pandas es necesario hacer su instalación.
pip install flickr_api
pip install pandas
Una vez instaladas, es necesario obtener una api key y una api secret que se obtienen en Flickr API key. Las pusimos en un archivo .csv. Luego las usamos como argumento en la terminal para leer ese archivo y ejecutar el código.
Para empezar, empleamos un código parecido al de la sección de OS y argparse y la NASA:
parser = argparse.ArgumentParser(description=’Scrap Flickr!’)
parser.add_argument(‘-c’, ‘–csv’, type=str, help=’csv file with keys’)
parser.add_argument(‘-d’, ‘–dir’, type=str, help=’Directory name to use for saving the results’)
parser.add_argument(‘-l’, ‘–limit’, type=int, help=’Max quantity of albums right now max is 249′)
args = parser.parse_args()
if args.csv is not None and args.dir is not None and args.limit is not None:
Posteriormente, como en la NASA, creamos los directorios para tener una mejor organización de los datos y guardamos en un dataframe las claves api para acceder a las herramientas de la biblioteca flickr_api.
df_keys = pd.read_csv(args.csv, header=None)
flickr.set_keys(api_key = df_keys.loc[0].values[0], api_secret = df_keys.loc[1].values[0])
num_pags=args.limit
os.chdir(«..»)
working_directory = os.getcwd()
if not os.path.exists(args.dir):
os.makedirs(args.dir)
wdif = working_directory + «/» + args.dir
os.chdir(path=wdif)
os.mkdir(‘images 350org’)
Después, similar a lo realizado con NASA, creamos el archivo .csv donde se va a guardar la url de la imagen, fecha en la que se subió, nombre del albúm donde se obtiene la imagen y, por último, las vistas de la imagen. También, se obtiene un array con el nombre de los álbumes del usuario y la información de cada álbum (imágenes, fechas, vistas).
user = flickr.Person.findByUserName(«350.org»)
albums = user.getPhotosets(user_id=’25654955@N03′,extras= ‘date_taken, views’)
array_terminations=[«jpg»,»jpeg», «gif», «png»]
array_images=[]
filename = «reporte350org.csv»
f = open(filename, «w»)
headers = «img_url, date, title, views\n»
f.write(headers)
Ahora, mediante el uso de la biblioteca urllib.request y flickr_api, creamos un ciclo for con un contador para recorrer los álbumes guardados en el array antes creado. Mediante una función de flickr_api damos forma a otro array con la infomación de cada álbum (url de la imagen, fecha y vistas por imagen). Añadimos la información anterior al reporte .csv y sumamos a un array el url de la imagen.
for i in range(num_pags):
try:
album = albums[2*i]
album_title = album[‘title’]
photos = album.getPhotos(user_id=’25654955@N03′,extras= ‘date_taken, views, url_c’)
for j in range(len(photos)):
try:
photo = photos[j]
views = photo[‘views’]
date = photo[‘datetaken’]
img = photo[‘url_c’]
f.write(img+ «,»+ date.split(» «)[0]+»,» +album_title.replace(«,»,» «).replace(«\n», » «) + «,» +str(views)+ «\n»)
array_images.append(img)
except:
pass
except:
pass
f.close()
Para terminar, escribimos un ciclo para acceder a los nombres de las imágenes guardadas dentro del array creado; luego cambiamos de directorio al generado en la sección de creación de directorios y hacemos la descarga de la imagen con la biblioteca urllib.request.
for image in array_images:
name=image.split(‘/’)[-1]
if not name.split(«.»)[-1] in array_terminations:
name=name+».jpg»
os.chdir(path=wdif+’/images 350org’)
img_data = requests.get(image).content
with open(name, ‘wb’) as handler:
handler.write(img_data)
os.chdir(path=wdif)
Es importante que, para poder usar el código mediante la terminal, se ejecute la siguiente línea:
python3 scrap_flickr.py -d <directorio> -l <número limite de albúmes> -c <archivo de las keys>.csv
En donde:
– d se pone el nombre del directorio a crear.
– l límite de albúmenes a descargar.
–c es el archivo.csv donde se encuentran el api_key y api_secret en este mismo orden.
El resultado de esta ejecución es la creación de una carpeta con el nombre del directorio dado en la línea de ejecución, así como una carpeta con las imágenes y un archivo .csv con el URL, fecha, título del álbum y el número de visitas.
¹ Dentro de la búsqueda de fuentes de información, se descartaron varias páginas, ya que la mayoría de los posts no cuentan con imágenes ni fechas de publicación y, al tener habilitado JavaScript, la extracción se volvía mucho más compleja utilizando BeautifulSoup, la herramienta que se utilizó durante la investigación.
² Greenpeace no cuenta con una sección de multimedia, pero sí con una de artículos. Sin embargo, el uso de JavaScript impide un recorrido por las diferentes páginas con la herramienta de BeautifulSoup. Por lo tanto, dejamos de lado esta página. Por su parte, FOEI cuenta con una sección de multimedia de la que se intentó obtener las imágenes de cada artículo, pero los resultados no fueron los deseados. De igual manera pasó con la página de Fridays for Future.
³ Por último, se intentó ShutterStock. Esta red social es similar a Flickr y existe un repositorio en GitHub el cual hace una descarga de imágenes por palabras clave; con la salvedad que no se genera un reporte para hacer un vínculo con fechas e imagen, igualmente, la mayoría de las organizaciones tienen sus cuentas en Flickr. Por lo tanto, decidimos enfocarnos más a la página de Flickr que a ShutterStock.