Skip to content

Commit a0a3253

Browse files
committed
feat: Switch to Camoufox
1 parent 582068e commit a0a3253

16 files changed

Lines changed: 281 additions & 103 deletions

File tree

.devcontainer/post-create.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ if [ -S /var/run/docker.sock ]; then
1111
fi
1212

1313
uv sync --all-groups
14-
uv run playwright install chromium --with-deps
14+
uv run camoufox fetch

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ This repository contains the following projects:
3838
- The number of DOM elements in the page
3939
- The size of the page
4040
- The number of external requests of the page
41-
- [Ecoindex Scraper](projects/ecoindex_scraper/README.md): This module provides a simple interface to get the [Ecoindex](http://www.ecoindex.fr) based on a URL. It uses [Playwright](https://playwright.dev/) to get the DOM elements, size and requests of the page.
41+
- [Ecoindex Scraper](projects/ecoindex_scraper/README.md): This module provides a simple interface to get the [Ecoindex](http://www.ecoindex.fr) based on a URL. It uses [Camoufox](https://camoufox.com/) to get the DOM elements, size and requests of the page.
4242
- [Ecoindex CLI](projects/ecoindex_cli/README.md): This module provides a CLI tool to get the [Ecoindex](http://www.ecoindex.fr) based on a URL. It uses the [Ecoindex Scraper](projects/ecoindex_scraper/README.md) module.
4343
- [Ecoindex API](projects/ecoindex_api/README.md): This module provides a REST API to get the [Ecoindex](http://www.ecoindex.fr) based on a URL. It uses the [Ecoindex Scraper](projects/ecoindex_scraper/README.md) module.
4444

@@ -80,4 +80,4 @@ Please also refer to the mentions provided in the code files for specifics on th
8080

8181
## [Contributing](CONTRIBUTING.md)
8282

83-
## [Code of conduct](CODE_OF_CONDUCT.md)
83+
## [Code of conduct](CODE_OF_CONDUCT.md)

bases/ecoindex/worker/tasks.py

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
from ecoindex.models.tasks import QueueTaskError, QueueTaskResult
2121
from ecoindex.scraper.scrap import EcoindexScraper
2222
from ecoindex.worker_component import app
23-
from playwright._impl._errors import Error as WebDriverException
2423
from sentry_sdk import init as sentry_init
2524

2625
if Settings().GLITCHTIP_DSN:
@@ -97,8 +96,34 @@ async def async_ecoindex_task(
9796
),
9897
)
9998

100-
except WebDriverException as exc:
101-
if exc.message and "ERR_NAME_NOT_RESOLVED" in exc.message:
99+
except TypeError as exc:
100+
return QueueTaskResult(
101+
status=TaskStatus.FAILURE,
102+
error=QueueTaskError(
103+
url=url, # type: ignore
104+
exception=EcoindexContentTypeError.__name__,
105+
status_code=520,
106+
message=exc.args[0],
107+
detail={"mimetype": None},
108+
),
109+
)
110+
111+
except EcoindexScraperStatusException as exc:
112+
return QueueTaskResult(
113+
status=TaskStatus.FAILURE,
114+
error=QueueTaskError(
115+
url=url, # type: ignore
116+
status_code=521,
117+
exception=EcoindexStatusError.__name__,
118+
message=exc.message,
119+
detail={"status": exc.status},
120+
),
121+
)
122+
123+
except Exception as exc:
124+
message = getattr(exc, "message", str(exc))
125+
126+
if message and "ERR_NAME_NOT_RESOLVED" in message:
102127
return QueueTaskResult(
103128
status=TaskStatus.FAILURE,
104129
error=QueueTaskError(
@@ -113,7 +138,7 @@ async def async_ecoindex_task(
113138
),
114139
)
115140

116-
if exc.message and "ERR_CONNECTION_TIMED_OUT" in exc.message:
141+
if message and "ERR_CONNECTION_TIMED_OUT" in message:
117142
return QueueTaskResult(
118143
status=TaskStatus.FAILURE,
119144
error=QueueTaskError(
@@ -134,35 +159,11 @@ async def async_ecoindex_task(
134159
url=url, # type: ignore
135160
exception=type(exc).__name__,
136161
status_code=500,
137-
message=str(exc.message) if exc.message else "",
162+
message=message,
138163
detail=await format_exception_response(exception=exc),
139164
),
140165
)
141166

142-
except TypeError as exc:
143-
return QueueTaskResult(
144-
status=TaskStatus.FAILURE,
145-
error=QueueTaskError(
146-
url=url, # type: ignore
147-
exception=EcoindexContentTypeError.__name__,
148-
status_code=520,
149-
message=exc.args[0],
150-
detail={"mimetype": None},
151-
),
152-
)
153-
154-
except EcoindexScraperStatusException as exc:
155-
return QueueTaskResult(
156-
status=TaskStatus.FAILURE,
157-
error=QueueTaskError(
158-
url=url, # type: ignore
159-
status_code=521,
160-
exception=EcoindexStatusError.__name__,
161-
message=exc.message,
162-
detail={"status": exc.status},
163-
),
164-
)
165-
166167

167168
@app.task(
168169
name="ecoindex.batch_import",
@@ -202,7 +203,7 @@ async def async_ecoindex_batch_import_task(
202203
return QueueTaskResult(
203204
status=TaskStatus.FAILURE,
204205
error=QueueTaskError(
205-
url=None, # type: ignore
206+
url=None,
206207
exception=type(exc).__name__,
207208
status_code=500,
208209
message=str(exc.message) if exc.message else "", # type: ignore

components/ecoindex/scraper/scrap.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,18 @@
33
from datetime import datetime
44
from time import sleep
55
from uuid import uuid4
6+
from typing import Any, cast
67

78
from ua_generator.user_agent import UserAgent
89
from ua_generator import generate as ua_generate
910

11+
from camoufox.async_api import AsyncCamoufox
12+
1013
from ecoindex.compute import compute_ecoindex
1114
from ecoindex.exceptions.scraper import EcoindexScraperStatusException
1215
from ecoindex.models.compute import PageMetrics, Result, ScreenShot, WindowSize
1316
from ecoindex.models.scraper import MimetypeAggregation, RequestItem, Requests
1417
from ecoindex.utils.screenshots import convert_screenshot_to_webp, set_screenshot_rights
15-
from playwright._impl._api_structures import SetCookieParam, ViewportSize
16-
from playwright.async_api import async_playwright
1718
from typing_extensions import deprecated
1819

1920

@@ -30,7 +31,7 @@ def __init__(
3031
page_load_timeout: int = 20,
3132
headless: bool = True,
3233
basic_auth: str | None = None,
33-
cookies: list[SetCookieParam] = [],
34+
cookies: list[dict[str, object]] = [],
3435
custom_headers: dict[str, str] = {},
3536
logger=None,
3637
):
@@ -84,16 +85,13 @@ async def get_requests_by_category(self) -> MimetypeAggregation:
8485
return self.all_requests.aggregation
8586

8687
async def scrap_page(self) -> PageMetrics:
87-
async with async_playwright() as p:
88-
browser = await p.chromium.launch(
89-
headless=self.headless, args=["--disable-software-rasterizer"]
90-
)
88+
async with AsyncCamoufox(
89+
headless=self.headless,
90+
window=(self.window_size.width, self.window_size.height),
91+
) as browser_handle:
92+
browser = cast(Any, browser_handle)
9193
self.context = await browser.new_context(
9294
record_har_path=self.har_temp_file_path,
93-
screen=ViewportSize(
94-
width=self.window_size.width,
95-
height=self.window_size.height,
96-
),
9795
ignore_https_errors=True,
9896
http_credentials={
9997
"username": self.basic_auth.split(":")[0],
@@ -103,7 +101,7 @@ async def scrap_page(self) -> PageMetrics:
103101
else None,
104102
extra_http_headers=self.custom_headers,
105103
)
106-
await self.context.add_cookies(self.cookies)
104+
await self.context.add_cookies(cast(Any, self.cookies))
107105
self.page = await self.context.new_page()
108106
response = await self.page.goto(self.url)
109107
await self.check_page_response(response)

projects/ecoindex_api/Taskfile.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,8 @@ tasks:
209209
- echo "Initialize the project for development"
210210
- echo "Install uv dependencies"
211211
- task: uv:install
212-
- echo "Install playwright"
213-
- task: uv:install-playwright
212+
- echo "Install Camoufox"
213+
- task: uv:install-camoufox
214214
- echo "Create the environment file"
215215
- task: init-env
216216
- echo "Create the database"

projects/ecoindex_api/docker/worker/dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ COPY projects/ecoindex_api/dist/$wheel $wheel
2424
RUN pip install --no-cache-dir $wheel
2525
RUN pip install --no-cache-dir aiomysql
2626

27-
RUN playwright install chromium --with-deps
27+
RUN uv run camoufox fetch
2828

2929
RUN rm -rf $wheel requirements.txt /tmp/dist /var/lib/{apt,dpkg,cache,log}/
3030

projects/ecoindex_api/pyproject.toml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ dependencies = [
1212
"celery>=5.3.4",
1313
"cryptography>=44.0.2",
1414
"fastapi>=0.109.1",
15-
"playwright>=1.39.0",
16-
"playwright-stealth>=1.0.6",
15+
"camoufox>=0.4.11",
1716
"pydantic[email]>=2.1.1,<=2.4.2",
1817
"pydantic-settings>=2.0.3",
1918
"pyyaml>=6.0.1",
@@ -41,8 +40,7 @@ backend = [
4140
]
4241
worker = [
4342
"pillow>=12.2.0",
44-
"playwright>=1.39.0",
45-
"playwright-stealth>=1.0.6",
43+
"camoufox>=0.4.11",
4644
]
4745
dev = [
4846
"aiosqlite>=0.19.0",

projects/ecoindex_cli/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ At first, you need to install dependencies from the repository root:
352352

353353
```bash
354354
uv sync --all-groups
355-
uv run playwright install chromium --with-deps
355+
uv run camoufox fetch
356356
```
357357

358358
### Usage

projects/ecoindex_cli/dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
2020
COPY projects/ecoindex_cli/dist/$wheel $wheel
2121
RUN pip install --no-cache-dir $wheel
2222

23-
RUN playwright install chromium --with-deps
23+
RUN uv run camoufox fetch
2424

2525
RUN rm -rf $wheel requirements.txt /tmp/dist /var/lib/{apt,dpkg,cache,log}/

projects/ecoindex_cli/pyproject.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ dependencies = [
1414
"loguru>=0.7.2",
1515
"matplotlib>=3.8.0",
1616
"pandas>=2.1.2",
17-
"playwright>=1.39.0",
18-
"playwright-stealth>=1.0.6",
17+
"camoufox>=0.4.11",
1918
"pydantic>=2.4.2",
2019
"pydantic-settings>=2.0.3",
2120
"pyyaml>=6.0.1",

0 commit comments

Comments
 (0)