ojs-dashboard / data_loader.py
Elias Entrup
Update for OpenAlex change
951bd56
Raw History Blame Contribute Delete
2.89 kB
import logging
import shutil
import tempfile
import zipfile
from pathlib import Path
import country_converter as coco
import polars as pl
import pyalex
import requests
from config import (
BEACON_PATH,
DATAVERSE_API_KEY,
OPENALEX_API_KEY,
ROR_PATH,
)
logger = logging.getLogger(__name__)
DATAVERSE_URL = 'https://dataverse.harvard.edu/api/access/dataset/:persistentId/?persistentId=doi:10.7910/DVN/OCZNVY'
pyalex.config.api_key = OPENALEX_API_KEY
def download_beacon_dataset() -> None:
"""Download beacon.csv from Harvard Dataverse."""
logger.info('Downloading beacon.csv')
response = requests.get(
DATAVERSE_URL,
headers={'X-Dataverse-key': DATAVERSE_API_KEY},
stream=True,
timeout=60,
)
BEACON_PATH.parent.mkdir(exist_ok=True)
with tempfile.TemporaryDirectory() as tmpdir:
tmpdir_path = Path(tmpdir)
zip_path = tmpdir_path / 'dataset.zip'
zip_path.write_bytes(response.content)
with zipfile.ZipFile(zip_path, 'r') as z:
z.extractall(tmpdir_path)
shutil.move(tmpdir_path / 'beacon.tab', BEACON_PATH)
(
pl.scan_csv(BEACON_PATH, separator='\t')
# TODO: filter out journals with less than X articles?
# .filter(pl.col('record_count_2025') > 0)
.with_columns(pl.col('country').str.replace_all('NA', 'none'))
.with_columns(
pl.col('country')
.alias('country_code')
.map_batches(
lambda x: pl.Series(
[c[0] for c in coco.convert(x, to='ISO2', enforce_list=True)]
),
),
)
.sink_csv(BEACON_PATH)
)
logger.info('Download completed')
def download_ror_dataset() -> None:
"""Download ROR csv dataset to ror_data.csv."""
logger.info('Starting to download ROR entities.')
r = requests.get('https://zenodo.org/api/records/18985120', timeout=10).json()
r = requests.get(r['links']['files'], timeout=10).json()
r = requests.get(r['entries'][0]['links']['content'], timeout=60)
logger.info('Download complete. Starting to unpack and update database.')
ROR_PATH.parent.mkdir(exist_ok=True)
with tempfile.TemporaryDirectory() as tmp:
tmppath = Path(tmp)
zippath = tmppath / 'resp.zip'
extractpath = tmppath / 'content'
with zippath.open('wb') as f:
f.write(r.content)
with zipfile.ZipFile(zippath, 'r') as zip_ref:
zip_ref.extractall(extractpath)
csvpath = next(extractpath.glob('*csv'))
shutil.move(csvpath, ROR_PATH)
logger.info('Done.')
def get_journals() -> pl.LazyFrame:
"""Get a dataframe of all OJS journals in the beacon.csv"""
logger.info('Reading OJS journals.')
if not BEACON_PATH.exists():
download_beacon_dataset()
return pl.scan_csv(BEACON_PATH)