version 0.9

This commit is contained in:
trnq1ll0 committed 2024-08-25 13:24:38 +02:00
commit 0fb19123d7
5 files changed
+229

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
.DS_Store
.venv
pages
images
config.json
+43
View File
@@ -0,0 +1,43 @@
# Ziel
Ziel des Paketes ist es alle Seiten eines MediWikis so zu konvertieren das sie direkt in Obsidian verwendete werden können.
Das Paket lädt dafür alle Seiten eines MediaWikis herunter und speichert sie in einem Ordner als Markdown file.
## Bestandteile
* Wikiseiten (Lemma) werden mit ihrem Titel als Dateinamen abgelegt
* Seiten die eine scheinbare Struktur in Form von slashes (/) im Namen haben werden in entsprechenden Unterordnern abgelegt
* Es wird die MediaWiki API verwendet um alle Seiten herunterzuladen.
* es wird html2text verwendet um die Seiten von HTML in Markdown zu konvertieren
* Meta-informationen der Seite werden am Ende in einem json gespeichert
* Dateien werden in einem separaten Ordner gespeichert un im Metadaten json richtig verlinkt
### Metadaten JSON
´´´
{
"metadata": {
"categories": [],
"internallinks": [],
"externallinks": [],
"images": [],
"showtoc": false
}
´´´
# Get started
## Install python environment
```
python3 -m venv .venv
source .venv/bin/activate # Für Unix/Mac
.venv\Scripts\activate # Für Windows
pip install -r requirements.txt
```
## Konfiguration
Kopiere die datei `config.json.tmpl` zu `config.json` und passe die Einstellungen darin an.
+8
View File
@@ -0,0 +1,8 @@
{
"api_url": "https://my-mediwiki/api.php",
"pages": "pages",
"images": "images",
"username": "bob",
"password": "password",
"maxfiles": -1
}
+8
View File
@@ -0,0 +1,8 @@
beautifulsoup4==4.12.3
certifi==2024.7.4
charset-normalizer==3.3.2
html2text==2024.2.26
idna==3.7
requests==2.32.3
soupsieve==2.6
urllib3==2.2.2
+165
View File
@@ -0,0 +1,165 @@
import os
import json
import requests
from bs4 import BeautifulSoup
import html2text
import urllib3
import warnings
api_url = ""
images_folder = ""
print("SSL waring ist okay, kann ignoriert werden.")
def load_config(config_file):
with open(config_file, 'r') as file:
return json.load(file)
def login(session, api_url, username, password):
params = {
"action": "query",
"meta": "tokens",
"type": "login",
"format": "json"
}
response = session.get(api_url, params=params)
login_token = response.json()['query']['tokens']['logintoken']
login_payload = {
"action": "login",
"lgname": username,
"lgpassword": password,
"lgtoken": login_token,
"format": "json"
}
response = session.post(api_url, data=login_payload)
if response.status_code == 200:
print("Login successful")
else:
print("Login failed")
response.raise_for_status()
def download_all_pages(session, api_url):
all_pages = []
params = {
'action': 'query',
'format': 'json',
'list': 'allpages',
'aplimit' : 'max'
}
while True:
response = session.get(api_url, params=params)
if response.status_code == 200:
data = response.json()
all_pages.extend(data['query']['allpages'])
if 'continue' in data:
params['apcontinue'] = data['continue']['apcontinue']
else:
break
else:
print(f"Failed to download pages from {api_url}")
break
return all_pages
def save_content_to_file(content, download_folder, page_name, extension='md'):
file_path = os.path.join(download_folder, f"{page_name}.{extension}")
os.makedirs(os.path.dirname(file_path), exist_ok=True)
with open(file_path, 'w', encoding='utf-8') as file:
file.write(content)
print(f"Downloaded {page_name} to {file_path}")
def GenerateMetadataJson(data):
metadata = {
'metadata' : {
'categories' : data['parse']['categories'],
'internallinks' : data['parse']['links'],
'externallinks' : data['parse']['externallinks'],
'images' : data['parse']['images'],
'showtoc' : data['parse']['showtoc']
}
}
return "\n\n " + json.dumps(metadata, indent=4)
def StoreImages(session, images_list, json_string):
for image in images_list:
params = {
'action': 'query',
'format': 'json',
'titles': f'File:{image}',
'prop': 'imageinfo',
'iiprop': 'url'
}
response = session.get(api_url, params=params)
if response.status_code != 200:
print(f"Failed to download image {image}")
continue
data = response.json()
pages = data['query']['pages']
page_id = list(pages.keys())[0]
image_info = pages[page_id].get('imageinfo', [{}])[0]
image_url = image_info.get('url')
if not image_url:
print(f"No image info found for {image}")
continue
image_name = image_url.split('/')[-1]
response = session.get(image_url)
if response.status_code != 200:
print(f"Failed to download image {image_name}")
continue
image_path = os.path.join(images_folder, image_name)
with open(image_path, 'wb') as file:
file.write(response.content)
print(f"Downloaded {image_name}")
json_string = ReplaceImagePath(json_string, image_name, image_path)
return json_string
def ReplaceImagePath(str, image_name, image_path):
return str.replace(f'"{image_name}"', f'"./{image_path}"')
def main():
global api_url
global images_folder
config = load_config('config.json')
api_url = config['api_url'].rstrip('/') # Entferne den abschließenden Schrägstrich, falls vorhanden
pages_folder = config['pages']
images_folder = config['images']
username = config['username']
password = config['password']
maxfiles = config['maxfiles']
if not os.path.exists(pages_folder):
os.makedirs(pages_folder)
if not os.path.exists(images_folder):
os.makedirs(images_folder)
with requests.Session() as session:
login(session, api_url, username, password)
all_pages = download_all_pages(session, api_url)
print(f"Downloading {len(all_pages)} pages")
for page in all_pages:
if maxfiles == 0:
break
maxfiles -= 1
page_title = page['title']
params = {
'formatversion': 2,
'action': 'parse',
'page': page_title,
'format': 'json'
}
response = session.get(api_url, params=params)
if response.status_code == 200:
data = response.json()
if 'parse' in data:
markdown_content = html2text.html2text(data['parse']['text'])
markdown_content += GenerateMetadataJson(data)
markdown_content = StoreImages(session, data['parse']['images'], markdown_content)
if markdown_content:
save_content_to_file(markdown_content, pages_folder, page_title, extension='md')
else:
print(f"Failed to parse page {page_title}")
else:
print(f"Failed to download page {page_title}")
if __name__ == "__main__":
main()