[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/15bubbles/async-python/main/scrape.py [Back]  [Original]

import asyncio
from asyncio.queues import Queue
from typing import (
    AsyncGenerator,
    Awaitable,
    Callable,
    Iterable,
    Tuple,
    TypeVar,
)

import aiofiles
import aiohttp


# CONSTANTS

MAX_WORKERS = 50

BASE_URL = "https://jsonplaceholder.typicode.com/posts"
URLS = [f"{BASE_URL}/{i}" for i in range(0, 1000)]


# MAIN REQUEST MAKING AND FILE WRITING LOGIC


async def get_url(session: aiohttp.ClientSession, url: str) -> str:
    response = await session.request("GET", url)
    data = await response.text()

    return data


async def write_to_file(filename: str, data: str) -> None:
    async with aiofiles.open(filename, mode="w") as file_handle:
        await file_handle.write(data)


async def request_and_write_results(
    session: aiohttp.ClientSession, url: str, filename: str
) -> None:
    data = await get_url(session, url)
    await write_to_file(filename, data)


# HELPER FUNCTIONS

_IterableItem = TypeVar("_IterableItem")


async def async_enumerate(
    urls: Iterable[_IterableItem],
) -> AsyncGenerator[Tuple[int, _IterableItem], None]:
    for idx, url in enumerate(urls):
        yield idx, url


async def queued_worker_wrapper(
    coroutine_function: Callable[[aiohttp.ClientSession, str, str], Awaitable],
    session: aiohttp.ClientSession,
    queue: Queue,
) -> None:
    while True:
        print("Getting item from queue")
        url, filename = await queue.get()
        print(f"Got {url}, {filename} from queue")
        print(f"Running coroutine for {url}, {filename}")
        await coroutine_function(session, url, filename)
        print(f"Coruoutine finished for {url}, {filename}")
        print("Letting queue know that the task is done")
        queue.task_done()


# MAIN FUNCTION


async def main():
    queue = Queue(MAX_WORKERS)

    async with aiohttp.ClientSession() as session:
        workers = [
            asyncio.create_task(
                queued_worker_wrapper(request_and_write_results, session, queue)
            )
            for _ in range(MAX_WORKERS)
        ]

        async for idx, url in async_enumerate(URLS):
            filename = f"{idx}.txt"
            queue_item = (url, filename)
            await queue.put((url, filename))
            print(f"Item {queue_item} added into the queue")

        await queue.join()
        print("Queue joined")

    for worker in workers:
        worker.cancel()


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

Web Proxy Viewer  |  New URL  |  Original Page