Skip to content

Commit 81c0609

Browse files
authored
Merge pull request #184 from vgalin/develop
Develop
2 parents f8d88ce + 9ff0343 commit 81c0609

File tree

5 files changed

+450
-120
lines changed

5 files changed

+450
-120
lines changed

README.md

Lines changed: 63 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -283,31 +283,72 @@ For ease of use, some flags are set by default. However default flags are not us
283283
```
284284

285285
## Using the CLI
286-
HTML2image comes with a Command Line Interface which you can use to generate screenshots from files and URLs on the go.
287-
288-
The CLI is a work in progress and may undergo changes.
289-
You can call it by typing `hti` or `html2image` into a terminal.
290-
291-
292-
| argument | description | example |
293-
| - | - | - |
294-
| -h, --help | Shows the help message | `hti -h` |
295-
| -U, --urls | Screenshots a list of URLs | `hti -U https://www.python.org` |
296-
| -H, --html | Screenshots a list of HTML files | `hti -H file.html` |
297-
| -C, --css | Attaches a CSS files to the HTML ones | `hti -H file.html -C style.css` |
298-
| -O, --other | Screenshots a list of files of type "other" | `hti -O star.svg` |
299-
| -S, --save-as | A list of the screenshot filename(s) | `hti -O star.svg -S star.png` |
300-
| -s, --size | A list of the screenshot size(s) | `hti -O star.svg -s 50,50`|
301-
| -o, --output_path| Change the output path of the screenshots (default is current working directory) | `hti star.svg -o screenshot_dir` |
302-
| -q, --quiet| Disable all CLI's outputs | `hti --quiet` |
303-
| -v, --verbose| More details, can help debugging | `hti --verbose` |
304-
| --chrome_path| Specify a different chrome path ||
305-
| --custom_flags| Specify custom browser flags |
306-
| --temp_path| Specify a different temp path (where the files are loaded)||
286+
HTML2image comes with a Command Line Interface which you can use to generate screenshots from files and URLs on the go. You can call it by typing `hti` or `html2image` into a terminal.
287+
288+
289+
**Example Usage (quick start):**
290+
Screenshot a URL with a specific output name and size:
291+
```bash
292+
hti --url https://example.com --save-as example_page.png --size 1280,720
293+
```
294+
295+
Screenshot multiple HTML files, applying a common CSS file, and saving with custom names:
296+
```bash
297+
hti --html-file page1.html page2.html --css-file common_styles.css --save-as shot1.jpg shot2.jpg
298+
```
299+
300+
Screenshot an HTML string with a custom browser flags and verbose output:
301+
```bash
302+
hti --html-string "<h1>Test</h1><p>Content</p>" --custom-flags '--no-sandbox' -v
303+
```
304+
305+
**Html2Image Instance Configuration:**
306+
307+
These arguments configure the underlying `Html2Image` instance.
308+
309+
| Argument | Description | Example |
310+
|----------|-------------|---------|
311+
| `-h, --help` | Show the help message and exit. | `hti --help` |
312+
| `-o, --output-path PATH` | Directory to save screenshots. (Default: current working directory)| `hti --url example.com -o my_images/` |
313+
| `--browser BROWSER`| Browser to use. Choices: `chrome`, `chromium`, `google-chrome`, `google-chrome-stable`, `googlechrome`, `edge`, `chrome-cdp`, `chromium-cdp`. (Default: `chrome`)| `hti --url example.com --browser edge` |
314+
| `--browser-executable EXECUTABLE_PATH` | Path to the browser executable. Auto-detected if not provided. | `hti --browser-executable /usr/bin/google-chrome-stable`|
315+
| `--cdp-port PORT` | CDP port for CDP-enabled browsers (e.g., `chrome-cdp`). (Default: library-dependent)| `hti --browser chrome-cdp --cdp-port 9222 --url example.com` |
316+
| `--temp-path TEMP_DIR_PATH` | Directory for temporary files. (Default: system temp directory in an `html2image` subfolder) | `hti --html-file page.html --temp-path /my/tmp`|
317+
| `--keep-temp-files`| Do not delete temporary files after screenshot generation.| `hti --html-file page.html --keep-temp-files` |
318+
| `--custom-flags [FLAG ...]` | Custom flags to pass to the browser (e.g., `'--no-sandbox' '--disable-gpu'`). If provided, these flags will be used. | `hti --url example.com --custom-flags '--no-sandbox' '--disable-gpu'` <br> `hti --url example.com --custom-flags '--no-sandbox --disable-gpu'` |
319+
320+
**Screenshot Sources:**
321+
322+
Specify what content to screenshot. At least one source type is required.
323+
324+
| Argument | Description | Example |
325+
|----------|-------------|---------|
326+
| `-U, --url [URL ...]` | URL(s) to screenshot. | `hti -U https://python.org https://example.com`|
327+
| `--html-file [FILE ...]` | HTML file(s) to screenshot. | `hti --html-file mypage.html another.html` |
328+
| `--html-string [STRING ...]`| HTML string(s) to screenshot. | `hti --html-string "<h1>Hello</h1>" "<h2>World</h2>"` |
329+
| `--css-file [FILE ...]` | CSS file(s) to load. Used by HTML files or applied with HTML strings. | `hti --html-file page.html --css-file style1.css style2.css` |
330+
| `--css-string [STRING ...]` | CSS string(s) to apply. Combined and used with HTML strings. | `hti --html-string "<h1>Hi</h1>" --css-string "body{color:red;}" "h1{font-size:40px;}"` |
331+
| `-O, --other-file [FILE ...]` | Other file(s) to screenshot (e.g., SVG).| `hti -O star.svg`|
332+
333+
**Screenshot Output Options:**
334+
335+
Control how the screenshots are saved.
336+
337+
| Argument | Description | Example |
338+
|----------|-------------|---------|
339+
| `-S, --save-as [FILENAME ...]` | Filename(s) for output images. If not provided or fewer names than items, names are auto-generated (e.g., `screenshot.png`, `screenshot_0.png`). | `hti -U python.org example.com -S py.png ex.png` |
340+
| `-s, --size [W,H ...]`| Size(s) for screenshots as `Width,Height`. If one W,H pair is given, it applies to all screenshots. If multiple W,H pairs are given, they apply to corresponding screenshots sequentially; if fewer pairs than items, the last pair is repeated. If omitted, the library's default (1920,1080) is used. Width and height must be positive integers. | `hti -U python.org --size 800,600` <br> `hti -U python.org example.com -s 800,600 1024,768` |
341+
342+
**General Options:**
343+
344+
| Argument | Description | Example |
345+
|----------|-------------|---------|
346+
| `-q, --quiet`| Suppress informational output from html2image library (sets `disable_logging=True`). | `hti -U python.org -q` |
347+
| `-v, --verbose` | Enable verbose output, including browser commands if supported by the browser handler. | `hti -U python.org -v` |
307348

