Skip to main content

ResuMesh Scrapers Banner

resumesh-scrapers

Enterprise-Grade, Standalone, and Decoupled Web Scraping Engines for Portfolio Building

PyPI version Python versions License CI Status


resumesh-scrapers is a clean, modular, and robust Python library containing standalone scraping services for GitHub, Dev.to, Medium, Substack, Behance, NPM, and PyPI platforms. Originally developed as part of the ResuMesh ecosystem, it has been decoupled to serve as a reusable package for any resume, portfolio, or profile aggregator project.

🚀 Key Features

  • Robust Core Network Engine: Centralized HTTP request handling with standard retry mechanisms powered by tenacity and structured logging.
  • Fully Decoupled Models: Independent, clean data validation using pydantic v2, keeping data structures separated from database constraints.
  • Extensible Architecture: Platform scrapers are isolated in a plug-and-play layout under platforms/ allowing quick addition of new integrations (e.g. LinkedIn, GitLab).
  • Detailed Exceptions: Standardized exceptions hierarchy inheriting from ScraperError with HTTP status code details.

🛠️ Installation

pip install resumesh-scrapers

For Local Development (Editable mode)

git clone https://github.com/AtaCanYmc/resumesh-scrapers.git
cd resumesh-scrapers
pip install -e .

💡 Quick Start

Here is a simple example showing how to scrape your repository and blog statistics:

import asyncio
from resumesh_scrapers import (
    GitHubScraper,
    DevToScraper,
    MediumScraper,
    SubstackScraper,
    BehanceScraper,
    GitHubRepositoryModel,
    GitHubCommitModel,
    GitHubUserModel,
    DevToArticleModel,
    MediumEntryModel,
    SubstackEntryModel,
    BehanceProjectModel,
)

async def main():
    # 1. Scraping GitHub Repositories, README Repos, Commits, and User Lists
    github = GitHubScraper()
    repos: list[GitHubRepositoryModel] = await github.fetch_data(
        username="octocat",
        pat="ghp_...",  # optional PAT token to bypass rate limit
        include_forks=False
    )
    print(f"Fetched {len(repos)} repositories.")

    # Fetch profile README repository details
    readme_repo = await github.fetch_readme_repo("octocat")
    if readme_repo:
        print(f"Profile README Repository: {readme_repo.html_url}")

    # Fetch recent commits (default since: last 7 days)
    commits: list[GitHubCommitModel] = await github.fetch_commits("octocat")
    print(f"Fetched {len(commits)} commits.")

    # Fetch followers and following list
    followers: list[GitHubUserModel] = await github.fetch_followers("octocat", per_page=10)
    print(f"Fetched {len(followers)} followers.")


    # 2. Scraping Dev.to Articles
    devto = DevToScraper()
    devto_posts: list[DevToArticleModel] = await devto.fetch_data("atacanymc")
    print(f"Fetched {len(devto_posts)} Dev.to articles.")

    # 3. Scraping Substack Publications
    substack = SubstackScraper()
    substack_posts: list[SubstackEntryModel] = await substack.fetch_data("atacan")
    print(f"Fetched {len(substack_posts)} Substack posts.")

    # 4. Scraping Behance Projects
    behance = BehanceScraper()
    behance_projects: list[BehanceProjectModel] = await behance.fetch_data(
        username="atacanymc",
        api_key="your_behance_api_key"  # optional, falls back to HTML scraping if not provided
    )
    print(f"Fetched {len(behance_projects)} Behance projects.")

if __name__ == "__main__":
    asyncio.run(main())

🗺️ Clean Architecture

The codebase has been refactored to enforce separation of concerns, decoupling models, platforms, and network layers:

src/resumesh_scrapers/
├── core/                       # Shared network and utility systems
│   ├── client.py               # Central HTTP requester with tenacity retries
│   └── __init__.py
├── platforms/                  # Individual platform scrapers
│   ├── github.py
│   ├── devto.py
│   ├── medium.py
│   ├── substack.py
│   ├── behance.py
│   ├── npm.py
│   ├── pypi.py
│   └── __init__.py
└── models/                     # Platform-specific Pydantic validation schemas
    ├── github.py
    ├── devto.py
    ├── medium.py
    ├── substack.py
    ├── behance.py
    ├── npm.py
    ├── pypi.py
    └── __init__.py

