Obtention de PDF d'articles PMC / OA
Conditions préalables
Utilisation réservée aux articles en accès libre (OA) (CC BY / CC BY-NC / CC BY-NC-ND, etc.). Ne pas utiliser pour contourner les paywalls des articles sous abonnement — cela constitue un contournement de la protection des droits d'auteur. Vérifier le statut OA : Unpaywall renvoie is_oa: true, ou EuropePMC renvoie isOpenAccess: Y.
Scénario d'abonnement institutionnel (complément important)
Lorsque l'université/l'établissement de l'utilisateur est abonné aux bases de données des éditeurs, le téléchargement manuel d'un seul article est totalement conforme dans le cadre des droits d'accès, mais il faut noter :
- Sur le réseau du campus / dans la plage IP de l'établissement : l'éditeur reconnaît l'IP, pas l'utilisateur. Le niveau 5 de la chaîne de dégradation (lien direct de l'éditeur) renvoie généralement un 200 directement, et Cloudflare ne bloque pas non plus — dans ce cas, le pipeline existant de cette compétence peut obtenir le contenu sous abonnement sans aucune logique de connexion.
- Accès hors campus : privilégier le VPN système fourni par l'établissement (transparent pour les scripts, configurable une fois) ; les WebVPN (proxies de réécriture d'URL) ne sont pas pris en charge par cette compétence en raison des règles de réécriture différentes selon les établissements et de la nécessité de conserver les cookies de session.
- Ne pas écrire de connexion automatique Shibboleth / OpenAthens : nécessite le stockage local d'identifiants d'authentification unifiés, ce qui est un risque de sécurité ; de plus, les flux IdP varient considérablement d'un établissement à l'autre, rendant une implémentation générique impossible.
- Ligne rouge du téléchargement en masse : presque toutes les licences institutionnelles des éditeurs distinguent le « téléchargement manuel d'un seul article » du systematic/bulk downloading. Même avec un abonnement, la récupération en masse par script viole les termes de la licence et peut entraîner le bannissement de toute la plage IP de l'établissement. Si un besoin réel d'extraction de texte intégral à grande échelle se présente, il faut demander l'API TDM (Text Mining) de l'éditeur (par exemple, Elsevier TDM API, Springer Nature Meta API) et passer par les canaux de quota officiels, plutôt que d'utiliser cette compétence pour des boucles en masse.
Chaîne de dégradation (strictement dans l'ordre)
| Priorité | Méthode | Commande / Point d'accès | Description |
|---|---|---|---|
| 1 | Texte intégral structuré EuropePMC | https://www.ebi.ac.uk/europepmc/webservices/rest/{PMCID}/fullTextXML | Le plus stable. Utilisé pour extraire une structure de texte intégral précise jusqu'au niveau des sous-titres. Renvoie JATS XML |
| 2 | Unpaywall localise la position OA | https://api.unpaywall.org/v2/{DOI}[email protected] | Lit oa_locations[].url_for_pdf, donne directement le lien direct PDF |
| 3 | Résolution PoW PMC et téléchargement | scripts/pmc_pdf.py <PMCID> <out.pdf> | Voir ci-dessous. Solution principale pour obtenir le PDF du corps de l'article |
| 4 | Fichiers supplémentaires EuropePMC | https://www.ebi.ac.uk/europepmc/webservices/rest/{PMCID}/supplementaryFiles | Renvoie un ZIP : images originales (gr1…=Figure 1…)+ PDF de matériel supplémentaire (mmc1.pdf) |
| 5 | Lien direct éditeur | .../article-pdf/... selon l'éditeur | Généralement 403 (Cloudflare). À essayer en dernier |
Points d'accès confirmés comme obsolètes (ne pas perdre de temps)
…/rest/{PMCID}/fullTextPDF→ 404 (obsolète)…/rest/{PMCID}/fulltextRepo→ 403https://europepmc.org/articles/{PMCID}?pdf=render→ 403https://europepmc.org/backend/ptpmcrender.fcgi?accid=…&blobtype=pdf→ 403https://www.ncbi.nlm.nih.gov/pmc/utils/oa/oa.fcgi?id=…→ 404 (le service OA a migré)- Les pages d'articles de
ashpublications.orgrestent bloquées sur la page de défi Cloudflare « Veuillez patienter… » dans un navigateur sans tête, inutilisable
★ Condition préalable : le nom du fichier PDF sur PMC n'est pas fixe, il faut d'abord l'analyser
Le <nom_fichier>.pdf dans https://pmc.ncbi.nlm.nih.gov/articles/{PMCID}/pdf/<nom_fichier>.pdf varie selon la revue et l'année. Coder en dur main.pdf aboutit à une 404 dans la plupart des cas.
| Revue testée | Nom de fichier réel |
|---|---|
| Am J Hematol | main.pdf |
| Blood Advances | main.pdf |
| HemaSphere | HEM3-10-e70338.pdf |
| Am J Hematol | AJH-101-1790.pdf |
| Liver International | LIV-46-0.pdf |
| Haematologica | 111300.pdf (volume 111 + page de début 300, abréviation de la revue omise) |
| Blood (manuscrit NIH) | nihms-2192199.pdf |
Méthode d'analyse (par priorité ; tous les cas testés ont correspondu à la règle 1)
- Balise
<meta name="citation_pdf_url" content="https://pmc.ncbi.nlm.nih.gov/articles/{PMCID}/pdf/XXX.pdf">sur la page de l'article ← Le plus fiable grep -oE 'href="[^"]*?/pdf/[^"]+?\.pdf"'prendre la première occurrence- Repli
pdf/main.pdf
Conventions de nommage (non fiables, à utiliser uniquement pour juger manuellement si l'analyse est correcte) : les OA de Wiley sont souvent <abréviation revue>-<volume imprimé>-0.pdf (ex. LIV-46-0.pdf) ; avec numéro d'article <abréviation revue>-<volume>-<numéro article>.pdf (ex. HEM3-10-e70338.pdf) ; pour la même revue, souvent <abréviation>-<volume>-<page début>.pdf (ex. AJH-101-1790.pdf) ; il existe aussi des variantes « volume+page de début, sans abréviation de la revue » (comme pour Haematologica 111300.pdf = volume 111 + page de début 300).
Lors de la récupération de la page de l'article, veillez à jeter les cookies : utilisez une requête indépendante, sans conservation des cookies, pour lire la page de l'article. La requête PDF doit également être lancée depuis une session de cookies entièrement nouvelle. Si les
ncbi_sid/ncbi_pingergénérés par la page de l'article sont transmis à la requête PDF, celle-ci sera immédiatement dégradée en reCAPTCHA (testé).scripts/pmc_pdf.pyimplémente déjà cela.
Solution principale : résolution hors ligne du Proof-of-Work PMC
Principe
https://pmc.ncbi.nlm.nih.gov/articles/{PMCID}/pdf/<nom_fichier>.pdf peut basculer entre deux types de pages de défi selon la stratégie de risque :
- Page PoW (1817 octets, titre
Preparing to download ...) → Résoluble hors ligne, c'est le canal que nous voulons. - Page reCAPTCHA (environ 20 Ko, titre contenant
reCAPTCHA) → Impossible à résoudre hors ligne.
Clé pour déclencher PoW plutôt que reCAPTCHA : utiliser un UA minimal, et ne pas visiter la page de l'article avant de demander le PDF.
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)
Contre-exemples (conduisent à une dégradation en reCAPTCHA, testé) :
- UA Chrome complet (
…AppleWebKit/537.36 … Chrome/1xx.0.0.0 Safari/537.36) GETde la page de l'article d'abord (en transportantncbi_sid/ncbi_pinger) puis demande du PDF
Algorithme PoW (rétroconception de pow-*.js, confirmée)
La page PoW intègre quatre constantes : POW_CHALLENGE / POW_DIFFICULTY / POW_COOKIE_NAME / POW_COOKIE_PATH.
- Trouver le plus petit entier non négatif
noncetel quesha256(challenge + str(nonce)).hexdigest()ait un préfixe égal à'0' * difficulty; - Définir le cookie :
<POW_COOKIE_NAME> = challenge + "," + nonce(chemin =POW_COOKIE_PATH) ; - Renvoyer la demande au lien direct PDF avec ce cookie et
Referer: https://pmc.ncbi.nlm.nih.gov/articles/{PMCID}/→ Renvoie normalement200etContent-Type: application/pdf.
difficulty = 4 typique (environ 65536 hachages attendus, terminé en moins d'une seconde en local).
Script en une commande
# Recommandé : analyse automatique du nom de fichier PDF réel (via citation_pdf_url), puis résolution hors ligne du PoW
python3 scripts/pmc_pdf.py PMC13575452 ./out.pdf
# Si le nom de fichier a déjà été analysé, il peut être spécifié directement, en sautant la requête de la page de l'article
python3 scripts/pmc_pdf.py PMC13575452 ./out.pdf --pdf-name LIV-46-0.pdf
# Mode silencieux (affiche uniquement la ligne de résultat)
python3 scripts/pmc_pdf.py PMC13575452 ./out.pdf --quiet
Comportement du script : d'abord, demande la page de l'article avec un UA minimal et en jetant les cookies pour analyser le lien direct PDF réel → puis fait une demande à froid de ce PDF avec une session de cookies entièrement nouvelle → si le PDF est obtenu directement, il est sauvegardé ; sinon, les constantes PoW sont analysées, résolues, le cookie est renseigné et la tentative est répétée. Pour forcer une nouvelle récupération du challenge, relancez simplement le script (le script ne sauvegarde pas les cookies sur le disque, chaque session est nouvelle).
★★ Deux règles strictes à retenir (leçons douloureuses testées sur le terrain)
1. Le deuxième paramètre positionnel est le chemin complet du fichier de sortie, pas un répertoire. Passer un répertoire déclenchera une erreur
IsADirectoryError: [Errno 21] Is a directoryaprès avoir déjà obtenu le PDF, rendant la résolution PoW et le PDF inutiles. ❌pmc_pdf.py PMC13482240 --outdir /path/to/dir✅pmc_pdf.py PMC13482240 /path/to/dir/xxx.pdf2. Le canal PDF de PMC a une caractéristique de « une seule chance ». La première demande à froid réussit généralement le PoW et obtient le vrai PDF ; si l'on demande à nouveau le même PDF immédiatement après, il sera presque certainement dégradé en reCAPTCHA (pas une simple limitation de débit « changez d'UA »). Par conséquent, le chemin de sortie doit être correct du premier coup, ne faites absolument pas de « test de lancement pour voir ». Testé : premier tour
status=200 type=application/pdf bytes=23970819, quelques secondes plus tard, en relançant la même URL, on obtienttype=text/html bytes=21329(page de défi reCAPTCHA). Une fois cette opportunité gaspillée, passez directement à la section suivante « Route de dégradation via le site de l'éditeur », ne réessayez pas sur PMC.
Diagnostic des pannes
| Phénomène | Cause | Action |
|---|---|---|
Retourne du HTML contenant POW_CHALLENGE | Canal PoW activé (normal) | Confier la résolution au script |
Retourne du HTML contenant recaptcha | Dégradé en reCAPTCHA | Changer pour un UA minimal, vider les cookies de session, attendre un peu et réessayer ; si toujours en échec, utiliser les voies 4/5 |
| 404 / « Article not found » | Le nom du fichier PDF est mal deviné | Revenir à la page de l'article pour analyser citation_pdf_url, ne pas coder en dur main.pdf |
nonce ne converge pas longtemps | difficulty a été augmenté | Afficher difficulty pour juger ; si >5, envisager une résolution asynchrone ou multi-processus |
| Résolution réussie mais le PDF est toujours du HTML | Domaine/chemin du cookie inadapté | Vérifier que le domaine du cookie est pmc.ncbi.nlm.nih.gov et que le chemin prend POW_COOKIE_PATH |
IsADirectoryError: Is a directory | Le paramètre de sortie a été traité comme un répertoire | Le deuxième paramètre est le chemin complet du fichier de sortie. Le PDF a en fait déjà été obtenu, mais pas sauvegardé — ne relancez pas immédiatement (cela déclencherait un reCAPTCHA). Corrigez d'abord le chemin. Si déjà dégradé, passez directement à la route du site de l'éditeur |
| Première réussite, deuxième reCAPTCHA immédiat | Limitation de débit « une seule chance » de PMC pour le même chemin de PDF | Voir la règle stricte 2 ci-dessus ; abandonnez PMC, passez à la route de dégradation via le site de l'éditeur |
citation_pdf_url renvoie -mmc1.pdf | Le PDF de l'article n'est pas en base, la balise pointe vers du matériel supplémentaire | Commun pour les revues comme Blood où « le texte intégral JATS existe mais le PDF du corps de l'article n'est pas en base ». Abandonnez immédiatement la route PMC, ne faites pas passer du matériel supplémentaire pour le corps de l'article (testé) |
★ Il existe une limitation de débit au niveau IP (testé) Après avoir répété les demandes de PDF à PMC sur une courte période (par exemple, téléchargement consécutif de plusieurs articles), même avec le bon UA minimal, on est directement dégradé en reCAPTCHA, et l'attente de 45 s ne rétablit pas la situation. Se manifeste par « première réussite, puis tous les échecs ». Action : ① Lors d'un téléchargement en masse, laissez un intervalle suffisant entre deux demandes ; ② Une fois en état reCAPTCHA, ne réessayez pas à plusieurs reprises (cela ne fera qu'allonger le bannissement), passez plutôt à d'autres tâches, ou utilisez la voie 4 (
supplementaryFiles) et les liens directs des éditeurs ; ③ Si vous avez vraiment besoin de plusieurs articles, privilégiez le téléchargement à la demande plutôt que le préchauffage en masse.
★★ Route de dégradation : quand PMC est bloqué par reCAPTCHA, passer par le site de l'éditeur (testé et efficace)
Lorsque le lien direct PMC a été dégradé en reCAPTCHA deux fois (limitation de débit IP, ne se rétablit pas après attente), si la revue cible est entièrement OA, passer par le site de l'éditeur est plus fiable que de continuer à réessayer PMC :
UA="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)"
# 1) Résolution DOI → observer la page d'article finale de l'éditeur
curl -s -o /dev/null -w "final: %{url_effective}\nHTTP: %{http_code}\n" -A "$UA" -L "https://doi.org/<DOI>"
# 2) Analyser le lien direct PDF réel sur la page de l'article
curl -s -A "$UA" "https://<publisher-article-page>" | grep -oiE '<meta name="citation_pdf_url"[^>]*>|href="[^"]*\.pdf[^"]*"' | sort -u | head
# 3) Récupérer directement avec Referer (les éditeurs ne vérifient presque jamais le Referer, mais le mettre est plus sûr)
curl -sL --retry 3 -A "$UA" -e "$ARTICLE_PAGE" -o "$OUT" "$PDF_URL"
★★ Quand le site de l'éditeur est complètement bloqué par Cloudflare : utiliser l'impression du navigateur en PDF (testé et efficace)
ashpublications.org (revues du groupe ASH) a subi un blocage complet par Cloudflare lors de cette session,
L'expérience précédente « attendre 10 s puis ouvrir » n'a pas pu être reproduite. Chemin alternatif efficace :
- Ouvrir la page de texte intégral de PMC (pas le PDF), contournant le site de l'éditeur
- Utiliser l'outil d'impression du navigateur pour imprimer cette page en PDF :
agent-browser pdf - Lors du premier affichage du reCAPTCHA, exécuter à nouveau
openune fois pour passer
Point de décision : lorsque la revue cible est fortement protégée par Cloudflare (comme ASH / ScienceDirect), ne réessayez pas avec
curl— le taux de réussite est faible et cela aggrave le bannissement. Passez directement au canal navigateur.
- Vérifié comme faisable : Haematologica / Ferrata Storti ——
doi.org/10.3324/haematol.2025.287698→haematologica.org/article/view/12187→haematologica.org/article/download/12187/78653→ 2.91 Mo / 14 pages. - Pas faisable : revues encore bloquées par des défis de type Cloudflare (ASH
ashpublications.org, Wileyonlinelibrary.wiley.com/doi/pdfdirect/..., De Gruyter, Thieme) — elles ne peuvent être traitées que par le canal PMC ou par une session navigateur. - Pré-évaluation : seules les revues entièrement OA / Gold OA méritent de tenter cette route (les revues sous abonnement rencontreront un paywall qu'il est interdit de contourner).
★ Vérification d'intégrité : les téléchargements interrompus de gros fichiers entraînent une corruption xref
Si le téléchargement du PDF par curl est interrompu par SIGTERM / timeout, l'en-tête du fichier reste normal %PDF-1.6, la taille semble raisonnable, mais pdfinfo signalera Invalid XRef entry. Par conséquent, après le téléchargement, ne vous fiez pas uniquement à l'en-tête et à la taille du fichier ; il faut vérifier simultanément :
head -c 8 "$OUT" # %PDF-…
tail -c 32 "$OUT" | od -c | tail -3 # devrait montrer startxref … %%EOF
pdfinfo "$OUT" | grep -E "Pages|Page size" # Le nombre de pages doit correspondre à celui déduit du « volume/numéro/page »
Ces trois éléments doivent être complets pour que le fichier soit considéré comme intègre ; en cas de manque, recommencer le téléchargement complet (avec --retry 3), ne pas livrer un fichier corrompu.
Matériel supplémentaire et images
Lorsque le PDF du corps de l'article est inaccessible, le point d'accès supplementaryFiles est généralement toujours disponible, et son contenu correspond souvent aux images et méthodes supplémentaires de l'article :
curl -sL -o sup.zip "https://www.ebi.ac.uk/europepmc/webservices/rest/PMC13049628/supplementaryFiles"
unzip -o sup.zip -d sup/
Conventions de nommage (Wiley / ASH) : *-gr1…*-grN correspondent aux Figures 1…N, *-ga1 au résumé graphique, *-mmc1.pdf au matériel supplémentaire.
Utilisation des outils navigateur
N'utiliser agent-browser que lorsque des clics, une connexion ou un rendu JS sont nécessaires. Ne pas lancer le navigateur pour des téléchargements purs — le PoW peut être résolu hors ligne, lancer Chromium n'ajoute que des centaines de Mo de surcharge et une surface d'échec. Si un navigateur est vraiment nécessaire :
- Vous devez d'abord avoir un nœud disponible dans le PATH (sinon le démon dépasse le délai d'attente) ;
- Assurez-vous de fermer le navigateur à la fin de la tâche avec
agent-browser closepour éviter les démons zombies.
Liste de vérification
- Avant le téléchargement, confirmer que l'article cible est OA (ou confirmer que l'on se trouve dans la plage IP de l'abonnement institutionnel — dans ce cas, le lien direct de l'éditeur peut être utilisé directement, mais toujours uniquement pour un téléchargement manuel d'un seul article, pas en masse)
- Analyser le nom de fichier PDF réel à partir de
citation_pdf_urlsur la page de l'article (ne pas coder en durmain.pdf) - Après la sauvegarde, vérifier que l'en-tête du fichier est
%PDF - Vérifier la fin avec
startxref/%%EOF(un fichier volumineux interrompu peut avoir un en-tête normal mais une structure xref corrompue ;pdfinfole détectera) - Vérifier le nombre de pages : utiliser
re.findall(rb'/Count\s+(\d+)', data)ou compter/Type /Page, ne pas faire confiance au nombre de pages defile out.pdf(souvent erroné comme « 1 pages » sur macOS) ; on peut aussi utilisermdls -name kMDItemNumberOfPages - Extraire la première et la dernière page pour vérifier le contenu (
pdftotext -f 1 -l 1/-f N -l N), confirmer qu'il ne s'agit pas de matériel supplémentaire ou d'un autre article - Enregistrer le
PMCID/DOI/ chemin de sauvegarde pour faciliter la vérification ultérieure - En cas d'échec, expliquer honnêtement la raison de l'échec, ne pas présenter du matériel supplémentaire ou des images comme le PDF du corps de l'article