keepcalculator

06 Numbers and Powers

Automate Research Metadata Exports with a Scholarly Search API

Card No. 06·50764 · Updated · Standard formula, shown below

This guide shows you how to automate the export of research metadata (titles, authors, abstracts, DOI, publication dates) using a scholarly search API like Crossref, OpenAlex, or Semantic Scholar. You’ll learn to write a script that queries the API, parses the JSON response, and saves clean metadata to a CSV or Excel file—saving hours of manual copy-paste. No prior coding experience is needed beyond basic Python and a willingness to follow steps.

What You’ll Need

  • Python 3.7+ installed on your computer
  • A code editor (VS Code, PyCharm, or even Notepad)
  • An internet connection
  • Optional: A free API key from Crossref (not required but increases rate limits)
  • Basic familiarity with the command line/terminal

Step-by-Step

  1. Choose your scholarly API. For general metadata, Crossref (api.crossref.org) is free and doesn’t require a key. OpenAlex (api.openalex.org) is also free and provides more detailed metadata. Semantic Scholar requires a key for higher limits. This guide uses Crossref as the example, but the pattern works for others.
  2. Install the required Python libraries. Open your terminal and run: pip install requests pandas. The requests library handles API calls, and pandas helps with data export.
  3. Set up your script file. Create a new Python file, e.g., export_metadata.py. Start with imports: import requests, pandas as pd, time.
  4. Define your search query. Decide what you’re searching for. For example, if you want all articles with “machine learning” in the title published in 2023, you’d use a query string like query.title=machine+learning&filter=from-pub-date:2023-01-01,until-pub-date:2023-12-31. The Crossref API uses URL parameters, not JSON bodies.
  5. Make the API request. Use requests.get() with the base URL and your query. For Crossref: url = "https://api.crossref.org/works?" + query. Add a mailto parameter to be polite: &mailto=your@email.com.
  6. Parse the JSON response. The API returns a JSON object. Access the items with data["message"]["items"]. Each item contains fields like title (a list), author (a list of dicts), DOI, published-print or published-online.
  7. Extract the metadata you need. Write a loop that goes through each item and pulls out the fields you want. For example:
    records = []
    for item in items:
        title = item.get("title", [""])[0]
        authors = "; ".join([f"{a.get('given','')} {a.get('family','')}" for a in item.get("author", [])])
        doi = item.get("DOI", "")
        year = item.get("published-print", {}).get("date-parts", [[""]])[0][0]
        records.append({"Title": title, "Authors": authors, "DOI": doi, "Year": year})
        
  8. Convert to a DataFrame. After the loop, create a pandas DataFrame: df = pd.DataFrame(records).
  9. Export to CSV or Excel. Use df.to_csv("metadata.csv", index=False) or df.to_excel("metadata.xlsx", index=False). The index=False prevents an extra row number column.
  10. Handle pagination. The API returns a limited number of results per request (default 20). To get all results, loop through pages by incrementing the offset parameter (or cursor for Crossref) until you have all records. Add a time.sleep(1) between requests to respect rate limits.
  11. Run the script. Execute it with python export_metadata.py. Check the output file to ensure it contains the expected metadata.
  12. Automate the script. To run it on a schedule, use your operating system’s task scheduler (Task Scheduler on Windows, cron on macOS/Linux). For example, a cron job: 0 9 * * 1 python /path/to/export_metadata.py runs it every Monday at 9 AM.

Common Mistakes

  • Not URL-encoding the query. Spaces and special characters must be encoded (e.g., use %20 or + for spaces). Use requests.utils.quote() or the params argument in requests.get() to handle this automatically.
  • Assuming field names are consistent. Crossref returns some fields as lists (e.g., title is a list even for one title). Always check the structure.
  • Ignoring rate limits. Sending too many requests quickly can get your IP temporarily blocked. Always add a small delay between requests.
  • Forgetting to handle missing data. Not all records have all fields. Use .get() with default values to avoid KeyErrors.
  • Not checking the HTTP status code. A 404 or 403 means your request failed. Always check response.status_code before parsing.

Tips

  • Use the API’s filter parameters. They reduce the amount of data you need to process. For example, filter by type: filter=type:journal-article.
  • Test with a small query first. Start with a narrow query and print the first few records to verify the parsing logic.
  • Save the raw JSON. If you need to re-run without hitting the API, save the response to a file and read from it.
  • Use a virtual environment. This keeps your dependencies isolated and avoids version conflicts.
  • Consider using the habanero library. It’s a Python wrapper for Crossref that simplifies some steps, but the raw approach gives you more control.

Troubleshooting

  • I get a 401 Unauthorized error. If you’re using an API key, check that it’s correctly set in the headers. For Crossref, you don’t need a key, but if you’re using Semantic Scholar, make sure the key is included as Authorization: Bearer YOUR_KEY.
  • The script runs but the CSV is empty. Check the JSON response. Print data["message"]["total-results"] to see if there are results. If total is 0, your query may be too restrictive.
  • I get a KeyError for ‘author’. Some records don’t have an author field. Use item.get("author", []) to return an empty list instead.
  • The script times out. Increase the timeout in requests.get() (e.g., timeout=30). Also check your internet connection.
  • I need more than 1000 results. Crossref has a maximum of 1000 results per query. You’ll need to split your query by date range or use the cursor parameter for deep pagination.
  • My output file has weird characters. Ensure you specify the correct encoding when writing: df.to_csv("metadata.csv", index=False, encoding="utf-8").

Frequently Asked Questions

Do I need an API key for Crossref?

No, Crossref is free and open. Adding a mailto parameter is polite and helps them contact you if needed.

Can I use this with other APIs like Scopus or Web of Science?

Yes, but those require institutional access and API keys. The pattern is the same: construct a query, get JSON, parse, export.

How do I get the full abstract?

Crossref often includes abstracts, but they may be in JATS XML format. You’ll need to strip HTML tags. OpenAlex provides plain-text abstracts more easily.

What if I want to export metadata for a specific journal?

Use the container-title filter in Crossref. For example: filter=container-title:Nature.

Can I schedule this to run automatically?

Yes, use cron (macOS/Linux) or Task Scheduler (Windows). You can also run it as a GitHub Action if you prefer cloud-based automation.

How do I handle large numbers of results without hitting rate limits?

Use the cursor parameter in Crossref for deep pagination, and add a delay of 1-2 seconds between requests. Also, consider using the rows parameter to increase results per request (max 1000).

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →