Méthodologie d'accès au contenu
Approches éthiques et légales pour accéder à du contenu web restreint dans le cadre du journalisme et de la recherche.
Hiérarchie d'accès (du plus au moins préféré)
┌─────────────────────────────────────────────────────────────────┐
│ HIÉRARCHIE DE DÉCISION D'ACCÈS AU CONTENU │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. TOTALEMENT LÉGAL (Toujours essayer en premier) │
│ ├─ Bases de données de bibliothèques (PressReader, ProQuest, │
│ │ JSTOR) │
│ ├─ Outils en libre accès (Unpaywall, CORE, PubMed Central) │
│ ├─ Contact direct avec l'auteur │
│ └─ Prêt entre bibliothèques │
│ │
│ 2. LÉGAL (Fonctionnalités du navigateur) │
│ ├─ Mode Lecture (Safari, Firefox, Edge) │
│ ├─ Archives de la Wayback Machine │
│ └─ Google Scholar "Toutes les versions" │
│ │
│ 3. ZONE GRISE (Utiliser avec prudence) │
│ ├─ Archive.is pour articles individuels │
│ ├─ Désactiver JavaScript (casse certaines fonctionnalités) │
│ └─ VPN pour contenu géo-bloqué │
│ │
│ 4. NON RECOMMANDÉ │
│ ├─ Partage d'identifiants │
│ ├─ Scraping systématique │
│ └─ Utilisation commerciale de contenu contourné │
│ │
└─────────────────────────────────────────────────────────────────┘
Outils en libre accès pour articles académiques
Extension de navigateur Unpaywall
Unpaywall trouve des copies gratuites et légales de plus de 20 millions d'articles académiques.
# API Unpaywall (gratuite, nécessite un email pour identification)
import requests
def find_open_access(doi: str, email: str) -> dict:
"""Trouve la version en libre accès d'un article via l'API Unpaywall.
Args:
doi: Identifiant d'objet numérique (ex: "10.1038/nature12373")
email: Votre email pour l'identification de l'API
Returns:
Dictionnaire avec la meilleure URL en libre accès si disponible
"""
url = f"https://api.unpaywall.org/v2/{doi}?email={email}"
response = requests.get(url, timeout=30)
if response.status_code != 200:
return {'error': f'Status {response.status_code}'}
data = response.json()
if data.get('is_oa'):
best_location = data.get('best_oa_location', {})
return {
'is_open_access': True,
'oa_url': best_location.get('url_for_pdf') or best_location.get('url'),
'oa_status': data.get('oa_status'), # gold, green, bronze, hybrid
'host_type': best_location.get('host_type'), # publisher, repository
'version': best_location.get('version') # publishedVersion, acceptedVersion
}
return {
'is_open_access': False,
'title': data.get('title'),
'journal': data.get('journal_name')
}
# Utilisation
result = find_open_access("10.1038/nature12373", "[email protected]")
if result.get('is_open_access'):
print(f"PDF gratuit à : {result['oa_url']}")
API CORE (295 millions d'articles)
# API CORE - nécessite une clé API gratuite depuis https://core.ac.uk/
import requests
class CORESearch:
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = "https://api.core.ac.uk/v3"
def search(self, query: str, limit: int = 10) -> list:
"""Recherche dans la base de données CORE des articles en libre accès."""
headers = {'Authorization': f'Bearer {self.api_key}'}
params = {
'q': query,
'limit': limit
}
response = requests.get(
f"{self.base_url}/search/works",
headers=headers,
params=params,
timeout=30
)
if response.status_code != 200:
return []
data = response.json()
results = []
for item in data.get('results', []):
results.append({
'title': item.get('title'),
'authors': [a.get('name') for a in item.get('authors', [])],
'year': item.get('yearPublished'),
'doi': item.get('doi'),
'download_url': item.get('downloadUrl'),
'abstract': item.get('abstract', '')[:500]
})
return results
def get_by_doi(self, doi: str) -> dict:
"""Récupère un article par DOI."""
headers = {'Authorization': f'Bearer {self.api_key}'}
response = requests.get(
f"{self.base_url}/works/{doi}",
headers=headers,
timeout=30
)
return response.json() if response.status_code == 200 else {}
API Semantic Scholar (214 millions d'articles)
# API Semantic Scholar - gratuite, aucune clé requise pour une utilisation de base
import requests
def search_semantic_scholar(query: str, limit: int = 10) -> list:
"""Recherche dans Semantic Scholar des articles avec des liens en libre accès."""
url = "https://api.semanticscholar.org/graph/v1/paper/search"
params = {
'query': query,
'limit': limit,
'fields': 'title,authors,year,abstract,openAccessPdf,citationCount'
}
response = requests.get(url, params=params, timeout=30)
if response.status_code != 200:
return []
results = []
for paper in response.json().get('data', []):
oa_pdf = paper.get('openAccessPdf', {})
results.append({
'title': paper.get('title'),
'authors': [a.get('name') for a in paper.get('authors', [])],
'year': paper.get('year'),
'citations': paper.get('citationCount', 0),
'open_access_url': oa_pdf.get('url') if oa_pdf else None,
'abstract': paper.get('abstract', '')[:500] if paper.get('abstract') else ''
})
return results
def get_paper_by_doi(doi: str) -> dict:
"""Récupère les détails d'un article par DOI."""
url = f"https://api.semanticscholar.org/graph/v1/paper/DOI:{doi}"
params = {
'fields': 'title,authors,year,abstract,openAccessPdf,references,citations'
}
response = requests.get(url, params=params, timeout=30)
return response.json() if response.status_code == 200 else {}
Mode lecture du navigateur pour les paywalls logiciels
Activation du mode lecture
// Bookmarklet pour déclencher le mode lecture type Firefox
// Fonctionne sur certains paywalls logiciels qui chargent le contenu avant de bloquer
javascript:(function(){
// Essayer d'extraire le contenu de l'article
var article = document.querySelector('article') ||
document.querySelector('[role="main"]') ||
document.querySelector('.article-body') ||
document.querySelector('.post-content');
if (article) {
// Supprimer les superpositions de paywall
document.querySelectorAll('[class*="paywall"], [class*="subscribe"], [id*="paywall"]')
.forEach(el => el.remove());
// Supprimer les superpositions en position fixe
document.querySelectorAll('*').forEach(el => {
var style = getComputedStyle(el);
if (style.position === 'fixed' && style.zIndex > 100) {
el.remove();
}
});
// Réactiver le défilement
document.body.style.overflow = 'auto';
document.documentElement.style.overflow = 'auto';
console.log('Superposition supprimée. Le contenu peut maintenant être visible.');
}
})();
Mode lecture par navigateur
| Navigateur | Comment activer | Efficacité |
|---|---|---|
| Safari | Cliquer sur l'icône Lecteur dans la barre d'URL | Élevée pour les paywalls logiciels |
| Firefox | Cliquer sur l'icône Mode Lecture (ou F9) | Élevée |
| Edge | Cliquer sur l'icône Lecteur Immersif | La plus élevée |
| Chrome | Nécessite un flag : chrome://flags/#enable-reader-mode | Moyenne |
Accès aux bases de données de bibliothèques
Vérification de l'accès à la bibliothèque par programmation
# La plupart des bases de données de bibliothèques nécessitent une authentification
# Ceci montre comment structurer l'accès à l'API d'une bibliothèque
class LibraryAccess:
"""Modèle d'accès pour les bases de données de bibliothèques."""
# Points de terminaison courants des bases de données de bibliothèques
DATABASES = {
'pressreader': {
'base': 'https://www.pressreader.com',
'auth': 'library_card',
'content': '7000+ journaux/magazines'
},
'proquest': {
'base': 'https://www.proquest.com',
'auth': 'institutionnel',
'content': 'actualités, thèses, documents'
},
'jstor': {
'base': 'https://www.jstor.org',
'auth': 'institutionnel',
'content': 'revues académiques, livres'
},
'nexis_uni': {
'base': 'https://www.nexisuni.com',
'auth': 'institutionnel',
'content': 'juridique, actualités, affaires'
}
}
@staticmethod
def get_pressreader_access_methods():
"""Moyens d'accéder à PressReader via les bibliothèques."""
return {
'in_library': "Se connecter au WiFi de la bibliothèque, visiter pressreader.com",
'remote': "Se connecter avec les identifiants de la carte de bibliothèque",
'app': "Télécharger l'application PressReader, lier la carte de bibliothèque",
'note': "Accès généralement 30 à 48 heures par session"
}
# Workflow de prêt entre bibliothèques (ILL)
def request_via_ill(paper_info: dict, library_email: str) -> str:
"""Générer une demande de prêt entre bibliothèques.
L'ILL est gratuit dans la plupart des bibliothèques et peut obtenir presque tous les articles.
Délai de traitement : généralement 3 à 7 jours.
"""
request = f"""
DEMANDE DE PRÊT ENTRE BIBLIOTHÈQUES
Titre : {paper_info.get('title')}
Auteur(s) : {paper_info.get('authors')}
Revue : {paper_info.get('journal')}
Année : {paper_info.get('year')}
DOI : {paper_info.get('doi')}
Volume/Numéro : {paper_info.get('volume')}/{paper_info.get('issue')}
Pages : {paper_info.get('pages')}
Demandé par : {library_email}
"""
return request.strip()
Utilisation de VPN pour contenu géo-bloqué
Quand les VPN sont appropriés
## Cas d'utilisation légitimes des VPN pour journalistes/chercheurs
### APPROPRIÉ :
- Accéder à des sources d'actualités spécifiques à une région
- Rechercher comment le contenu apparaît dans d'autres pays
- Contourner la censure gouvernementale (dans certains contextes)
- Protéger les communications avec les sources
- Vérifier le contenu ciblé géographiquement
### INAPPROPRIÉ :
- Contourner des contrôles d'accès légitimes
- Accéder à du contenu que vous êtes contractuellement interdit de consulter
- Éviter des interdictions ou des blocages placés sur votre compte
Comparaison des services VPN
| Service | Meilleur pour | Confidentialité | Vitesse | Prix |
|---|---|---|---|---|
| ExpressVPN | Contournement de la censure | Excellente | Rapide | $$$ |
| NordVPN | Usage général | Excellente | Rapide | $$ |
| Surfshark | Budget, appareils illimités | Bonne | Bonne | $ |
| ProtonVPN | Axé sur la confidentialité | Excellente | Moyenne | $$ |
| Tor Browser | Anonymat maximal | Excellente | Lente | Gratuit |
Vérification du statut de géo-restriction
import requests
def check_geo_access(url: str, regions: list = None) -> dict:
"""Vérifier si une URL est accessible depuis différentes régions.
Remarque : cela nécessite des services VPN/proxy pour des tests réels.
Cette fonction montre le concept.
"""
regions = regions or ['US', 'UK', 'EU', 'JP', 'AU']
results = {}
# Test d'accès direct
try:
response = requests.get(url, timeout=10)
results['direct'] = {
'accessible': response.status_code == 200,
'status_code': response.status_code
}
except Exception as e:
results['direct'] = {'accessible': False, 'error': str(e)}
# Nécessiterait une intégration VPN/proxy pour les tests régionaux
# results[region] = test_through_proxy(url, region)
return results
Accès par archive
Utilisation d'Archive.today pour les articles payants
import requests
from urllib.parse import quote
def get_archived_article(url: str) -> str:
"""Essayer d'obtenir un article depuis Archive.today.
Archive.today capture souvent le contenu complet de l'article
car il rend JavaScript et capture le résultat.
Le statut juridique varie selon la juridiction - à utiliser à des fins de recherche.
"""
# Vérifier s'il existe une archive
search_url = f"https://archive.today/{quote(url, safe='')}"
try:
response = requests.get(search_url, timeout=30, allow_redirects=True)
if response.status_code == 200 and 'archive.today' in response.url:
return response.url
# Aucune archive existante - pourrait en demander une
# Remarque : cela peut violer les CGU, à utiliser de manière responsable
return None
except Exception:
return None
Wayback Machine pour accès historique
def get_wayback_article(url: str) -> str:
"""Obtenir un article depuis la Wayback Machine.
100 % légal - Internet Archive est une bibliothèque reconnue.
Peut avoir des versions plus anciennes d'articles (avant la mise en place du paywall).
"""
# Vérifier la disponibilité
api_url = f"http://archive.org/wayback/available?url={url}"
try:
response = requests.get(api_url, timeout=10)
data = response.json()
snapshot = data.get('archived_snapshots', {}).get('closest', {})
if snapshot.get('available'):
return snapshot['url']
return None
except Exception:
return None
Stratégies Google Scholar
Trouver des versions gratuites
def find_free_via_scholar(title: str) -> list:
"""Stratégies de recherche pour trouver des versions gratuites d'articles.
Google Scholar renvoie souvent à :
- Copies sur les sites personnels des auteurs
- Versions dans les dépôts institutionnels
- ResearchGate/Academia
...