Skip to main content

Standalone, reusable web scraping services for GitHub, Dev.to, and Medium — extracted from the ResuMesh project.

Project description

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,
    DevToArticleModel,
    MediumEntryModel,
    SubstackEntryModel,
    BehanceProjectModel,
)

async def main():
    # 1. Scraping GitHub Repositories
    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.")

    # 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 Stars, Forks, Main languages, Visibility, Watchers, Creation dates
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.

Project details


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.4.0.tar.gz (31.9 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.4.0-py3-none-any.whl (29.4 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for resumesh_scrapers-0.4.0.tar.gz
Algorithm Hash digest
SHA256 d9ea7582dfacef82ee385d0ce96b03bc98e923c344128497b81d9301c1cbd9c3
MD5 08d39f8111fdfc416e0f86a0f0fd66e5
BLAKE2b-256 731a79329ef142aa6baf1a9cf0225d01b539da40394a638c68cb9e1466c99560

See more details on using hashes here.

Provenance

The following attestation bundles were made for resumesh_scrapers-0.4.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.4.0-py3-none-any.whl.

File metadata

File hashes

Hashes for resumesh_scrapers-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 225de0a5fe21e5fdc1720072e194d7b7825bd6241bed74bd7e0568b64b2ce1e3
MD5 69669c99a2311129e6c1f6eb8c1adf77
BLAKE2b-256 7f2bd7dfb410d470dbb7d8f5c2c31056b9a6f9dc2bf40c4a11ddf915e49a1746

See more details on using hashes here.

Provenance

The following attestation bundles were made for resumesh_scrapers-0.4.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.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page