Compare commits

..
9 Commits
Author SHA1 Message Date
hmrhkr 525a99f411 feat: updated readme to new dependencies and added marxist.org examples 2026-09-30 15:18:46 +02:00
hmrhkr fc00034361 fix: replaced deprecated pdfkit with weasyprint, remove pure newlines and links from pdf 2026-09-30 15:03:24 +02:00
hmrhkr 9bd20bf1ae feat: added optional dryrun arg 2026-09-30 15:02:05 +02:00
hmrhkr e11e808613 added shutil 2023-04-07 20:44:52 +02:00
hmrhkr 6286ebc7f6 extended readme 2023-04-07 20:05:36 +02:00
hmrhkr 5815c0c044 extended readme 2023-04-07 18:47:21 +02:00
hmrhkr 7cd7e18ff4 added usage to readme 2023-04-07 18:41:45 +02:00
hmrhkr 55e08de784 added mlwerke2pdf.py 2023-04-07 18:41:33 +02:00
hmrhkr 1e1e7f6288 added gitignore 2023-04-07 18:41:14 +02:00
4 changed files with 256 additions and 1 deletions

No files matched your search

+160
View File
@@ -0,0 +1,160 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
+28 -1
View File
@@ -1,3 +1,30 @@
# mlwerke2pdf
Python module to convert texts on http://www.mlwerke.de into pdfs
Python module to convert texts on http://www.mlwerke.de or https://www.marxists.org into Portable Document Format files
mlwerke2pdf fetches the linked subsites from the given table of contents and concats them to a single pdf
at this point links and linked images in the pdf are not functional as they point to the mlwerke html structure
converting them to pdf internal links would be possible but rather complex
# dependencies
uses python modules requests, BeautifulSoup4, urllib and weasyprint
# Usage as commandline util
python mlwerke2pdf_shutil.py -u URL -o PDF_OUTPUT_PATH [--dry True optional for not writing any files]
use the base / table of contents of a text like https://www.marxists.org/deutsch/archiv/marx-engels/1848/manifest/index.htm as URL
# Usage as Python module
## create MLWerke Object:
mlwerk = mlwerke2pdf.MLWerk(URL)
use the base / table of contents of a text like https://www.marxists.org/deutsch/archiv/marx-engels/1848/manifest/index.htm as URL
## generate a pdf
mlwerk.text2pdf(PDF_OUTPUT_PATH)
## or cominded into one line
mlwerke2pdf.MLWerk(URL).text2pdf(PDF_OUTPUT_PATH)
+54
View File
@@ -0,0 +1,54 @@
import requests
from bs4 import BeautifulSoup
import urllib.parse
from weasyprint import HTML
class MLWerk:
class SubSite:
def __init__(self, url):
self.url = url
self.getsoup()
def getsoup(self):
r = requests.get(self.url)
r.encoding = 'UTF-8'
self.soup = BeautifulSoup(r.text, 'html.parser')
def __init__(self, url):
self.url = url
self.baseurl = url[:url.rfind('/')] + '/'
self.subsites = []
self.getsoup()
def getsoup(self):
r = requests.get(self.url)
r.encoding = 'UTF-8'
self.soup = BeautifulSoup(r.text, 'html.parser')
def getsubsites(self, limit = None):
i = 0
for link in self.soup.find_all('a'):
if limit != None and i > limit:
break
link = link.get('href')
if not link == None and not ("#" in link or "/" in link):
self.subsites.append(self.SubSite(urllib.parse.urljoin(self.baseurl, link)))
i += 1
def concatsubsites(self):
for subsite in self.subsites:
for tag in subsite.soup.body:
if (tag != "\n" and tag.name != "a"):
self.soup.body.append(tag)
def genpdf(self, path):
HTML(string=str(self.soup)).write_pdf(path)
def text2pdf(self, path, dry=False):
print("gettings subsites")
self.getsubsites()
print("concatting subsites")
self.concatsubsites()
if not dry:
print("generating pdf")
self.genpdf(path)
+14
View File
@@ -0,0 +1,14 @@
import mlwerke2pdf
import argparse
parser = argparse.ArgumentParser(
prog='MLWerke2PDF',
description='convert texts on http://www.mlwerke.de into Portable Document Format files',
epilog='published under GPL-3 at https://git.roteserver.de/humorhenker/mlwerke2pdf')
parser.add_argument('-u', '--url', dest='url', help='base / table of contents of a text like http://www.mlwerke.de/me/me04/me04_459.htm', required=True)
parser.add_argument('-o', '--pdfpath', dest='pdfpath', help='path for the output pdf', required=True)
parser.add_argument('--dry', dest='dryrun', default=False, help="dont store any files just dry fetch")
args = parser.parse_args()
mlwerke2pdf.MLWerk(args.url).text2pdf(args.pdfpath, args.dryrun)