Fetches the abstract text and core metadata for one or more records from the
Elsevier 'Scopus' Abstract Retrieval API. This complements the Search API used
elsewhere in the package: a search returns many records with a few fields each,
whereas this returns the fuller record, including the abstract, for a known
identifier. Passing include adds the author keywords, the index keywords
and the document's reference list, or any of them, to the same request.
Arguments
- ids
Character vector of identifiers to look up, either Digital Object Identifiers or 'Scopus' record identifiers (with or without the
"SCOPUS_ID:"prefix), according toby.- by
Either
"doi"or"scopus_id", the kind of identifier inids.- view
The Abstract Retrieval view to request:
"META_ABS"(the default),"META","REF"or"FULL", orNULL."META_ABS"is the view Elsevier documents as carrying the abstract with the core metadata.NULLsends noviewparameter, as the 0.4.0 release and earlier did, and leaves the choice to the API. Elsevier documents its default as"META", a view without the abstract, but a live request in October 2026 returned the abstract without a view. Retrievinginclude = "references"requiresview = "FULL"orview = "REF"; see Details for how the two differ and which to prefer.- include
Optional character vector naming extra fields to retrieve in the same request: any of
"references","keywords"(the author keywords) and"index_terms"(the index keywords 'Scopus' assigns)."references"requiresview = "FULL"orview = "REF", and"keywords"and"index_terms"requireview = "FULL", since theREFresponse carries neither kind of keyword. Either way this is an entitlement that is separate from ordinary abstract access and from 'Scopus' Search access, and, per Elsevier's own documentation, some fields (notably author keywords) may need to be requested from your Scopus/Elsevier account contact even when the view itself is otherwise accessible. See Details.- cache_dir
Optional directory for per-identifier cache files, as in
scopus_fetch_plan().NULL(the default) performs no caching. Worth setting wheneverincludeis used: Abstract Retrieval draws on its own weekly quota, smaller than and separate from Search's, and every identifier here costs at least one request of its own, so re-running an interrupted batch without a cache re-spends quota already spent. Acache_dirthat cannot be written is refused before any request, and a checkpoint that cannot be written all the same warns and keeps the row, as inscopus_fetch_plan().- resume
Logical. When
TRUE(the default) andcache_diris set, an identifier whose cache file already exists is loaded from disk, sparing a second request for it. A cache file that cannot be read back, for example one left half-written by an interrupted run, is retrieved again with ascopus_warning_cache_unreadablewarning, and the batch carries on. One holding a different identifier, since distinct identifiers can share a cache filename, is retrieved again with ascopus_warning_cache_mismatchwarning.- api_key, inst_token
Optional credentials (see
scopus_has_key()).- verbose
Logical. When
TRUE, progress is reported.
Value
A tibble of class scopus_abstracts, one row per identifier, with
columns id (the input identifier), scopus_id, doi, title, abstract,
publication, year and citations. A field the API does not return is
NA. An identifier that cannot be retrieved (for example one not in
'Scopus') yields a row of NAs with a warning, so a batch is not lost to a
single failure. The number of Abstract Retrieval requests made and the
most recently parsed quota (see scopus_quota()) are attached as the
n_requests and quota attributes, since this is a materially more
expensive operation than a search call.
When include names "keywords", an authkeywords column is added: the
document's author-supplied keywords, joined the same way as authors
("; "-separated), or NA when the document has none, or when the API
omits the field for a given key's entitlement (see Details).
When include names "index_terms", an idxterms column is added after
any authkeywords: the index keywords of the document, joined by "; ",
or NA when the response carries none. An entry without text is dropped.
When include names "references", a references list-column is added:
one data frame per document, with one row per cited work, where a joined
string would have to be parsed apart again. Its columns are position (the
reference's place in the bibliography), id (the 'Scopus' identifier of
the cited work, when
resolved), doi, title, authors, source (the journal or other
venue), year and citedbycount (the cited work's own citation count;
populated only under view = "REF", NA under "FULL"). A document with
no resolvable references yields a zero-row data frame, so the column can
always be unnested.
Details
Retrieving references needs Abstract Retrieval's FULL or REF view, and
keywords need FULL. FULL returns the whole bibliography in one request.
REF serves it a page at a time, about 40 references per request, so
scopus_abstract() follows the view's startref parameter until it holds
as many references as the document reports, as pybliometrics does. A REF
document with N references therefore costs ceiling(N / 40) requests,
each counted in n_requests, which makes "FULL" the cheaper view when
your entitlement allows it. Elsevier's guide numbers startref from 0 and
pybliometrics from 1, and which of the two the API follows has not been
confirmed. Paging stops on an empty page, on a page that adds no new
reference, or after as many pages as the first page's length implies, so
neither numbering can make it loop or repeat references. When the number
of references held still differs from the document's reported count, a
scopus_warning_incomplete_references warning says so. An
identifier whose later page fails is a failed retrieval: it gets a row of
NAs with a warning and is not checkpointed.
Author keywords were not populated by either 'Scopus' Search's COMPLETE
view (see scopus_records()) or Abstract Retrieval's FULL view in this
package's own development testing, against a live, otherwise
fully-entitled key, on documents that do carry author keywords in 'Scopus'
itself. If your own keywords come back all NA, this is most likely an
entitlement gap specific to that field, worth raising with your
Scopus/Elsevier account contact. The documents do carry keywords.
Index keywords are the other kind 'Scopus' records. Authors choose their own
keywords, whereas 'Scopus' chooses the index keywords and standardises them
to vocabularies derived from thesauri Elsevier owns or licenses, with
synonyms, spellings and plurals brought together. The two kinds therefore
give different keyword co-occurrence results, and a study should say which
it used. Elsevier's guide lists index keywords in the FULL view as not
available by default, so whether they arrive depends on your key's
entitlement as well. In this package's development testing, they did
arrive on the same key whose author keywords came back empty.
API access
This performs one request per identifier, or one per page of references
under view = "REF" with include = "references", and requires a valid
API key and internet access; full-text abstract access, and the FULL/REF views in
particular, can also depend on your entitlement. A view or field your key is
not entitled to raises a scopus_error_forbidden condition with a message
naming the view and suggesting who to contact, where a generic HTTP failure
would leave you guessing. Because entitlement is a property of the account,
retrieval stops at the first such failure, so the same refusal is not
repeated for every remaining identifier.
A spent weekly quota (HTTP 429 marked QUOTA_EXCEEDED) also stops the
requests, but returns what the batch holds, since it usually arrives
part-way through: the rows already retrieved are kept, each identifier not
retrieved gets a row of NAs that is not checkpointed, and one
scopus_warning_quota_exceeded warning names the identifier reached, how
many were not retrieved and when the quota resets. A checkpoint in
cache_dir is still read after the stop. See the API access section of
scopus_count() for the other conditions that may be raised.
See also
scopus_fetch(), scopus_extract_dois(), scopus_corpus() to
assemble a minimal keyword/reference corpus across many documents.
Examples
if (FALSE) { # scopusflow::scopus_has_key()
# One record of the bundled corpus, looked up for real.
scopus_abstract(scopus_extract_dois(example_records)[1])
# Author keywords and a structured reference list, in the same request.
# Costs one Abstract Retrieval request per identifier, against a smaller,
# separate weekly quota from Search; see the API access section above for
# the entitlement this needs.
rich <- scopus_abstract(
"10.1038/natrevmats.2016.33",
view = "FULL", include = c("references", "keywords")
)
rich$references[[1]]
}
# The offline companion, which needs no key. The identifiers, titles,
# sources and citation counts are two records of the bundled corpus of real
# articles; the abstract text is what a live call adds, so it is left as a
# placeholder here, as is the 'Scopus' identifier the corpus does not
# carry.
cited <- example_records[order(-example_records$citations), ][1:2, ]
abstracts <- tibble::tibble(
id = cited$doi,
scopus_id = NA_character_,
doi = cited$doi,
title = cited$title,
abstract = NA_character_,
publication = cited$publication,
year = cited$year,
citations = cited$citations
)
class(abstracts) <- c("scopus_abstracts", class(abstracts))
abstracts
#> <scopus_abstracts> (2 records)
#> # A tibble: 2 × 8
#> id scopus_id doi title abstract publication year citations
#> <chr> <chr> <chr> <chr> <chr> <chr> <int> <int>
#> 1 10.1038/natrevmats… NA 10.1… Grap… NA Nature Rev… 2016 1247
#> 2 10.1021/am509065d NA 10.1… Flex… NA ACS Applie… 2015 469
# A reference list arrives as one data frame per document, in the
# `references` list-column added by include = "references". The corpus
# carries no bibliographies, so its own records fill the columns here,
# standing in for the works the first document cites.
refs <- example_records[1:3, ]
abstracts$references <- list(
tibble::tibble(
position = as.character(seq_len(nrow(refs))),
id = NA_character_,
doi = refs$doi,
title = refs$title,
authors = refs$authors,
source = refs$publication,
year = refs$year,
citedbycount = refs$citations
),
tibble::tibble()
)
abstracts$references[[1]]
#> # A tibble: 3 × 8
#> position id doi title authors source year citedbycount
#> <chr> <chr> <chr> <chr> <chr> <chr> <int> <int>
#> 1 1 NA 10.15541/jim20140527 Enhance… Jianhu… Journ… 2015 1
#> 2 2 NA NA Fabrica… Patric… Digit… 2015 0
#> 3 3 NA 10.1021/am509065d Flexibl… Zhiwei… ACS A… 2015 469