📊 Models & Capabilities

Platform Scraper Class Response Model Captured Data Features
GitHub GitHubScraper GitHubRepositoryModel
GitHubCommitModel
GitHubUserModel
Repos: Stars, Forks, languages, watchers.
Commits: author, message, sha, repo, date, HTML link.
Users: login, avatar URL, HTML link (followers/following).
Dev.to DevToScraper DevToArticleModel Title, URL, Tags, Reading time, Publishing date
Medium MediumScraper MediumEntryModel Title, RSS Summary, UTM-stripped link, Category tags
Substack SubstackScraper SubstackEntryModel Title, RSS Summary, link, tags
Behance BehanceScraper BehanceProjectModel Project title, gallery URL, appreciation count, publication dates (supports API client keys)
NPM NpmScraper NpmSearchResultModel Maintainer packages, keywords, version history, publisher metadata
PyPI PyPIScraper PyPiPackageModel Releases, download statistics, license, project metadata

⚠️ Exception Handling

All scraper exceptions inherit from ScraperError to simplify integration errors:

from resumesh_scrapers.exceptions import ScraperError, GitHubScraperError

try:
    repos = await github_scraper.fetch_data("some_username")
except GitHubScraperError as e:
    print(f"GitHub API Error: {e.message} (HTTP {e.status_code})")
except ScraperError as e:
    print(f"Generic Scraping Exception: {e}")

🤝 Contributing

We welcome contributions to add more platforms (such as LinkedIn, GitLab, or Dribbble) or optimize parsers. Please open a Pull Request or file an issue to discuss your ideas!

  1. Fork the Project.
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature).
  3. Commit your Changes (git commit -m 'Add some AmazingFeature').
  4. Push to the Branch (git push origin feature/AmazingFeature).
  5. Open a Pull Request.

📄 License

Distributed under the Apache 2.0 License. See LICENSE for more information.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

resumesh_scrapers-0.8.0.tar.gz (35.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

resumesh_scrapers-0.8.0-py3-none-any.whl (31.1 kB view details)

Uploaded Python 3

File details

Details for the file resumesh_scrapers-0.8.0.tar.gz.

File metadata

  • Download URL: resumesh_scrapers-0.8.0.tar.gz
  • Upload date:
  • Size: 35.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for resumesh_scrapers-0.8.0.tar.gz
Algorithm Hash digest
SHA256 1adfdfe55e79bb7319abbdba2706d1e6815b44c8455cefb74c275ed13b4feee5
MD5 526867880c94ec6c7785054b949cbebb
BLAKE2b-256 8fe3d7885bbaa1a9dcd61bcefa5dfd0087d424473d8ea286a28ec69b64ed311c

See more details on using hashes here.

Provenance

The following attestation bundles were made for resumesh_scrapers-0.8.0.tar.gz:

Publisher: cd.yml on AtaCanYmc/resumesh-scrapers

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file resumesh_scrapers-0.8.0-py3-none-any.whl.

File metadata

File hashes

Hashes for resumesh_scrapers-0.8.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9041e731e33d376dcd2a4281a63a5983dbca3c5c249148ee7b61d4d8f14dbd13
MD5 71e1d285c84c00f209aebcb456cda926
BLAKE2b-256 22e2a7b5260ec77cd53d3bc9a6df26431ff974d5d7bb0c25632c2cc34e68b6c0

See more details on using hashes here.

Provenance

The following attestation bundles were made for resumesh_scrapers-0.8.0-py3-none-any.whl:

Publisher: cd.yml on AtaCanYmc/resumesh-scrapers

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.9.0

2 files

This release

0.8.0 This release

2 files

0.6.0

2 files

0.4.0

2 files

0.3.0

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page