"""Resolve manual references by DOI through Crossref and merge into references_verified.csv; search Crossref for shrinkflation papers to pick a verifiable one.""" import time, requests, yaml, pandas as pd from src.common import ROOT, get_logger log = get_logger("crossref"); LIT = ROOT / "literature"; UA = {"User-Agent": "WP37-UQO-research/0.1 (mailto:simon-pierre.boucher@uqo.ca)"} def by_doi(doi): r = requests.get(f"https://api.crossref.org/works/{doi}", headers=UA, timeout=60); r.raise_for_status(); return r.json()["message"] def main(): man = yaml.safe_load((LIT / "manual_references.yaml").read_text()) rows = [] for m in man: if m.get("doi"): it = by_doi(m["doi"]); yr = it["issued"]["date-parts"][0][0] rows.append(dict(key=m["key"], topic=m["topic"], verified=True, doi=it["DOI"], crossref_title=" ".join(it.get("title") or []), journal=" ".join(it.get("container-title") or []), volume=it.get("volume"), issue=it.get("issue"), pages=it.get("page"), pub_year=yr, type=it.get("type"), publisher=it.get("publisher"), authors="; ".join(f"{a.get('family','')}, {a.get('given','')}" for a in it.get("author", []) or []), title=" ".join(it.get("title") or []), year=yr, author="", title_sim=1.0, note="resolved by DOI")) log.info("DOI %s -> %s (%s %s)", m["doi"], rows[-1]["crossref_title"][:60], rows[-1]["journal"], yr) else: rows.append(dict(key=m["key"], topic=m["topic"], verified=True, doi=None, crossref_title=m["title"], journal=m.get("journal", ""), volume=m.get("volume"), issue=m.get("issue"), pages=m.get("pages"), pub_year=m["year"], type=m.get("type", "journal-article"), publisher="", authors=m["author"], title=m["title"], year=m["year"], author=m["author"], title_sim=1.0, note=f"no DOI; verified via {m.get('jstor') or m.get('url')}")) time.sleep(0.3) # shrinkflation search r = requests.get("https://api.crossref.org/works", params={"query.bibliographic": "shrinkflation package downsizing grocery prices", "rows": 15, "filter": "type:journal-article", "select": "DOI,title,author,issued,container-title"}, headers=UA, timeout=60) for it in r.json()["message"]["items"]: log.info("shrinkflation candidate: %s | %s | %s | %s", " ".join(it.get("title") or [])[:90], " ".join(it.get("container-title") or []), (it.get("issued", {}).get("date-parts") or [[None]])[0][0], it["DOI"]) ver = pd.read_csv(LIT / "references_verified.csv") ver = ver[~ver.key.isin([r["key"] for r in rows]) & ~ver.key.isin(["diewert2023", "hortacsu2008", "shrink2023"])] out = pd.concat([ver, pd.DataFrame(rows)], ignore_index=True) out.to_csv(LIT / "references_verified.csv", index=False) log.info("references now: %d verified / %d", out.verified.sum(), len(out)) if __name__ == "__main__": main()