Catalog PyPI
PACKAGE EXPLORERView in registry

academic-phd-scraper

PyPI

A Python module to scrape PhD offers from academicpositions.com

academicacademicpositionsjobsphdpositionsscraper
Versions collected1
Direct dependencies6From release 1.0.0
Last observed20 Oct, 17:50 UTC

README

Version 1.0.0 documentation

PhD Scraper for Academic Positions

A Python module to scrape PhD offers from academicpositions.com.

Features

  • 🔍 Scrape PhD positions with filtering by country and field
  • 📋 Extract detailed information: title, university, requirements, deadlines, etc.
  • 💾 Export to JSON, CSV, or Markdown formats
  • 🔄 Iterator support for memory-efficient processing
  • ⚡ Concurrent fetching with rate limiting
  • 🖥️ Command-line interface included

Installation

# Clone or navigate to the project directory
cd PhDFinder

# Install dependencies
pip install -e .

# Or install dependencies directly
pip install requests beautifulsoup4

Quick Start

Python API

from phd_scraper import AcademicPositionsScraper, PhDPosition

# Create scraper instance
scraper = AcademicPositionsScraper()

# Get PhD positions (basic usage)
positions = scraper.get_phd_positions(max_pages=2)

# Print results
for pos in positions:
    print(f"{pos.title} at {pos.university}")
    print(f"  Location: {pos.location}")
    print(f"  Deadline: {pos.deadline}")
    print(f"  URL: {pos.url}")
    print()

Filter by Country and Field

# Get Computer Science PhDs in Germany
positions = scraper.get_phd_positions(
    max_pages=3,
    country="germany",
    field="computer-science"
)

# Get Physics PhDs in Switzerland
positions = scraper.get_phd_positions(
    country="switzerland",
    field="physics"
)

Search with Keywords

# Search for specific keywords
positions = scraper.search_positions(
    keywords=["machine learning", "deep learning", "AI"],
    country="germany",
    max_pages=5
)

Export Results

from phd_scraper.utils import export_to_json, export_to_csv, export_to_markdown

# Get positions
positions = scraper.get_phd_positions(max_pages=2)

# Export to different formats
export_to_json(positions, "phd_positions.json")
export_to_csv(positions, "phd_positions.csv")
export_to_markdown(positions, "phd_positions.md")

Memory-Efficient Iterator

# Process positions one at a time (good for large datasets)
for position in scraper.iter_positions(country="sweden"):
    print(position.summary())
    # Process each position without loading all into memory

Command-Line Interface

# Basic usage - get 2 pages of positions
python -m phd_scraper --pages 2

# Filter by country and field
python -m phd_scraper --country germany --field computer-science

# Export to JSON
python -m phd_scraper --output positions.json --format json --pages 3

# Export to CSV
python -m phd_scraper --output positions.csv --format csv

# Search with keywords
python -m phd_scraper --keywords "machine learning" "neural networks" --pages 5

# List available filters
python -m phd_scraper --list-filters

# Fast mode (skip detailed info)
python -m phd_scraper --no-details --pages 10

# Verbose output
python -m phd_scraper --verbose --pages 1

Available Filters

Countries

  • germany, sweden, belgium, switzerland, netherlands, finland
  • norway, austria, france, united-kingdom, united-states
  • italy, spain, denmark, luxembourg

Fields

  • computer-science, physics, chemistry, biology, mathematics
  • engineering, medicine, economics, social-science, geosciences
  • artificial-intelligence, machine-learning, psychology, law

Data Model

Each PhDPosition object contains:

FieldDescription
titlePosition title
universityUniversity/employer name
locationFull location (city, country)
countryCountry name
cityCity name
deadlineApplication deadline
published_dateWhen the position was published
job_typeType of position (PhD)
fieldsResearch fields/disciplines
descriptionFull job description
requirementsQualifications needed
benefitsWhat the position offers
urlLink to the job posting
apply_urlDirect application link

Configuration

scraper = AcademicPositionsScraper(
    request_delay=1.5,      # Delay between requests (seconds)
    timeout=30,             # Request timeout (seconds)
    max_retries=3,          # Number of retry attempts
    user_agent="Custom UA"  # Custom user agent string
)

Utility Functions

from phd_scraper.utils import (
    filter_positions,
    deduplicate_positions,
    sort_positions
)

# Filter positions
filtered = filter_positions(
    positions,
    keywords=["AI", "robotics"],
    countries=["germany", "switzerland"],
    has_deadline=True
)

# Remove duplicates
unique = deduplicate_positions(positions)

# Sort by field
sorted_pos = sort_positions(positions, by="deadline")

Example Output

[1] PhD Position in AI and Strategy
    University: ETH Zürich
    Location: Zurich, Switzerland
    Deadline: Unspecified
    Fields: Business Administration, Management, Artificial Intelligence
    URL: https://academicpositions.com/ad/eth-zurich/2026/...

[2] Doctoral student in Radiofrequency ranging for Lunar orbits
    University: KTH Royal Institute of Technology
    Location: Stockholm, Sweden
    Deadline: 2026-01-31 (Europe/Stockholm)
    Fields: Physics, Space Science
    URL: https://academicpositions.com/ad/kth-royal-institute-of-technology/2025/...

