Pri delu si lahko pomagaš z zapiski, vendar ne uporabljaj enake povezave kot tam: stran z imeni avtorjev, ki se začnejo s črko b, pridobi na naslovu https://ucilnica.fri.uni-lj.si/mod/resource/view.php?id=54610.

  1. Napiši program, ki izpiše imena vseh avtorjev, naštetih na strani.
Rešitev
from urllib.request import urlopen
from bs4 import BeautifulSoup

url = "https://ucilnica.fri.uni-lj.si/mod/resource/view.php?id=54610"
html = urlopen(url).read()
soup = BeautifulSoup(html, 'html.parser')

for link in soup.find_all("a"):
    if "name" in link.attrs:
        print(link.text)
  1. Dopolni program tako, da sestavi slovar, katerega ključi so avtorji del, vrednosti pa pripadajoče oznake, npr. a556.
Rešitev
avtorji = {}
for link in soup.find_all("a"):
    if "name" in link.attrs:
        author = link.text
        avtorji[author] = link.attrs["name"]
  1. V datoteko zapiši dokument v obliki Markdown, ki vsebuje seznam (= alineje) z imeni avtorjev. Imena naj delujejo kot povezave v dokument. Babbage, na primer, je zapisan z

    - [Babbage, Charles, 1791-1871](https://ucilnica.fri.uni-lj.si/mod/resource/view.php?id=54610#a556)
    

    Ali je oblikovanje pravilno in ali povezave delujejo, lahko preveriš tako, da skopiraš nekaj vrstic v Jupyter (če za programiranje uporabljaš tega), ali pa ga odpreš v PyCharmu (vanj ga preprosto povleci).

Rešitev
with open("avtorji.md", "w") as f:
    for a, n in avtorji.items():
        f.write(f"- [{a}]({url}#{n})\n")
  1. Spremeni slovar tako, da

    • bo ključ vseboval samo ime avtorja, brez letnic rojstva
    • pripadajoča vrednost bo trojka z interno oznako (npr. a556), letnico rojstva in letnico smrti.

    Pri tej nalogi po možnosti uporabi regularne izraze.

Rešitev
import re

avtorji = {}
for link in soup.find_all("a"):
    if "name" in link.attrs:
        avtor = link.text
        r = s = ""
        res = re.search(r"(.*), (\d*)\??-(\d*)\??", avtor)
        if res is not None:
            avtor, r, s = res.groups()
            if r:
                r = int(r)
            if s:
                s = int(s)
        avtorji[avtor] = (link.attrs["name"], r, s)
  1. Spremeni datoteko z Markdownom tako, da bodo avtorji urejeni po stoletjih, v katerem so se rodili. Stoletja naj bodo mednaslovi, na primer

    ## 1700 - 1799
    
Rešitev
min_rojstvo = min(x for _, x, _ in avtorji.values() if x) // 100 * 100
max_rojstvo = max(x for _, x, _ in avtorji.values() if x) // 100 * 100

with open("avtorji1.md", "w") as f:
    for st in range(min_rojstvo, max_rojstvo + 100, 100):
        f.write(f"## {st} - {st + 99}\n\n")
        for a, (n, r, _) in avtorji.items():
            if r and st <= r < st + 100:
                f.write(f"- [{a}]({url}#{n})\n\n")
  1. Sestavi slovar, katerega ključi so imena avtorjev (brez letnic), pripadajoče vrednosti pa seznami naslovo njihovih del. Imena del naj ne vsebujejo jezikov in opomb "as Author".

  2. Iz seznamov, nabranih v prejšnji točki, izloči tista "dela", ki so pravzaprav le povezave na Wikipedijo. (Oziroma, obratno, obdrži le dela, pri katerih je opomba "as Author").

  3. Vrni se k točki 6: pripadajoča vrednost naj ne bo seznam naslovov, temveč seznam parov (naslov, jezik).

Rešitev
from collections import defaultdict

avtorji = {}
dela = defaultdict(list)
for link in soup.find_all("a"):
    if "name" in link.attrs:
        avtor = link.text
        r = s = ""
        res = re.search(r"(.*), (\d*)\??-(\d*)\??", avtor)
        if res is not None:
            avtor, r, s = res.groups()
            if r:
                r = int(r)
            if s:
                s = int(s)
        avtorji[avtor] = (link.attrs["name"], r, s)

        next = link.find_next("ul")
        for delo in next.find_all("li", {"class": "pgdbetext"}):
            naslov = delo.a.text
            besedilo = delo.text
            if "(as Author)" in besedilo:
                jezik = re.findall(r"\(.*?\)", besedilo)[-2].strip("()")
                dela[avtor].append((naslov, jezik))
  1. Sestavi dokument markdown, v katerem bodo navedena vsa dela vseh avtorjev v takšni obliki:

    • glavni naslovi so imena jezikov
    • podnaslovi so imena avtorjev, ki so napisali vsaj eno delo v tem jeziku
    • znotraj tega podnaslova so našteta vsa dela tega avtorja v tem jeziku.
Rešitev
jeziki_avtorji_dela = defaultdict(lambda: defaultdict(list))

for avtor, dela_ in dela.items():
    for naslov, jezik in dela_:
        jeziki_avtorji_dela[jezik][avtor].append(naslov)

with open("dela.md", "w") as f:
    for jezik, avtor_dela in jeziki_avtorji_dela.items():
        f.write(f"# {jezik}\n\n")
        for avtor, dela_ in avtor_dela.items():
            f.write(f"## {avtor}\n\n")
            f.write("\n".join(f"- {d}" for d in dela_) + "\n\n")