Skip to content

Commit

Permalink
Merge pull request #121 from vgalin/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
vgalin authored Aug 14, 2023
2 parents 3184329 + 5005ddd commit a07ee3c
Show file tree
Hide file tree
Showing 18 changed files with 1,115 additions and 152 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.6, 3.7, 3.8]
python-version: [3.6, 3.7, 3.8, 3.9, "3.10"]
poetry-version: [1.1.4]
os: [ubuntu-18.04, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
Expand All @@ -33,6 +33,7 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
pip install -r requirements.txt
pip install -r requirements-test.txt
- name: Flake8 linting
run: |
Expand Down
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,7 @@ dmypy.json

# Added
.vscode/
tests_output/
tests_output/

# .lock file not relevant for libraries
poetry.lock
8 changes: 4 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
FROM python

RUN curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -
RUN curl -sSL https://install.python-poetry.org | python3 -

WORKDIR /pkgs/html2image
COPY . .

RUN $HOME/.poetry/bin/poetry install
RUN $HOME/.poetry/bin/poetry build
RUN $HOME/.local/bin/poetry install
RUN $HOME/.local/bin/poetry build
RUN pip install dist/*.whl

RUN apt-get update -y && apt-get install -y chromium
Expand All @@ -19,4 +19,4 @@ RUN echo 'export CHROMIUM_FLAGS="$CHROMIUM_FLAGS --no-sandbox"' >> /etc/chromium
# MOTD
RUN echo " \n =============HTML2IMAGE============= \n Welcome to the html2image CLI container ! \n Type html2image -h for help :)" >> /etc/motd
RUN echo "clear" >> /root/.bashrc
RUN echo "cat /etc/motd" >> /root/.bashrc
RUN echo "cat /etc/motd" >> /root/.bashrc
36 changes: 24 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
<img src="readme_assets/html2image_black.png" align="right" alt="html2image logo" title="html2image" height="128"/>

# HTML2Image
[


<h1 align="center">
<a href="https://github.com/MadeInPierre/finalynx">
<img src="readme_assets/html2image_black.png" alt="html2image logo" title="html2image" height="200"/>
</a>
</h1>


<div align="center">

![PyPI](https://img.shields.io/pypi/v/html2image.svg)
![PyPI](https://img.shields.io/pypi/pyversions/html2image.svg)
![PyPI](https://img.shields.io/github/license/vgalin/html2image.svg)
](https://pypi.org/project/html2image/)
[
![GitHub](https://img.shields.io/github/v/release/vgalin/html2image?include_prereleases)
![GitHub](https://img.shields.io/github/languages/code-size/vgalin/html2image)
](https://github.com/vgalin/html2image)

HTML2Image is a lightweight Python package that acts as a wrapper around the headless mode of existing web browsers to generate images from URLs and from HTML+CSS strings or files.

|[PyPI Package](https://pypi.org/project/html2image/)|[GitHub Repository](https://github.com/vgalin/html2image)|
|-|-|

**A lightweight Python package acting a wrapper around the headless mode of existing web browsers, allowing images generation from HTML/CSS strings, files and URLs.**

</div>
&nbsp;

This package has been tested on Windows, Ubuntu (desktop and server) and MacOS. It is currently in a work in progress stage. If you encounter any problem or difficulties while using it, feel free to open an issue on the GitHub page of this project. Feedback is also welcome!


## Principle


Most web browsers have a Headless Mode, which is a way to run them without displaying any graphical interface. Headless mode is mainly used for automated testings but also comes in handy if you want to take screenshots of web pages that are exact replicas of what you would see on your screen if you were using the browser yourself.

However, for the sake of taking screenshots, headless mode is not very convenient to use. HTML2Image aims to hide the inconveniences of the browsers' headless modes while adding useful features such as allowing to create an image from as little as a string.
Expand All @@ -36,6 +49,7 @@ pip install --upgrade html2image
In addition to this package, at least one of the following browsers **must** be installed on your machine :
- Google Chrome (Windows, MacOS)
- Chromium Browser (Linux)
- Microsoft Edge

## Usage

Expand All @@ -45,14 +59,14 @@ from html2image import Html2Image
hti = Html2Image()
```

<details>
<summary> Multiple arguments can be passed to the constructor (click to expand):</summary>
Multiple arguments can be passed to the constructor:

- `browser` : Browser that will be used, set by default to `'chrome'` (the only browser supported by HTML2Image at the moment)
- `browser` : Browser that will be used, can be set to `'chrome'` (default) or `'edge'`.
- `browser_executable` : The path or the command that can be used to find the executable of a specific browser.
- `output_path` : Path to the folder to which taken screenshots will be outputed. Default is the current working directory of your python program.
- `size` : 2-Tuple representing the size of the screenshots that will be taken. Default value is `(1920, 1080)`.
- `temp_path` : Path that will be used to put together different resources when screenshotting strings of files. Default value is `%TEMP%/html2image` on Windows, and `/tmp/html2image` on Linux and MacOS.
- `keep_temp_files` : Pass True to this argument to not automatically remove temporary files created in `temp_path`. Default is False.

Example:
```python
Expand All @@ -63,8 +77,6 @@ You can also change these values later:
``` python
hti.size = (500, 200)
```
</details>
<br>

### Then take a screenshot

Expand Down
23 changes: 22 additions & 1 deletion html2image/browsers/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
class Browser(ABC):
"""Abstract class representing a web browser."""

def __init__(self, flags):
def __init__(self, flags, disable_logging):
pass

@property
Expand All @@ -20,3 +20,24 @@ def executable(self, value):
@abstractmethod
def screenshot(self, *args, **kwargs):
pass

@abstractmethod
def __enter__(self):
pass

@abstractmethod
def __exit__(self, *exc):
pass

@property
@abstractmethod
def disable_logging(self):
pass


class CDPBrowser(Browser):
"""A web browser that can be interacted with via Chrome DevTools Protocol.
"""

def __init__(self, flags, cdp_port, disable_logging):
pass
80 changes: 8 additions & 72 deletions html2image/browsers/chrome.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from .browser import Browser
from .chromium import ChromiumHeadless
from .search_utils import get_command_origin, find_first_defined_env_var

import subprocess
import platform
import os
import shutil
import platform

ENV_VAR_LOOKUP_TOGGLE = 'HTML2IMAGE_TOGGLE_ENV_VAR_LOOKUP'

Expand All @@ -15,7 +15,6 @@
'CHROME_EXE',
]


def _find_chrome(user_given_executable=None):
""" Finds a Chrome executable.
Expand Down Expand Up @@ -161,8 +160,7 @@ def _find_chrome(user_given_executable=None):
'machine, please specify it yourself.'
)


class ChromeHeadless(Browser):
class ChromeHeadless(ChromiumHeadless):
"""
Chrome/Chromium browser wrapper.
Expand All @@ -174,23 +172,16 @@ class ChromeHeadless(Browser):
- `flags` : list of str
+ Flags to be used by the headless browser.
+ Default flags are :
- '--default-background-color=000000'
- '--default-background-color=00000000'
- '--hide-scrollbars'
- `print_command` : bool
+ Whether or not to print the command used to take a screenshot.
- `disable_logging` : bool
+ Whether or not to disable Chrome's output.
"""

def __init__(self, executable=None, flags=None, print_command=False):
self.executable = executable
if not flags:
self.flags = [
'--default-background-color=000000',
'--hide-scrollbars',
]
else:
self.flags = [flags] if isinstance(flags, str) else flags

self.print_command = print_command
def __init__(self, executable=None, flags=None, print_command=False, disable_logging=False):
super().__init__(executable=executable, flags=flags, print_command=print_command, disable_logging=disable_logging)

@property
def executable(self):
Expand All @@ -199,58 +190,3 @@ def executable(self):
@executable.setter
def executable(self, value):
self._executable = _find_chrome(value)

def screenshot(
self,
input,
output_path,
output_file='screenshot.png',
size=(1920, 1080),
):
""" Calls Chrome or Chromium headless to take a screenshot.
Parameters
----------
- `output_file`: str
+ Name as which the screenshot will be saved.
+ File extension (e.g. .png) has to be included.
+ Default is screenshot.png
- `input`: str
+ File or url that will be screenshotted.
+ Cannot be None
- `size`: (int, int), optional
+ Two values representing the window size of the headless
+ browser and by extention, the screenshot size.
+ These two values must be greater than 0.
Raises
------
- `ValueError`
+ If the value of `size` is incorrect.
+ If `input` is empty.
"""

if not input:
raise ValueError('The `input` parameter is empty.')

if size[0] < 1 or size[1] < 1:
raise ValueError(
f'Could not screenshot "{output_file}" '
f'with a size of {size}:\n'
'A valid size consists of two integers greater than 0.'
)

# command used to launch chrome in
# headless mode and take a screenshot
command = [
f'{self.executable}',
'--headless',
f'--screenshot={os.path.join(output_path, output_file)}',
f'--window-size={size[0]},{size[1]}',
*self.flags,
f'{input}',
]

if self.print_command:
print(' '.join(command))

subprocess.run(command)
Loading

0 comments on commit a07ee3c

Please sign in to comment.