Abschalten vom Entwickleralltag und lesen. Aber so richtig komfortabel sucht man sich sein Ebook bei der Onleihe Bonn doch mit etwas Programmierung. Oder du lädst dir hier die von mir erstellte und in Excel einlesbare Datei herunter und benutzt dann sozusagen dein Tabellenkalkulationsprogrammm als Oberfläche. Du kannst dann auch nach Verlag oder Erscheinungsjahr filtern. Ich möchte z.B. nicht monatelang ein Buch lesen, da ich (noch) wenig lese und daher brauche ich Bücher < 300 Seiten. Sowieso kann man ein Buch maximal 21 Tage lang ausleihen.

Hier alle Informationen zu allen Belletristik-Ebooks der Onleihe für die Stadtbibliothek in Bonn

Das war die Kurzversion für Ungeduldige. Nachfolgend in Langform. Der nachfolgende Code schreibt alle ca. 6000 Ebooks erstmal ohne Details im JSON-Format in eine Datei, jedes Buch jeweils mit Link, so dass wir uns im zweiten Schritt die Details holen können.

import urllib.request
from bs4 import BeautifulSoup
import json

url = "http://www3.onleihe.de/bonn/frontend/"
next_link = url + "mediaList,0-2-0-101-0-0-0-0-400001-0-0.html"
books = []
while next_link:
    response = urllib.request.urlopen(next_link)
    html_doc = response.read().decode("utf8")
    response.close()
    soup = BeautifulSoup(html_doc, 'html.parser')
    lis = soup.find(id="titlelist").contents[7].find_all('li')
    for li in lis:
        book = {}
        title_tag = li.find("span", string="Titel:")
        book['Titel'] = title_tag.nextSibling
        subtitle_tag = li.find("span", string="Untertitel:")
        book['Untertitel'] = subtitle_tag.nextSibling if subtitle_tag else ""
        author_link = li.find(title="Alle Titel des Autors anzeigen")
        book['Autor'] = author_link.text.replace('\r', '').replace('\n', '') if author_link else ""
        verlag_tag = li.find(class_="item-1", string="Verlag:")
        book['Verlag'] = verlag_tag.parent.contents[3].text
        l_row = li.find(class_="l-row")
        book['Link'] = l_row.find("a", class_="anchor").attrs['href']
        print (str(book))
        # >>> {'Titel': 'Bevor wir verschwinden', 'Untertitel': 'Roman', 'Autor': 'Fuchs, David',
        # >>>   'Verlag': 'Haymon Verlag', 'Link': 'mediaInfo,0-0-760854085-200-0-0-0-0-0-0-0.html'}
        # prüfen, ob es sich nur um Strings handelt, komplexere Objekte können später nicht serialisiert werden
        books.append(book) if all(isinstance(value, str) for value in book.values()) else \
            print ("Kann nicht in JSON serialisiert werden, bleibt draußen")
    next_link = soup.find("a", title="Seite weiter")
    next_link = url + next_link.attrs['href'] if next_link else ''
with open('data.json', 'w') as outfile:
    json.dump(books, outfile)

Jetzt holen wir uns die Details:

import json
import urllib.request
from bs4 import BeautifulSoup

with open('data.json') as f:
    data = json.load(f)
    i = 0
    try:
        for book in data:
            response = urllib.request.urlopen("http://www3.onleihe.de/bonn/frontend/" + book['link'])
            html_doc = response.read().decode("utf8")
            response.close()
            soup = BeautifulSoup(html_doc, 'html.parser')
            item_info = soup.find(class_="item-info")
            year_tag = item_info.find(class_="item-2", string="Jahr:")
            book['Jahr'] = year_tag.parent.contents[4].text
            isbn_tag = item_info.find(title="Internationale Standardbuchnummer", string="ISBN")
            book['ISBN'] = isbn_tag.parent.parent.contents[4].text if isbn_tag else None
            pages_tag = item_info.find(class_="item-2", string="Umfang:")
            book['Seiten'] = pages_tag.parent.contents[4].text if pages_tag else None
            language_tag = item_info.find(class_="item-2", string="Sprache:")
            book['Sprache'] = language_tag.parent.contents[4].text if language_tag else None
            content_tag = item_info.find('h3', string="Inhalt:")
            book['Inhalt'] = content_tag.parent.parent.contents[3].text if content_tag else None
            author_info_tag = item_info.find('h3', string="Autor(en) Information:")
            book['Autoreninfo'] = author_info_tag.parent.parent.contents[3].text if author_info_tag else None
            # Es sind nur Werte vom Typ String erlaubt, da sonst nicht nach JSON serialisierbar
            book = {k: v for k, v in book.items() if isinstance(v, str)}
            i += 1
            print ("book nr. {}".format(str(i)))
    # falls etwas passiert, alles in einem JSON-Dump speichern, dann haben wir ein Teilergebnis, an das wir anknüpfen können
    # alles läuft aber durch. Wir können/sollten nicht öfter 6000 Einzelseiten absurfen, um den Server nicht unnötig zu überlasten
    except Exception as e:
        print(e)
        with open('data-2.json', 'w') as outfile:
            json.dump(data, outfile)
    with open('data-2.json', 'w') as outfile:
        json.dump(data, outfile)

Schließlich kann dein Tabellenkalkulationsprogramm kein JSON lesen und deshalb wird die JSON-Datei in CSV umgewandelt. Aus der Seitenzahl wird auch informationstechnisch eine Seitenzahl gemacht, so dass danach gefiltert werden kann.

import json
import csv
import re

keys = ['Titel', 'Untertitel', 'Autor', 'Verlag', 'Link', 'Jahr', 'ISBN', 'Seiten', 'Sprache', 'Inhalt', 'Autoreninfo']
with open('data-2.json') as f:
    data = json.load(f)
    csvData = [keys]
    for book in data:
        # Aus einem String eine Zahl machen, damit man in Excel nach der Seitenzahl filtern kann
        if book['Seiten']:
            try:
                re_findall = re.findall('\d+', book['no_pages'])[0]
                book['Seiten'] = int(re_findall)
            except Exception as e:
                print(e)
        csvData.append([book[x] for x in keys])
    with open('data-2.csv', 'w') as csvFile:
        csv.writer(csvFile).writerows(csvData)
    csvFile.close()