Important Notes

  • Rate Limiting: The scraper includes built-in delays to be respectful of the server
  • Terms of Service: Please review academicpositions.com's terms before scraping
  • Data Accuracy: Always verify position details on the original website
  • Updates: Website structure may change; report issues if scraping fails

License

MIT License

Downloads & popularity

1downloads
1-day window · source-reported counts19 Oct 2026
1890
2026-07-23: 5 · observed 2026-10-20T18:41:32.5560937Z · period 2026-07-23–2026-07-232026-07-26: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-07-26–2026-07-262026-07-27: 2 · observed 2026-10-20T18:41:32.5560937Z · period 2026-07-27–2026-07-272026-07-28: 6 · observed 2026-10-20T18:41:32.5560937Z · period 2026-07-28–2026-07-282026-07-30: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-07-30–2026-07-302026-08-01: 2 · observed 2026-10-20T18:41:32.5560937Z · period 2026-08-01–2026-08-012026-08-02: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-08-02–2026-08-022026-08-03: 4 · observed 2026-10-20T18:41:32.5560937Z · period 2026-08-03–2026-08-032026-08-04: 4 · observed 2026-10-20T18:41:32.5560937Z · period 2026-08-04–2026-08-042026-08-05: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-08-05–2026-08-052026-08-06: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-08-06–2026-08-062026-08-09: 3 · observed 2026-10-20T18:41:32.5560937Z · period 2026-08-09–2026-08-092026-08-13: 2 · observed 2026-10-20T18:41:32.5560937Z · period 2026-08-13–2026-08-132026-08-14: 4 · observed 2026-10-20T18:41:32.5560937Z · period 2026-08-14–2026-08-142026-08-17: 5 · observed 2026-10-20T18:41:32.5560937Z · period 2026-08-17–2026-08-172026-08-18: 18 · observed 2026-10-20T18:41:32.5560937Z · period 2026-08-18–2026-08-182026-08-20: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-08-20–2026-08-202026-08-23: 3 · observed 2026-10-20T18:41:32.5560937Z · period 2026-08-23–2026-08-232026-08-24: 8 · observed 2026-10-20T18:41:32.5560937Z · period 2026-08-24–2026-08-242026-08-27: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-08-27–2026-08-272026-08-28: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-08-28–2026-08-282026-08-31: 2 · observed 2026-10-20T18:41:32.5560937Z · period 2026-08-31–2026-08-312026-09-01: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-09-01–2026-09-012026-09-03: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-09-03–2026-09-032026-09-05: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-09-05–2026-09-052026-09-06: 5 · observed 2026-10-20T18:41:32.5560937Z · period 2026-09-06–2026-09-062026-09-07: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-09-07–2026-09-072026-09-08: 3 · observed 2026-10-20T18:41:32.5560937Z · period 2026-09-08–2026-09-082026-09-09: 2 · observed 2026-10-20T18:41:32.5560937Z · period 2026-09-09–2026-09-092026-09-10: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-09-10–2026-09-102026-09-12: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-09-12–2026-09-122026-09-15: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-09-15–2026-09-152026-09-16: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-09-16–2026-09-162026-09-18: 3 · observed 2026-10-20T18:41:32.5560937Z · period 2026-09-18–2026-09-182026-09-20: 2 · observed 2026-10-20T18:41:32.5560937Z · period 2026-09-20–2026-09-202026-09-21: 2 · observed 2026-10-20T18:41:32.5560937Z · period 2026-09-21–2026-09-212026-09-24: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-09-24–2026-09-242026-09-26: 2 · observed 2026-10-20T18:41:32.5560937Z · period 2026-09-26–2026-09-262026-09-27: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-09-27–2026-09-272026-09-29: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-09-29–2026-09-292026-09-30: 3 · observed 2026-10-20T18:41:32.5560937Z · period 2026-09-30–2026-09-302026-10-01: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-10-01–2026-10-012026-10-04: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-10-04–2026-10-042026-10-05: 3 · observed 2026-10-20T18:41:32.5560937Z · period 2026-10-05–2026-10-052026-10-06: 4 · observed 2026-10-20T18:41:32.5560937Z · period 2026-10-06–2026-10-062026-10-07: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-10-07–2026-10-072026-10-08: 3 · observed 2026-10-20T18:41:32.5560937Z · period 2026-10-08–2026-10-082026-10-09: 3 · observed 2026-10-20T18:41:32.5560937Z · period 2026-10-09–2026-10-092026-10-10: 4 · observed 2026-10-20T18:41:32.5560937Z · period 2026-10-10–2026-10-102026-10-11: 3 · observed 2026-10-20T18:41:32.5560937Z · period 2026-10-11–2026-10-112026-10-13: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-10-13–2026-10-132026-10-14: 2 · observed 2026-10-20T18:41:32.5560937Z · period 2026-10-14–2026-10-142026-10-18: 3 · observed 2026-10-20T18:41:32.5560937Z · period 2026-10-18–2026-10-182026-10-19: 1 · observed 2026-10-20T18:41:32.5560937Z · period 2026-10-19–2026-10-19
23 Jul19 Oct