308349
<br>
309350

310-
### ... now within a Docker container !
351+
### Using a Docker Container
311352

312353
You can also test the package and the CLI without having to install everything on your local machine, via a Docker container.
313354

html2image/cli.py

Lines changed: 215 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,81 +2,247 @@
22
"""
33

44
import argparse
5-
5+
import os
66
from html2image import Html2Image
77

88

9-
def main():
10-
11-
def size_type(string):
12-
try:
13-
x, y = map(int, string.split(','))
14-
return x, y
15-
except Exception:
9+
def size_type(string):
10+
try:
11+
width, height = map(int, string.split(','))
12+
if width <= 0 or height <= 0:
1613
raise argparse.ArgumentTypeError(
17-
f"size should be int,int, instead got {string}"
14+
'Width and height must be positive integers.'
1815
)
16+
return width, height
17+
except ValueError: # incorrect number of values
18+
raise argparse.ArgumentTypeError(
19+
f"Size should be W,H (e.g., 1920,1080), instead got '{string}'"
20+
)
21+
except Exception as e: # unexpected errors
22+
raise argparse.ArgumentTypeError(f"Invalid size format '{string}': {e}")
1923

20-
parser = argparse.ArgumentParser()
2124

22-
parser.add_argument('-U', '--url', nargs='*', required=False, default=[])
23-
parser.add_argument('-H', '--html', nargs='*', required=False, default=[])
24-
parser.add_argument('-C', '--css', nargs='*', required=False, default=[])
25-
parser.add_argument('-O', '--other', nargs='*', required=False, default=[])
25+
def main():
26+
parser = argparse.ArgumentParser(
27+
description='Generate images from HTML/CSS or URLs using the html2image library.',
28+
formatter_class=argparse.ArgumentDefaultsHelpFormatter
29+
)
30+
31+
# Html2Image instantiation arguments
32+
group_hti_init = parser.add_argument_group('Html2Image Instance Configuration')
33+
group_hti_init.add_argument(
34+
'--output-path', '-o',
35+
default=os.getcwd(),
36+
help='Directory to save screenshots.'
37+
)
2638

27-
parser.add_argument(
28-
'-S', '--save-as', nargs='*', required=False, default="screenshot.png"
39+
# TODO : this list is duplicated from browser_map in html2image.py
40+
browser_choices = [
41+
'chrome', 'chromium', 'google-chrome', 'google-chrome-stable',
42+
'googlechrome', 'edge', 'chrome-cdp', 'chromium-cdp'
43+
]
44+
group_hti_init.add_argument(
45+
'--browser',
46+
default='chrome',
47+
choices=browser_choices,
48+
help='Browser to use for screenshots.'
2949
)
30-
parser.add_argument(
31-
'-s', '--size', nargs='*', required=False, default=[], type=size_type
50+
group_hti_init.add_argument(
51+
'--browser-executable',
52+
default=None,
53+
help='Path to the browser executable. Auto-detected if not provided.'
54+
)
55+
group_hti_init.add_argument(
56+
'--cdp-port',
57+
type=int,
58+
default=None,
59+
help='CDP port for CDP-enabled browsers (e.g., chrome-cdp). Default is library-dependent.'
60+
)
61+
group_hti_init.add_argument(
62+
'--temp-path',
63+
default=None,
64+
help="Directory for temporary files. Defaults to system temp directory within an 'html2image' subfolder."
65+
)
66+
group_hti_init.add_argument(
67+
'--keep-temp-files',
68+
action='store_true',
69+
help='Do not delete temporary files after screenshot generation.'
70+
)
71+
group_hti_init.add_argument(
72+
'--custom-flags',
73+
nargs='*',
74+
default=[], # If not provided, defaults are used
75+
help="Custom flags to pass to the browser (e.g., '--no-sandbox' '--disable-gpu'). If provided, these flags will be used."
3276
)
3377

34-
parser.add_argument('-o', '--output_path', required=False)
78+
# Screenshot sources arguments
79+
group_sources = parser.add_argument_group('Screenshot Sources (at least one type is required)')
80+
group_sources.add_argument(
81+
'--url', '-U',
82+
nargs='*', default=[],
83+
metavar='URL',
84+
help='URL(s) to screenshot.'
85+
)
86+
group_sources.add_argument(
87+
'--html-file',
88+
nargs='*', default=[],
89+
metavar='FILE',
90+
help='HTML file(s) to screenshot.'
91+
)
92+
group_sources.add_argument(
93+
'--html-string',
94+
nargs='*', default=[],
95+
metavar='STRING',
96+
help='HTML string(s) to screenshot.'
97+
)
98+
group_sources.add_argument(
99+
'--css-file',
100+
nargs='*', default=[],
101+
metavar='FILE',
102+
help='CSS file(s) to load. Used by HTML files or applied with HTML strings.'
103+
)
104+
group_sources.add_argument(
105+
'--css-string',
106+
nargs='*', default=[],
107+
metavar='STRING',
108+
help='CSS string(s) to apply. Combined and used with HTML strings.'
109+
)
110+
group_sources.add_argument(
111+
'--other-file', '-O',
112+
nargs='*', default=[],
113+
metavar='FILE',
114+
help='Other file(s) to screenshot (e.g., SVG).'
115+
)
35116

36-
parser.add_argument('-q', '--quiet', required=False, action="store_true")
37-
parser.add_argument('-v', '--verbose', required=False, action="store_true")
117+
# Screenshot output control arguments
118+
group_output_ctrl = parser.add_argument_group('Screenshot Output Options')
119+
group_output_ctrl.add_argument(
120+
'--save-as', '-S',
121+
nargs='*', default=None, # html2image handles default naming if only one source
122+
metavar='FILENAME',
123+
help='Filename(s) for the output images. If not provided or fewer names than items, names are auto-generated.'
124+
)
125+
group_output_ctrl.add_argument(
126+
'--size', '-s',
127+
nargs='*', default=[],
128+
type=size_type,
129+
metavar='W,H',
130+
help="Size(s) for screenshots as W,H. If one W,H pair is given, it applies to all. If multiple, they apply to corresponding screenshots; if fewer pairs than items, the last is repeated. If omitted, (1920,1080) is used."
131+
)
38132

39-
# parser.add_argument('--browser', required=False)
40-
parser.add_argument('--chrome_path', required=False)
41-
# parser.add_argument('--firefox_path', required=False)
42-
parser.add_argument('--temp_path', required=False)
43-
parser.add_argument('--custom_flags', required=False)
133+
# General arguments
134+
group_general = parser.add_argument_group('General Options')
135+
group_general.add_argument(
136+
'--quiet', '-q',
137+
action='store_true',
138+
help='Suppress output from browsers (sets disable_logging=True).'
139+
)
140+
group_general.add_argument(
141+
'--verbose', '-v',
142+
action='store_true',
143+
help='Enable verbose output, including browser commands if supported by the browser handler.'
144+
)
44145

45146
args = parser.parse_args()
46147

148+
# Prepare Html2Image()
149+
hti_kwargs = {
150+
'output_path': args.output_path,
151+
'browser': args.browser,
152+
'browser_executable': args.browser_executable,
153+
'custom_flags': [cf.replace("'", '') for cf in args.custom_flags],
154+
'disable_logging': args.quiet,
155+
'temp_path': args.temp_path,
156+
'keep_temp_files': args.keep_temp_files,
157+
}
158+
159+
# Only pass cdp_port if a CDP browser is likely selected and port is given
160+
if args.cdp_port and 'cdp' in args.browser.lower():
161+
hti_kwargs['browser_cdp_port'] = args.cdp_port
162+
elif args.cdp_port:
163+
print(
164+
f"Warning: --cdp-port ({args.cdp_port}) was specified, but the selected browser ('{args.browser}') might not be a CDP browser."
165+
)
166+
47167
try:
48-
hti = Html2Image(disable_logging=args.quiet)
168+
# Filter out None values so defaults are used for those specific kwargs
169+
# keep_temp_files and disable_logging are bools, always pass them.
170+
# custom_flags should be passed even if None, so Html2Image can use its defaults or an empty list.
171+
active_hti_kwargs = {
172+
k: v for k, v in hti_kwargs.items()
173+
if v is not None or k in ['keep_temp_files', 'disable_logging', 'custom_flags']
174+
}
175+
hti = Html2Image(**active_hti_kwargs)
176+
49177
except Exception as e:
50-
print('Could not instanciate html2image.')
51-
print(e)
178+
print(f'Error: Could not instantiate Html2Image: {e}')
52179
exit(1)
53180

54181
if args.verbose:
55-
print(f'args = {args}')
56-
hti.browser.print_command = True
57-
58-
if args.output_path:
59-
hti.output_path = args.output_path
182+
# The `print_command` attribute is specific to ChromiumHeadless.
183+
# CDP browsers print logs internally.
184+
if hasattr(hti.browser, 'print_command'):
185+
hti.browser.print_command = True
186+
print('Verbose mode: Browser commands will be printed for compatible handlers.')
187+
else:
188+
print('Verbose mode enabled. Note: Detailed browser command printing depends on the selected browser handler.')
189+
190+
has_sources = any([
191+
args.url, args.html_file, args.html_string, args.other_file
192+
])
193+
194+
# Print help message if no sources were passed
195+
if not has_sources:
196+
print('Error: No screenshot sources (URL, HTML file/string, other file) provided.')
197+
parser.print_usage()
198+
exit(1)
60199

61-
if args.chrome_path:
62-
hti.chrome_path = args.chrome_path
200+
# Perform screenshot
201+
screenshot_kwargs = {
202+
'url': args.url,
203+
'html_file': args.html_file,
204+
'html_str': args.html_string,
205+
'css_file': args.css_file,
206+
'css_str': args.css_string,
207+
'other_file': args.other_file,
208+
'size': args.size, # Pass the list of sizes directly from the --size CLI arg
209+
}
63210

64-
if args.custom_flags:
65-
hti.browser.flags = args.custom_flags
211+
if args.save_as is not None:
212+
screenshot_kwargs['save_as'] = args.save_as
66213

67-
if args.temp_path:
68-
hti.temp_path = args.temp_path
214+
try:
215+
if args.verbose:
216+
print('--- Html2Image Instance Configuration ---')
217+
for k, v in active_hti_kwargs.items():
218+
print(f' {k}: {v}')
219+
print('--- Screenshot Call Arguments ---')
220+
for k, v in screenshot_kwargs.items():
221+
if v or k == 'size': # print if list not empty, or always for size
222+
print(f' {k}: {v}')
223+
224+
paths = hti.screenshot(**screenshot_kwargs)
225+
226+
if not args.quiet:
227+
print(f'Successfully created {len(paths)} image(s):')
228+
for path in paths:
229+
print(f' {path}')
230+
231+
except FileNotFoundError as e:
232+
print(f'Error: A required file was not found: {e}')
233+
exit(1)
69234

70-
paths = hti.screenshot(
71-
html_file=args.html, css_file=args.css, other_file=args.other,
72-
url=args.url, save_as=args.save_as, size=args.size
73-
)
235+
except ValueError as e: # Can be raised by browser screenshot method for bad size etc.
236+
print(f'Error: Invalid value encountered: {e}')
237+
exit(1)
74238

75-
if not args.quiet:
76-
print(f'Created {len(paths)} file(s):')
77-
for path in paths:
78-
print(f'\t{path}')
239+
except Exception as e:
240+
print(f'An unexpected error occurred during screenshotting: {e}')
241+
if args.verbose:
242+
import traceback
243+
traceback.print_exc()
244+
exit(1)
79245

80246

81-
if __name__ == "__main__":
247+
if __name__ == '__main__':
82248
main()

0 commit comments

Comments
 (0)