Repository: apify/crawlee-python
File: docs/guides/code_examples/creating_web_archive/manual_archiving_playwright_crawler.py (Python)

Code before:
        headless=False,
    )

    # Create a WARC archive file a prepare the writer.
    archive = 'example2.warc.gz'
    with open(archive, 'wb') as output:
        writer = WARCWriter(output, gzip=True)

        # Create a WARC info record to store metadata about the archive.
        warcinfo_payload = {
            'software': 'Crawlee',
            'format': 'WARC/1.1',
            'description': 'Example archive created with PlaywrightCrawler',
        }
        writer.write_record(writer.create_warcinfo_record(archive, warcinfo_payload))

        @crawler.pre_navigation_hook
        async def archiving_hook(context: PlaywrightPreNavCrawlingContext) -> None:
            # Ensure that all responses with additional resources are archived
            context.page.on(
                'requestfinished',
                partial(archive_response, logger=context.log, writer=writer),
            )

        @crawler.router.default_handler
        async def request_handler(context: PlaywrightCrawlingContext) -> None:
            # For some sites, where the content loads dynamically,
            # it is needed to scroll the page to load all content.
            # It slows down the crawling, but ensures that all content is loaded.
            await context.infinite_scroll()
            await context.enqueue_links()

        await crawler.run(['https://crawlee.dev/'])


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


Review comment (suggestion):
`on("requestfinished")` returns a `Request` instance ([docs](https://playwright.dev/python/docs/api/class-page#page-event-request-finished)), so an additional `.response()` call is needed.

Code after:

async def main() -> None:
    crawler = PlaywrightCrawler(
        max_requests_per_crawl=1,
        headless=False,
    )

    # Create a WARC archive file a prepare the writer.
    archive = Path('example.warc.gz')
    with archive.open('wb') as output:
        writer = WARCWriter(output, gzip=True)

        # Create a WARC info record to store metadata about the archive.
        warcinfo_payload = {
            'software': 'Crawlee',
            'format': 'WARC/1.1',
            'description': 'Example archive created with PlaywrightCrawler',
        }
        writer.write_record(writer.create_warcinfo_record(archive.name, warcinfo_payload))

        @crawler.pre_navigation_hook
        async def archiving_hook(context: PlaywrightPreNavCrawlingContext) -> None:
            # Ensure that all responses with additional resources are archived
            context.page.on(
                'requestfinished',
                partial(archive_response, logger=context.log, writer=writer),
            )

        @crawler.router.default_handler
        async def request_handler(context: PlaywrightCrawlingContext) -> None:
            # For some sites, where the content loads dynamically,
            # it is needed to scroll the page to load all content.
            # It slows down the crawling, but ensures that all content is loaded.
            await context.infinite_scroll()
            await context.enqueue_links(strategy='same-domain')

        await crawler.run(['https://crawlee.dev/'])


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