Source code for scitex_dataset.general.figshare

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Figshare API client for scientific dataset discovery.

Figshare is a repository where users can make all of their research
outputs available in a citable, shareable and discoverable manner.

API Documentation: https://docs.figshare.com/
"""

from typing import Optional

import httpx
from scitex_dev.decorators import supports_return_as

FIGSHARE_API = "https://api.figshare.com/v2"


[docs] @supports_return_as def fetch_datasets( query: str = "", page: int = 1, page_size: int = 25, order: str = "published_date", order_direction: str = "desc", ) -> list[dict]: """ Fetch datasets from Figshare. Parameters ---------- query : str Search query string. page : int Page number (1-indexed). page_size : int Number of results per page (max 1000). order : str Sort field: 'published_date', 'modified_date', 'views', 'shares'. order_direction : str Sort direction: 'asc' or 'desc'. Returns ------- list[dict] List of article records. """ params = { "page": page, "page_size": page_size, "order": order, "order_direction": order_direction, "item_type": 3, # 3 = dataset } if query: params["search_for"] = query response = httpx.post( f"{FIGSHARE_API}/articles/search", json=params, timeout=60, ) response.raise_for_status() return response.json()
[docs] @supports_return_as def fetch_all_datasets( query: str = "", max_datasets: Optional[int] = None, page_size: int = 25, logger=None, ) -> list[dict]: """ Fetch all datasets from Figshare with pagination. Parameters ---------- query : str Search query string. max_datasets : int, optional Maximum number of datasets to fetch. page_size : int Datasets per request. logger : optional Logger for progress messages. Returns ------- list[dict] List of raw article dictionaries. """ all_datasets = [] page = 1 while True: if logger: logger.info(f"Fetching Figshare page {page}...") hits = fetch_datasets( query=query, page=page, page_size=page_size, ) if not hits: break all_datasets.extend(hits) if logger: logger.info( f" Retrieved {len(hits)} records (total: {len(all_datasets)})" ) if max_datasets and len(all_datasets) >= max_datasets: all_datasets = all_datasets[:max_datasets] break if len(hits) < page_size: break page += 1 return all_datasets
[docs] @supports_return_as def format_dataset(record: dict) -> dict: """ Format a Figshare article into a standardized dataset dictionary. Parameters ---------- record : dict Raw Figshare article from API. Returns ------- dict Standardized dataset dictionary. """ # Fetch full article details for richer metadata article_id = record.get("id", "") try: detail = httpx.get( f"{FIGSHARE_API}/articles/{article_id}", timeout=30, ).json() except Exception: detail = record authors = [a.get("full_name", "") for a in detail.get("authors", [])] files = detail.get("files", []) total_size = sum(f.get("size", 0) for f in files) tags = detail.get("tags", []) categories = [c.get("title", "") for c in detail.get("categories", [])] license_info = detail.get("license", {}) license_name = license_info.get("name", "") if isinstance(license_info, dict) else str(license_info) return { "id": str(article_id), "doi": detail.get("doi", ""), "name": detail.get("title", record.get("title", "")), "description": detail.get("description", ""), "created": detail.get("created_date", ""), "modified": detail.get("modified_date", ""), "publish_date": detail.get("published_date", ""), "version": str(detail.get("version", "")), "authors": authors, "keywords": tags + categories, "license": license_name, "n_files": len(files), "size_bytes": total_size, "size_gb": round(total_size / (1024**3), 3) if total_size else 0, "views": detail.get("views", 0), "downloads": detail.get("downloads", 0), "url": detail.get("url_public_html", record.get("url", "")), "source": "figshare", }
# EOF