First Commit

This commit is contained in:
2026-08-15 23:43:07 +09:00
commit c3aad03182
41 changed files with 4342 additions and 0 deletions
+60
View File
@@ -0,0 +1,60 @@
import logging
import requests
log = logging.getLogger(__name__)
class UnpaywallResolver:
def __init__(self, email: str, timeout=(10, 30)):
self.email = (email or "").strip()
self.timeout = timeout
self.base_url = "https://api.unpaywall.org/v2"
def resolve(self, paper):
if not paper.doi:
return paper
if not self.email:
log.warning(
"Unpaywall email missing; OA lookup skipped: %s",
paper.title,
)
return paper
doi = paper.doi.strip()
try:
response = requests.get(
f"{self.base_url}/{doi}",
params={"email": self.email},
timeout=self.timeout,
)
response.raise_for_status()
except requests.exceptions.HTTPError as exc:
status = exc.response.status_code if exc.response else None
# DOI not present in Unpaywall is not fatal.
if status == 404:
paper.oa_status = "not_found"
return paper
raise
data = response.json()
paper.oa_status = str(
data.get("oa_status") or ""
)
best = data.get("best_oa_location") or {}
pdf_url = best.get("url_for_pdf") or ""
# Some OA records do not expose url_for_pdf but do expose a landing URL.
# We intentionally do NOT treat url as a PDF here.
paper.pdf_url = str(pdf_url).strip()
return paper