pypistats · 54 observations shown. Missing days are unknown. Source category: overall: without mirrors.

View observed values
Date / source periodValueObserved at
2026-10-19 – 2026-10-1912026-10-20T18:41:32.5560937Z
2026-10-18 – 2026-10-1832026-10-20T18:41:32.5560937Z
2026-10-14 – 2026-10-1422026-10-20T18:41:32.5560937Z
2026-10-13 – 2026-10-1312026-10-20T18:41:32.5560937Z
2026-10-11 – 2026-10-1132026-10-20T18:41:32.5560937Z
2026-10-10 – 2026-10-1042026-10-20T18:41:32.5560937Z
2026-10-09 – 2026-10-0932026-10-20T18:41:32.5560937Z
2026-10-08 – 2026-10-0832026-10-20T18:41:32.5560937Z
2026-10-07 – 2026-10-0712026-10-20T18:41:32.5560937Z
2026-10-06 – 2026-10-0642026-10-20T18:41:32.5560937Z
2026-10-05 – 2026-10-0532026-10-20T18:41:32.5560937Z
2026-10-04 – 2026-10-0412026-10-20T18:41:32.5560937Z
2026-10-01 – 2026-10-0112026-10-20T18:41:32.5560937Z
2026-09-30 – 2026-09-3032026-10-20T18:41:32.5560937Z
2026-09-29 – 2026-09-2912026-10-20T18:41:32.5560937Z
2026-09-27 – 2026-09-2712026-10-20T18:41:32.5560937Z
2026-09-26 – 2026-09-2622026-10-20T18:41:32.5560937Z
2026-09-24 – 2026-09-2412026-10-20T18:41:32.5560937Z
2026-09-21 – 2026-09-2122026-10-20T18:41:32.5560937Z
2026-09-20 – 2026-09-2022026-10-20T18:41:32.5560937Z
2026-09-18 – 2026-09-1832026-10-20T18:41:32.5560937Z
2026-09-16 – 2026-09-1612026-10-20T18:41:32.5560937Z
2026-09-15 – 2026-09-1512026-10-20T18:41:32.5560937Z
2026-09-12 – 2026-09-1212026-10-20T18:41:32.5560937Z
2026-09-10 – 2026-09-1012026-10-20T18:41:32.5560937Z
2026-09-09 – 2026-09-0922026-10-20T18:41:32.5560937Z
2026-09-08 – 2026-09-0832026-10-20T18:41:32.5560937Z
2026-09-07 – 2026-09-0712026-10-20T18:41:32.5560937Z
2026-09-06 – 2026-09-0652026-10-20T18:41:32.5560937Z
2026-09-05 – 2026-09-0512026-10-20T18:41:32.5560937Z
2026-09-03 – 2026-09-0312026-10-20T18:41:32.5560937Z
2026-09-01 – 2026-09-0112026-10-20T18:41:32.5560937Z
2026-08-31 – 2026-08-3122026-10-20T18:41:32.5560937Z
2026-08-28 – 2026-08-2812026-10-20T18:41:32.5560937Z
2026-08-27 – 2026-08-2712026-10-20T18:41:32.5560937Z
2026-08-24 – 2026-08-2482026-10-20T18:41:32.5560937Z
2026-08-23 – 2026-08-2332026-10-20T18:41:32.5560937Z
2026-08-20 – 2026-08-2012026-10-20T18:41:32.5560937Z
2026-08-18 – 2026-08-18182026-10-20T18:41:32.5560937Z
2026-08-17 – 2026-08-1752026-10-20T18:41:32.5560937Z
2026-08-14 – 2026-08-1442026-10-20T18:41:32.5560937Z
2026-08-13 – 2026-08-1322026-10-20T18:41:32.5560937Z
2026-08-09 – 2026-08-0932026-10-20T18:41:32.5560937Z
2026-08-06 – 2026-08-0612026-10-20T18:41:32.5560937Z
2026-08-05 – 2026-08-0512026-10-20T18:41:32.5560937Z
2026-08-04 – 2026-08-0442026-10-20T18:41:32.5560937Z
2026-08-03 – 2026-08-0342026-10-20T18:41:32.5560937Z
2026-08-02 – 2026-08-0212026-10-20T18:41:32.5560937Z
2026-08-01 – 2026-08-0122026-10-20T18:41:32.5560937Z
2026-07-30 – 2026-07-3012026-10-20T18:41:32.5560937Z
2026-07-28 – 2026-07-2862026-10-20T18:41:32.5560937Z
2026-07-27 – 2026-07-2722026-10-20T18:41:32.5560937Z
2026-07-26 – 2026-07-2612026-10-20T18:41:32.5560937Z
2026-07-23 – 2026-07-2352026-10-20T18:41:32.5560937Z

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
1.0.014 Jan 20266

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 17:50 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:1f5719486e04c768430111a2e30d7877ea15cf9614f893f31bc6f81517af4ac4