|
8 | 8 |
|
9 | 9 | from __future__ import annotations |
10 | 10 |
|
11 | | -# Beautiful Soup - A library for pulling data out of HTML and XML files. Read more at: |
12 | | -# https://www.crummy.com/software/BeautifulSoup/bs4/doc |
| 11 | +import sys |
| 12 | + |
13 | 13 | # Apify SDK - A toolkit for building Apify Actors. Read more at: |
14 | 14 | # https://docs.apify.com/sdk/python |
15 | 15 | from apify import Actor |
16 | | -from bs4 import BeautifulSoup |
17 | | - |
18 | | -# HTTPX - A library for making asynchronous HTTP requests in Python. Read more at: |
19 | | -# https://www.python-httpx.org/ |
20 | | -from httpx import AsyncClient |
21 | 16 |
|
22 | 17 |
|
23 | 18 | async def main() -> None: |
24 | 19 | """Define a main entry point for the Apify Actor. |
25 | 20 |
|
26 | 21 | This coroutine is executed using `asyncio.run()`, so it must remain an asynchronous function for proper execution. |
27 | | - Asynchronous execution is required for communication with Apify platform, and it also enhances performance in |
28 | | - the field of web scraping significantly. |
| 22 | + Asynchronous execution is required for communication with the Apify platform. |
| 23 | +
|
| 24 | + This is a minimal, general-purpose Actor: it reads an input, does a little work with it, logs its progress, and |
| 25 | + stores a result in the dataset. Replace the body with whatever your Actor should do, for example a scraper, a |
| 26 | + browser automation, an AI agent, an MCP server, or a web server. |
29 | 27 | """ |
30 | 28 | async with Actor: |
31 | | - # Retrieve the input object for the Actor. The structure of input is defined in input_schema.json. |
32 | | - actor_input = await Actor.get_input() or {'url': 'https://apify.com/'} |
33 | | - url = actor_input.get('url') |
34 | | - if not url: |
35 | | - raise ValueError('Missing "url" attribute in input!') |
36 | | - |
37 | | - # Create an asynchronous HTTPX client for making HTTP requests. |
38 | | - async with AsyncClient() as client: |
39 | | - # Fetch the HTML content of the page, following redirects if necessary. |
40 | | - Actor.log.info(f'Sending a request to {url}') |
41 | | - response = await client.get(url, follow_redirects=True) |
42 | | - |
43 | | - # Parse the HTML content using Beautiful Soup and lxml parser. |
44 | | - soup = BeautifulSoup(response.content, 'lxml') |
45 | | - |
46 | | - # Extract all headings from the page (tag name and text). |
47 | | - headings = [] |
48 | | - for heading in soup.find_all(['h1', 'h2', 'h3', 'h4', 'h5', 'h6']): |
49 | | - heading_object = {'level': heading.name, 'text': heading.text} |
50 | | - Actor.log.info(f'Extracted heading: {heading_object}') |
51 | | - headings.append(heading_object) |
52 | | - |
53 | | - # Save the extracted headings to the dataset, which is a table-like storage. |
54 | | - await Actor.push_data(headings) |
| 29 | + # uv manages both the dependencies and the Python version, so the interpreter running here is exactly the |
| 30 | + # one pinned in `.python-version`. |
| 31 | + python_version = '.'.join(map(str, sys.version_info[:3])) |
| 32 | + Actor.log.info(f'Hello from a uv-managed Apify Actor, running on Python {python_version}!') |
| 33 | + |
| 34 | + # Retrieve the Actor input. The structure of the input is defined in `input_schema.json`. |
| 35 | + actor_input = await Actor.get_input() or {} |
| 36 | + name = actor_input.get('name', 'world') |
| 37 | + repeat = actor_input.get('repeat', 3) |
| 38 | + |
| 39 | + # Do something with the input. Here we simply greet the given name a few times. |
| 40 | + for i in range(1, repeat + 1): |
| 41 | + Actor.log.info(f'[{i}/{repeat}] Hello, {name}!') |
| 42 | + |
| 43 | + # Save a structured result to the dataset, which is a table-like storage. |
| 44 | + await Actor.push_data( |
| 45 | + { |
| 46 | + 'greeting': f'Hello, {name}!', |
| 47 | + 'repeated': repeat, |
| 48 | + 'python_version': python_version, |
| 49 | + 'managed_by': 'uv', |
| 50 | + } |
| 51 | + ) |
0 commit comments