D2SN/Séminaire Mémoire/Sources de données
Bases de données
modifierIl ne manque pas de bases de données déjà constituées sur lesquelles on peut travailler directement. Leurs origines sont diverses, des recherches, des archives, des expériences. Certaines ont même été constitués à partir de l'usage d'APIs et du scraping, et on va aussi se retrouver avec une base de données quand on s'utilise d'eux. Donc les soucis au moment de constituer, traiter et utiliser une base de données sont partagées peu importe la méthode. Voici quelques uns :
- Est-elle bien documenté ?
- Est-elle complète ?
- Est-elle structuré comme promis ?
- Quel interprétation attribuer aux données ?
- Les coquilles sont conséquentes ? Pour les questions qu'on pose ?
- Quels biais on trouve dans sa constitution ?
- Quels biais par rapport à nos questions ?
- Quel décalage entre les données souhaitées et les données obtenus ?
- Quelles interactions possibles avec d'autres bases de données ? Quels des autres questions reviennent ?
Sources de bases de données
modifierCertains dépôts de bases de données fournissent un accès par API ou par téléchargement aux données hébergés, tandis que d'autres fournissent uniquement un accès via le Web.
- Dépôts institutionnels. Ex :
- Universités : Harvard Dataverse, Peking University Open Research Data
- Instituts de recherche : Data INRA, CIRAD Dataverse
- Agences de financement : Projets ANR chez le dépôt OpenData ESRI, NIH Exporter
- Gouvernements : data.gouv.fr, dados.gov.br
- Dépôts thématiques
- Dépôts ouverts
- Dépôts meta/biblio
- Dépôts universels sémantiques
- Wikidata
- Concept : Linked Open Data
API
modifierLes APIs sont des accès documentées et stables, munis d'un vocabulaire avec lequel on peut demander des opérations et des données de façon directe. Quand on utilise une bibliothèques logicielle, l'ensemble de fonctions qu'on utilise est son API. Les Web APIs sont des APIs accessibles sur Internet par des requêtes distantes du type HTTP[S].
Exemple d'usage de deux APIs de Wikimédia / Wikipédia :
- Pour chercher les pages membres d'une catégorie :
- Pour obtenir le nombre d'accès à une page :
- À partir de ces deux APIs, on construit un petit logiciel pour récupérer les accès de toutes les pages d'une catégorie et les visualiser dans un graphe :
#!/usr/bin/python3
"""
This script was based on :
get_category_items.py
MediaWiki API Demos
Demo of `Categorymembers` module : List twenty items in a category
MIT License
"""
import sys, requests
import pandas as pd
from numpy import datetime64
def wm_timestamp_to_datetime64(ts, unit):
"""Takes a timestamp in wikimedia format and converts it to a `datetime64` object."""
return datetime64("{}-{}-{}T{}".format(ts[0:4], ts[4:6], ts[6:8], ts[8:10]), unit)
def datetime64_to_wm_timestamp(dt):
"""Takes a `datetime64` object and converts it to a timestamp in wikimedia format."""
return datetime64(dt, "h").astype(str).replace("-", "").replace("T", "")
class WikiAPIExemple:
def __init__(self, language="fr", project="wikipedia.org"):
"""Instantiates an HTTP sesssion and sets the project and language."""
self.S = requests.Session()
self.project = project # wikipedia.org, wiktionary.org
self.language = language # fr, en, pt
def get_categorymembers(self, category_name):
"""Given a category name, gets the pages that are members of that category."""
url = "https://{}.{}/w/api.php".format(self.language, self.project)
params = {
"action": "query",
"cmtitle": "Category:{}".format(category_name),
"cmlimit": "20",
"list": "categorymembers",
"format": "json",
}
data = self.S.get(url=url, params=params).json()
return data["query"]["categorymembers"]
def get_pageviews(self, page_name, granularity="monthly"):
"""Given a page name, gets the page views for that page in either monthly or daily intervals."""
dt_unit = "M" if granularity == "monthly" else "D"
start = datetime64("2010-10-10", dt_unit)
end = datetime64("2019-10-31", dt_unit)
api_ep = (
"https://wikimedia.org/api/rest_v1"
+ "/metrics/pageviews/per-article"
+ "/{project}/{access}/{agent}/{article}/{granularity}/{start}/{end}"
)
url = api_ep.format(
project=".".join([self.language, self.project]),
access="all-access",
agent="user",
article=page_name.replace(" ", "_"),
granularity=granularity,
start=datetime64_to_wm_timestamp(start),
end=datetime64_to_wm_timestamp(end),
)
headers = {"accept": "application/json"}
s = pd.Series(name=page_name, index=pd.DatetimeIndex([], name=granularity))
results = self.S.get(url, headers=headers).json()
for item in results.get("items", []):
dt = wm_timestamp_to_datetime64(item["timestamp"], unit=dt_unit)
s.loc[dt] = item["views"]
return s
def plot_pageviews(self, pageviews, fname=None):
"""Given a Series or DataFrame, plots it in a decent size and tightened layout."""
ax = pageviews.plot(figsize=(16, 9))
ax.figure.tight_layout()
if fname:
ax.figure.savefig(fname)
if __name__ == "__main__":
"""Run as a program, this script will get details from the user and make a standard plot"""
# Input
input_category = input("Category: ") # i.e. "Indépendance du Brésil"
input_granularity = input("Granularity (monthly, daily): ")
input_fname = input("File name (if empty won't save figure): ")
# Get pages in category and display them to the user
wae = WikiAPIExemple("fr", "wikipedia.org")
cat_members = wae.get_categorymembers(input_category)
print(cat_members)
# Build a dataframe with view counts for pages in the wiki's main namespace
page_views = pd.DataFrame()
for page in cat_members:
if page["ns"] == 0:
page_name = page["title"]
page_views[page_name] = wae.get_pageviews(page_name, input_granularity)
# Plot the ten pages with highest average
sel = page_views.mean().sort_values(ascending=False).iloc[:10].index
wae.plot_pageviews(page_views.loc[:, sel], input_fname)
Scraping
modifierLe scraping c'est créer des robots (spiders, crawleurs) pour naviguer automatiquement des pages web et en extraire des contenus d'intérêt, tout en les enregistrant de façon structurée.
L'outil python incontournable pour faire du scraping c'est Scrapy. Voici un bon tutoriel à suivre :