webscan: Prüfung auf Playwright und Browser mit Installationshinweisen

- fehlt Playwright oder der Browser, werden die passenden Befehle für
  Ubuntu/Debian bzw. Arch ausgegeben (erkannt über /etc/os-release),
  Abbruch mit Exit-Code 2
- doc/README.md: Einrichtung getrennt nach Ubuntu und Arch

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Michael Stangl
2026-10-09 09:16:04 +02:00
co-authored by Claude Opus 5.5
parent 7bd43e9e00
commit c884f4fd92
2 changed files with 93 additions and 5 deletions
+17 -3
View File
@@ -154,13 +154,27 @@ Konfiguration (in `cfg/webscan.cfg`: 800×500).
Einmalig einrichten (Python-Umgebung im Projektverzeichnis): Einmalig einrichten (Python-Umgebung im Projektverzeichnis):
```sh ```sh
python3 -m venv .venv python3 -m venv .venv # Ubuntu: vorher sudo apt install python3-venv
.venv/bin/pip install -r requirements.txt .venv/bin/pip install -r requirements.txt
```
Browser unter Ubuntu/Debian:
```sh
sudo .venv/bin/playwright install-deps chromium
.venv/bin/playwright install chromium .venv/bin/playwright install chromium
``` ```
Statt des Playwright-Chromiums kann auch ein installiertes Chromium benutzt Browser unter Arch Linux (Playwright unterstützt Arch nicht offiziell, daher
werden: `-b /usr/bin/chromium` oder `export PICCREATE_BROWSER=/usr/bin/chromium`. besser das Chromium der Distribution):
```sh
sudo pacman -S chromium
export PICCREATE_BROWSER=/usr/bin/chromium # oder Option -b /usr/bin/chromium
```
Fehlen Playwright oder der Browser, gibt `webscan.py` die passenden Befehle
für die erkannte Distribution aus und bricht mit Exit-Code 2 ab.
Eingabedatei, z. B. `in/kunden.csv` (Kopfzeile optional, `http://` wird bei Eingabedatei, z. B. `in/kunden.csv` (Kopfzeile optional, `http://` wird bei
Bedarf ergänzt): Bedarf ergänzt):
+76 -2
View File
@@ -18,7 +18,70 @@ import optparse
import os import os
import sys import sys
from playwright.async_api import async_playwright, Error as PlaywrightError PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
VENV = os.path.join(PROJECT_DIR, '.venv')
INSTALL_HINTS = {
'ubuntu': '''Ubuntu / Debian:
sudo apt install python3-venv
python3 -m venv {venv}
{venv}/bin/pip install -r {project}/requirements.txt
sudo {venv}/bin/playwright install-deps chromium
{venv}/bin/playwright install chromium''',
'arch': '''Arch Linux:
python -m venv {venv}
{venv}/bin/pip install -r {project}/requirements.txt
then either the browser from Arch (recommended, Playwright does not
officially support Arch):
sudo pacman -S chromium
export PICCREATE_BROWSER=/usr/bin/chromium
or the Playwright browser:
{venv}/bin/playwright install chromium''',
}
BROWSER_HINTS = {
'ubuntu': '''Ubuntu / Debian:
sudo {venv}/bin/playwright install-deps chromium
{venv}/bin/playwright install chromium''',
'arch': '''Arch Linux:
sudo pacman -S chromium
export PICCREATE_BROWSER=/usr/bin/chromium
or the Playwright browser:
{venv}/bin/playwright install chromium''',
}
def linux_distro():
''' liefert 'ubuntu' oder 'arch' (aus /etc/os-release), sonst None '''
try:
with open('/etc/os-release', encoding='utf-8') as fh:
info = dict(line.rstrip('\n').split('=', 1) for line in fh if '=' in line)
except OSError:
return None
ids = (info.get('ID', '') + ' ' + info.get('ID_LIKE', '')).replace('"', '').split()
if 'arch' in ids:
return 'arch'
if 'ubuntu' in ids or 'debian' in ids:
return 'ubuntu'
return None
def print_hint(hints):
''' gibt die Installationshinweise für diese Distribution aus
(bei unbekannter Distribution alle) '''
distro = linux_distro()
keys = [distro] if distro in hints else sorted(hints)
for key in keys:
print(hints[key].format(venv=VENV, project=PROJECT_DIR), file=sys.stderr)
try:
from playwright.async_api import async_playwright, Error as PlaywrightError
except ImportError:
print('Playwright is not installed for', sys.executable, file=sys.stderr)
print('Install it into the project environment:', file=sys.stderr)
print_hint(INSTALL_HINTS)
sys.exit(2)
from utils import CompleteEnding from utils import CompleteEnding
@@ -92,8 +155,17 @@ async def run(jobs, pic_config, options):
async with async_playwright() as p: async with async_playwright() as p:
launch_args = {} launch_args = {}
if options.browser: if options.browser:
if not os.path.isfile(options.browser):
print('browser', options.browser, 'does not exist.', file=sys.stderr)
print_hint(BROWSER_HINTS)
return None
launch_args['executable_path'] = options.browser launch_args['executable_path'] = options.browser
browser = await p.chromium.launch(**launch_args) try:
browser = await p.chromium.launch(**launch_args)
except PlaywrightError as e:
print('could not start the browser:', str(e).splitlines()[0], file=sys.stderr)
print_hint(BROWSER_HINTS)
return None
async def worker(customer_id, url): async def worker(customer_id, url):
out_path = os.path.join(out_dir, customer_id + '.' + pic_config['format']) out_path = os.path.join(out_dir, customer_id + '.' + pic_config['format'])
@@ -133,6 +205,8 @@ def main():
print('no urls found in', options.infile) print('no urls found in', options.infile)
return 1 return 1
failed = asyncio.run(run(jobs, pic_config, options)) failed = asyncio.run(run(jobs, pic_config, options))
if failed is None:
return 2
if failed: if failed:
print(len(failed), 'of', len(jobs), 'pages failed:', ', '.join(failed), file=sys.stderr) print(len(failed), 'of', len(jobs), 'pages failed:', ', '.join(failed), file=sys.stderr)
return 1 return 1