Process Swedish Librivox text
Normalisation, adding boilerplate
From this page:
I BÖRJAN AV INSPELNINGEN: (Introduktion)
• "[Kapitel] av [titel]. Detta är en LibriVox inspelning. Alla LibriVox inspelningar är allmän egendom. För mer information, eller för att anmäla dig som frivillig, besök librivox punkt org." • Om du vill så kan du säga: "Uppläst av [ditt namn]" • Säg: "[Titel] av [författare]. [Kapitel]"
I SLUTET AV INSPELNINGEN:
• Vid slutet av ett kapitel, säg: "Slut på [kapitel]" • Vid slutet av boken, säg (utöver det förra): "Slut på [titel] av [författare]." • Om du vill så kan du säga: "Uppläst av [ditt namn] [stad, din blog, podcast, webbaddress]"
boilerplate = {}
boilerplate_end = {}
codeswitch = {}
codeswitch_end = {}
boilerplate["elin_i_hagen"] = "Elin i hagen by Gustaf Fröding read in Swedish for librivox dot org by Elina Riuttanen"
codeswitch["elin_i_hagen"] = "sv sv sv en sv sv en en en en en en en en fi fi"
boilerplate_end["elin_i_hagen"] = "End of poem. This recording is in the public domain"
codeswitch_end["elin_i_hagen"] = "en en en en en en en en en en"
boilerplate["en_saga_om_vreden"] = "En saga om Vreden av Fredrika Runeberg uppläst på svenska av Johan Borg. Detta är en LibriVox inspelning. Alla LibriVox inspelningar är allmän egendom. För mer information, eller för att anmäla dig som frivillig, besök librivox punkt org."
boilerplate_end["en_saga_om_vreden"] = "slut på en saga om vreden av fredrika runeberg uppläst av johan borg flavors punkt m e snedstreck johan borg"
boilerplate["efter_torgdagen"] = "Detta är en LibriVox inspelning. Alla LibriVox inspelningar är allmän egendom. För mer information, eller för att anmäla dig som frivillig, besök librivox punkt org. Efter torgdagen av Victoria Benedictsson"
boilerplate_end["efter_torgdagen"] = "här slutar efter torgdagen av Victoria Benedictsson uppläst av anna troy"
boilerplate["jenny"] = "Jenny av Johan Ludvig Runeberg. Läst på svenska för librivox punkt org av Petra"
boilerplate_end["jenny"] = "Slut på dikten. Den här inspelningen är allmän egendom"
boilerplate["nocturne"] = "Nocturne av Edith Södergran uppläst av Johan Borg för librivox punkt org"
boilerplate_end["nocturne"] = "Slut på dikt. Den här inspelningen är av allmän egendom"
boilerplate["dagen_svalnar"] = "Dagen svalnar by Edith Södergran read in Swedish for librivox dot org by Jonna"
codeswitch["dagen_svalnar"] = "sv sv en sv sv en en en en en en en en sv"
boilerplate_end["dagen_svalnar"] = "End of Dagen svalnar. This recording is in the public domain"
codeswitch_end["dagen_svalnar"] = "en en sv sv en en en en en en en"
boilerplate["korpen"] = "Korpen by Edgar Allen Poe. Translated by Viktor Rydberg. Read for librivox dot org in Swedish by Lars Rolander"
codeswitch["korpen"] = "sv en en en en en en sv sv en en en en en en en en sv sv"
boilerplate_end["korpen"] = "End of poem. This recording is in the public domain"
codeswitch_end["korpen"] = "en en en en en en en en en en"
boilerplate["onskenatt"] = "Önskenatt av Karin Boye. Läst på svenska för librivox punkt org av Petra"
boilerplate_end["onskenatt"] = "Slut på Önskenatt. Den här inspelningen är allmän egendom"
boilerplate["tomten"] = "Tomten by Viktor Rydberg read in Swedish. This is a Librivox recording. All Librivox recordings are in the public domain. For more information, or to volunteer, please visit librivox dot org. Tomten."
codeswitch["tomten"] = "sv en sv sv en en en en en en en en en en en en en en en en en en en en en en en en en en en sv"
boilerplate_end["tomten"] = "End of Tomten by Viktor Rydberg"
codeswitch_end["tomten"] = "en en sv en sv sv"
boilerplate["ett_halvt_ark_papper"] = "Ett halvt ark papper av August Strindberg uppläst på svenska. Detta är en LibriVox inspelning. Alla LibriVox inspelningar är allmän egendom. För mer information, eller för att anmäla dig som frivillig, besök librivox punkt org. Ett halvt ark papper."
boilerplate_end["ett_halvt_ark_papper"] = "Slut på Ett halvt ark papper av August Strindberg"
boilerplate["pa_rakstugan"] = "På rakstugan av Albert Ulrik Bååth. Uppläst på svenska för librivox punkt org. På rakstugan"
boilerplate_end["pa_rakstugan"] = "Slut på dikten på rakstugan. Den inspelning är allmän egendom"
boilerplate["for_morgonbris"] = "För morgonbris av Karl August Tavaststjerna. Läst i svenska för librivox punkt org av Cecilia"
boilerplate_end["for_morgonbris"] = "Slut på dikten. Den här inspelningen är av allmän egendom"
def boilerplate_norm(text):
text = text.replace(". ", "\n")
text = text.replace(",", "")
if text[-1] == ".":
text = text[:-1]
return text.lower()
%pip install requests mosestokenizer
import requests
from mosestokenizer import MosesSentenceSplitter
import re
BARON_OLSEN_TITLES = """\
BARON OLSON
TUSEN TJOG ÄGG
ÖMSESIDIGT FÖRTROENDE
»DEN GYLLENE PLOMMONBLOMMAN»
EN RÄTTSFRÅGA
SVÅRSÅLD VARA
ARTIGHET I BARBACKA
JÄRNVÄGSSTREJKEN I FÄLANDA
EN SPRITAFFÄR
MAJUMBA
EN KRIGSLIST
EN ITALIENSK EPISOD
DJURVÄNLIGHET
EN LIVLIG JULAFTON
ETT SJUKDOMSFALL
VÄGEN TILL ENA PIGO
WATERMANS IDEAL
EN HEMSK HISTORIA
MOTORDRIFT
EN BRA MEDICIN
NUTIDA JÄRNVÄGSRESOR
MÖRKSENS GÄRNINGAR
MANNEN SOM VAR EN TIDTABELL
I SNÖSTORMEN
FÖRSTA APRIL
JOURNALISTIK I VILDA VÄSTERN
"""
def runeberg_norm(lines):
buf = []
for line in lines:
line = line.strip()
if line == "":
continue
line = line.replace(",", "")
line = line.replace(" - ", " ")
line = line.replace(" -- ", " ")
line = line.replace('"', "")
line = line.replace("<i>", "")
line = line.replace("</i>", "")
if line.startswith("- "):
line = line[2:]
if line.endswith(" -"):
line = line[:-2]
#if line[-1] in ";:.?!":
# line = line[:-1]
for char in ";:.?!":
line = line.replace(char, "")
line = re.sub(" +", " ", line)
buf.append(line.lower())
return buf
def runeberg_page(url = "http://runeberg.org/dragharm/elinhage.html", normalise = True, joined = True):
response = requests.get(url)
assert response.status_code == 200
response.encoding = 'UTF-8'
if "<p><i>Below is the <b>raw OCR text</b>" in response.text:
text = response.text.split("<!-- #### -->")[1]
if "<!-- mode=normal -->" in response.text:
text = text.split("<!-- mode=normal -->")[1]
else:
splitter = "</h1>" if "</h1>" in response.text else "</h3>"
splitter = "</h2>" if "</h2>" in response.text else "</h3>"
text = response.text.split(splitter)[1].split("<br clear=all>")[0]
text = text.replace("<p>", "\n").replace("<br>", "\n")
if normalise:
buf = runeberg_norm(text.split("\n"))
else:
buf = text.split("\n")
if joined:
return "\n".join(buf)
else:
return buf
def write_with_boilerplate(func):
name = func.__name__
with open(f"{name}.txt", "w") as of:
if name in boilerplate:
of.write(boilerplate_norm(boilerplate[name]))
of.write("\n")
of.write(func())
if name in boilerplate_end:
of.write("\n")
of.write(boilerplate_norm(boilerplate_end[name]))
def elin_i_hagen(url = "http://runeberg.org/dragharm/elinhage.html", normalise = True):
return runeberg_page(url, normalise)
def onskenatt(url = "http://runeberg.org/boyemoln/1_16.html", normalise = True):
return runeberg_page(url, normalise)
def landshovdingen(url = "http://runeberg.org/fstal/2p.html", normalise = True):
return runeberg_page(url, normalise)
write_with_boilerplate(elin_i_hagen)
write_with_boilerplate(onskenatt)
write_with_boilerplate(landshovdingen)
BASIC_ROMAN = {
"I": "ett",
"II": "tvo",
"III": "tre",
"IV": "fyra"
}
def dagen_svalnar(url = "http://runeberg.org/sodrgran/01_02.html", normalise = True):
raw = runeberg_page(url, normalise, False)
buf = []
for line in raw:
line = line.strip()
line = line.replace("<h3>", "").replace("</h3>", "")
if line.upper() in BASIC_ROMAN.keys():
buf.append(BASIC_ROMAN[line.upper()])
else:
buf.append(line)
return "\n".join(buf)
write_with_boilerplate(dagen_svalnar)
def korpen(url = "http://runeberg.org/rydbdikt/korpen.html", normalise = True):
lines = runeberg_page(url, normalise, False)
buf = []
for line in lines:
line = line.replace(" ", " ")
line = line.replace("</p>", "")
line = line.replace("»", "").strip()
line = re.sub(" +", " ", line)
if line == "(efter edgar allan poe)":
continue
buf.append(line)
return "\n".join(buf)
write_with_boilerplate(korpen)
def en_saga_om_vreden(url = "http://web.archive.org/web/20190814032041/http://freetexthost.com:80/bcp31m60i4", normalise = True):
response = requests.get(url)
assert response.status_code == 200
text = response.text.split('<div id="contentsinner">')[1].split('<a href=')[0]
if normalise:
text = text.replace(""", "").replace("<br/>", "")
buf = []
for line in text.split("\n"):
if line.strip() == "":
continue
#line = line.strip().replace(",", "")
buf.append(line)
if buf[0].startswith("En saga om Vreden,"):
buf = buf[1:]
with MosesSentenceSplitter('sv') as splitsents:
sents = splitsents(buf)
newbuf = []
for sent in sents:
sent = sent.replace(",", "")
sent = sent.replace(" - ", " ")
if sent.endswith(" -"):
sent = sent[:-2]
if sent[-1] in ";:.?!":
sent = sent[:-1]
newbuf.append(sent)
text = "\n".join(newbuf).lower()
else:
text = text.replace(""", "\"").replace("<br/>", "\n")
return text
write_with_boilerplate(en_saga_om_vreden)
def baron_olson(url = "https://www.gutenberg.org/cache/epub/15719/pg15719.txt", normalise = True):
def _skip(text):
text = text.strip()
if text == "":
return True
if text == "* * * * *":
return True
return False
stories = {}
response = requests.get(url)
assert response.status_code == 200
GB_START = "*** START OF THIS PROJECT GUTENBERG EBOOK BARON OLSON OCH ANDRA HISTORIER ***"
GB_END = "End of Project Gutenberg's Baron Olson och andra historier, by Sigge Strömberg"
text = response.text.split(GB_START)[1].split(GB_END)[0]
chapter_titles = [t for t in BARON_OLSEN_TITLES.split("\n") if t != ""]
prev_title = ""
cur_title = chapter_titles.pop(0)
text_buf = []
for line in text.replace("\r", "").split("\n"):
if line.strip() == cur_title:
if prev_title != "":
stories[prev_title] = text_buf.copy()
text_buf.clear()
prev_title = cur_title
cur_title = chapter_titles.pop(0)
elif not _skip(line):
text_buf.append(line)
return stories
def tomten(url = "https://www.gutenberg.org/cache/epub/15753/pg15753.txt", normalise = True):
import re
response = requests.get(url)
assert response.status_code == 200
text = response.text.split("TOMTEN.")[1].split("I NATTEN.")[0]
text = text.replace("\r", "")
buf = []
for line in text.split("\n"):
line = line.strip()
if line == "":
continue
line = re.sub(" +[1-8]?[05]$", "", line)
if normalise:
line = line.replace(",", "")
line = line.replace("--", " ")
line = line.replace('"', "")
if line[-1] in ";:.?!":
line = line[:-1]
line = line.lower()
buf.append(line)
text = "\n".join(buf)
return text
write_with_boilerplate(tomten)
def get_litteraturbanken_page(workid, pageno, normalise = True):
page_url = f"https://litteraturbanken.se/txt/{workid}/res_{str(pageno).zfill(5)}.html?username=app"
response = requests.get(page_url)
response.encoding = "UTF-8"
return response.text
from bs4 import BeautifulSoup
def get_litteraturbanken_text(page, full = False):
soup = BeautifulSoup(page, 'html.parser')
paras = []
if full:
classes = {"class": ["_p", "_head"]}
else:
classes = {"class": "_p"}
for div in soup.find_all("div", classes):
paras.append(div.text)
return paras
def resplit_litteraturbanken(text):
if type(text) != list:
text = [text]
join_page = False
if text[-1][-1] == "-":
join_page = True
prev = ""
buf = []
for part in text:
part = part.replace("-\n", "")
part = part.replace("\xad\n", "")
part = part.replace("\n", " ")
buf.append(part)
return join_page, buf
def join_resplit_litteraturbanken(pages):
return True
paras = get_litteraturbanken_text(get_litteraturbanken_page("lb1814351", 130))
resplit_litteraturbanken(paras)
def efter_torgdagen(url = "https://litteraturbanken.se/f%C3%B6rfattare/BenedictssonV/titlar/Ber%C3%A4ttelserOchUtkast/sida/126/etext", normalise = True):
#https://litteraturbanken.se/txt/lb1814351/res_00125.html?username=app
BASE = url
for num in range(125, 131):
raw = get_litteraturbanken_page("lb1814351", num)
buf = []
if line == "1884.":
buf.append("maj åttonhundra åttiofyra")
return ""
def for_morgonbris(url = "https://web.archive.org/web/20100413161537/http://www.omnibus.se:80/cgi-bin/ebokinfo.pl?eB=395-1", normalise = True):
response = requests.get(url)
assert response.status_code == 200
raw_text = response.text.split('<hr noshade size="1">')
assert '<div class="text2">' in raw_text[1]
lines = raw_text[1].split('<div class="text2">')
lines = [l.split("</div>")[0].replace('\x00', "") for l in lines if '<div class="text1">' not in l]
if normalise:
def cleanup(text):
text = text.strip()
text = text.replace(",", "")
text = re.sub(" +", " ", text)
if text[-1] in ".:!?;":
text = text[:-1]
return text.lower()
lines = [cleanup(l.replace("—", "")) for l in lines]
else:
lines = [l.replace("—", "—") for l in lines]
return "\n".join(lines)
write_with_boilerplate(for_morgonbris)
def jenny(url = "https://www.gutenberg.org/cache/epub/13100/pg13100.txt", normalise = True):
response = requests.get(url)
assert response.status_code == 200
assert "JENNY." in response.text
text = response.text.split("JENNY.")[1].split("JULKVÄLLEN.")[0]
text = text.strip().replace("\r", "")
buf = []
for line in text.split("\n"):
if line.strip() == "":
continue
if normalise:
line = line.replace(". ", " ")
if line.endswith(".--"):
line = line[:-3]
line = line.replace(",", "")
line = line.replace("--", " ")
line = line.replace("?", "")
line = line.replace("!", "")
line = line.replace(":", "")
line = line.replace(";", "")
line = line.replace('"', "")
if line[-1] == ".":
line = line[:-1]
line = re.sub(" +", " ", line)
line = line.strip()
buf.append(line.lower())
else:
buf.append(line)
return "\n".join(buf)
write_with_boilerplate(jenny)
def nocturne(url = "http://web.archive.org/web/20180815020322/http://www.svensklyrik.se/poeter/edith-sodergran/nocturne-2", normalise = True):
response = requests.get(url)
assert response.status_code == 200
text = response.text.split("<pre>")[1].split("</pre>")[0]
if normalise:
text = text.replace("\x97", "")
buf = []
for line in text.split("\n"):
line = line.strip()
line = line.replace(",", "")
if line[-1] == ".":
line = line[:-1]
buf.append(line.lower())
return "\n".join(buf)
else:
return text
write_with_boilerplate(nocturne)
def ett_halvt_ark_papper(url = "http://runeberg.org/strindbg/etthalvt.html", normalise = True):
raw = runeberg_page(url, normalise=False, joined=False)
with MosesSentenceSplitter('sv') as splitsents:
sents = splitsents([sent for sent in raw if sent != ""])
clean = runeberg_norm(sents)
joined = "\n".join(clean)
joined = joined.replace("15 11", "femton elva").replace("50 50", "femtio femtio") # says 'femti'
return joined
write_with_boilerplate(ett_halvt_ark_papper)
def pa_rakstugan(url = "https://sv.wikisource.org/wiki/P%C3%A5_rakstugan", normalise = True):
response = requests.get(url)
assert response.status_code == 200
text = response.text.split('<div class="poem">')[1].split("</div>")[0]
text = text.replace("</p>", "").replace("<p>", "").replace("<br />", "")
if normalise:
text = text.replace("\x97", "")
buf = []
for line in text.split("\n"):
if line == "":
continue
line = line.strip()
line = line.replace(",", "")
if line[-1] == ".":
line = line[:-1]
buf.append(line.lower())
return "\n".join(buf)
else:
return text
write_with_boilerplate(pa_rakstugan)
get_litteraturbanken_page("lb1814351", 125)
WALTERS_NEWPAGE = [7, 8]
def merge_runeberg_paragraphs(a, b, page):
if page in WALTERS_NEWPAGE:
return a + b
else:
a[-1] = a[-1] + " " + b[0]
return a + b[1:]
def get_walters_page(pageno):
raw = runeberg_page(f"http://runeberg.org/topbarn/4/{str(pageno).zfill(4)}.html", False, True)
raw = raw.replace("\n<!-- NEWIMAGE2 -->\n", "")
paras = raw.split("\n\n\n\n")
paras = [p.replace("\n\n", " ") for p in paras]
return paras
p5 = get_walters_page(5)
p6 = get_walters_page(6)
p7 = get_walters_page(7)
merge_runeberg_paragraphs(p5, p6, 6)