Gutenberg
V domači nalogi delamo z enakimi podatki kot na predavanju in vajah, vendar je projekt Guttenberg na dan ali dva po predavanjih spremenil obliko svojih strani. To je odlično, saj boste morali svoje znanje pokazati na podobni, vendar malenkost drugačni nalogi.
Podatki projekta Gutenberg so dostopni tudi v lažje berljivi obliki. Tole delamo za vajo.
Ocena 6
Za oceno 6 bo potrebno napisati le dve funkciji, ki ne bi smeli imeti več kot 10 vrstic.
Funkcija
prenesi_podatke()
naj stori naslednje.- Če v trenutnem direktoriju (v katerem teče program) ni poddirektorija
authors
, ga naredi (glej koristne funkcije, spodaj). - Vanj direktorij
authors
shrani datoteke s strani https://ucilnica.fri.uni-lj.si/mod/folder/view.php?id=54634. Rezultat prenašanja morajo torej biti datoteke authors/a.html, authors/b.html, authors/c.html ... Datotek, ki že obstajajo, ne prenašaj ponovno.
Predpostaviti smeš, da se datoteke nahajajo na naslovih
https://ucilnica.fri.uni-lj.si/pluginfile.php/217381/mod_folder/content/0/{crka}.html
, pri čemer socrka
male črke angleške abecede.Koristne funkcije:
os.path.exists
os.mkdir
alios.mkdirs
- `string.ascii_lowercase``
urllib.request.urlopen
, ki, pazi, ne vrne niza temveč bajte. Kdor je pozabil, kako to spremeniti v niz, naj bere zapiske, saj smo morali to narediti tudi na predavanju.
V vsem ostanku naloge uporabljaj te datoteke, da ne nadleguješ Učilnice brez potrebe.
- Če v trenutnem direktoriju (v katerem teče program) ni poddirektorija
Funkcija
avtorji(priimek)
vrne seznam vseh avtorjev s podanim priimkom.- Kaj so "avtorji", je očitno s spletne strani: poglej strukturo strani, da uvidiš, za kateri element gre.
- Priimek je vse, kar se nahaja pred prvo vejico v vrstici z imenom avtorja.
- V seznamu naj bodo celotne vrstice.
Klic
avtorji("Fairfax")
vrne seznam['Fairfax, Cecil', 'Fairfax, Edward, -1635']
. Seznam ne vsebuje "Fairfax Muckley, A. (Angelo)", saj je priimek tega avtorja Fairfax Muckley in ne samo Fairfax.Koristne funkcije:
- Elementi, ki jih vrača BeautifulSoup imajo atribut
strings
z vsemi nizi znotraj elementa. Če imamo elementel
, ki vsebuje
<div><a href="peter.html">Peter</<a> je pojedel veliko <img src="melona.png"> in šel v <img src="melona.png">.</div>
bo
el.strings
vseboval"Peter"
," je pojedel veliko "
," in šel v "
, in"."
.strings
ni seznam, temveč generator. Če želimo seznam, pokličemolist(el.strings)
, lahko pa ga podamo tudi kaki drugi funkciji ali metodi, na primer (namig!) metodijoin
, ki jo imajo nizi. (Nasvet: ko združuješ, ne vrivaj presledkov, razen v nalogi za oceno 10.)
Ocena 7
Funkcija
razberi_avtorja(s)
, prejme vrstico z imenom avtorja ter letnicami rojstva in smrti.Če vrstica ne vsebuje ne letnice rojstva ne letnice smrti, funkcija vrne
None
.Sicer pa vrne četverko z naslednjimi elementi:
- niz s priimkom avtorja (vse, kar je pred prvo vejico)
- seznam z ostalimi elementi imena; dobimo ga tako, da vse, kar ni priimek ali letnice, razdelimo po vejicah
- številka z letnico rojstva, če je podana; če ni naj bo ta element enak
None
. - številka z letnico smrti, če je podana; če ni naj bo ta element enak
None
.
Letnici rojstva in smrti sta tisto, kar sledi zadnji vejici, pod pogojem, da imata primerno obliko in sta ločeni z
-
(brez presledkov).Letnica ima primerno obliko, če je
- sestavljena iz števk,
- ki jim morda sledi vprašaj (ki ga ignoriraj) ter,
- morda, presledek, ki mu sledi BC.
Dodatnih presledkov ali drugih znakov ni. Če se v datotekah pojavi kaj, kar je podobno letnici, vendar ne ustreza temu opisu, potem predpostavimo, da to ni letnica in jo ignoriramo. (Pazi: zadnji vejici mora slediti presledek in tako nato letnici. Če je vmes še kaj, na primer "active", potem tega avtorja ignoriraj.)
Letnico pretvori v številko; če ji sledi BC, mora biti negativna.
Če vrstica vsebuje ime brez vejic in nato letnico (na primer Guérin de Bouscal, 1613?-1657), se vedemo, kot da je celotno ime avtorja priimek, imena pa nima.
- Klic
razberi_avtorja('Macaulay, James, Peter, Joe-Ann, 1817?-1902')
vrne("Macaulay", ["James", "Peter", "Joe-Ann"], 1817, 1902)
. - Klic
razberi_avtorja("Cicero, Marcus Tullius, 106 BC-43 BC")
vrne("Cicero", ["Marcus Tullius"], -106, -43)
- Klic
razberi_avtorja("Bach, P. D. Q., 33-12? BC")
vrne("Bach", ["P. D. Q."], 33, -12)
. 33 nima BC, torej je pozitivna, 12 pa, torej je negativna. Ker P. D. Q. Bach. - Klic
razberi_avtorja("Štefan, Jožef")
vrneNone
, ker manjkata letnici. - Klic
razberi_avtorja("Kralj, Ludvik, 1914")
vrneNone
, ker manjkata letnici (1914 je videti kot leto, vendar ni znaka-
) - Klic
razberi_avtorja("Kralj, Ludvik, 1914-ič")
vrneNone
, ker manjkata letnici (ič
niso števke)
Koristne funkcije:
re.match
; glej zapiske predavanja o regularnih izrazih. Tam je skoraj vse, kar potrebujemo, le za BC bo potrebno poskrbeti. Brez tega bo najbrž malo naporneje. Učenje regularnih izrazov je koristna naložba.
Funkcija
zberi_podatke(crke)
prejme niz črk in vrne slovar, katerega ključi so priimki avtorjev, pripadajoče vrednosti pa seznam podatkov za vse avtorje s tem priimkom, pri čemer so "podatki" natančno četverke, ki jih vrača gornja funkcija. Avtorji so urejeni po vrstnem redu njihovega pojavljanja na strani.Funkcija uvrsti v slovar le tiste avtorje, katerih priimek se začne z eno od črk v podanem nizu
crke
. Če je ta niz prazen, pa prebere vse avtorje. Takozberi_podatke("mte")
sestavi slovar le za avtorje, katerih priimki se začnejo z m, t, ali e; kliczberi_podatke("m")
zbere le podatke z avtorji s priimki na črko m; kliczberi_podatke("")
zbere podatke za vse avtorje.Slovar, ki ga vrne
zberi_podatke("g")
se začne tako:{'Gaal': [('Gaal', ['György'], 1783, 1855), ('Gaal', ['József'], 1811, 1866), ('Gaal', ['Mózes'], 1863, 1936)], 'Gabel': [('Gabel', ['Norman E.'], 1906, 1961)], 'Gaboriau': [('Gaboriau', ['Emile'], 1832, 1873)], 'Gabrielean': [('Gabrielean', ['M. Smbat'], 1856, 1919)], 'Gabriel': [('Gabriel', ['Gilbert W. (Gilbert Wolf)'], 1890, 1952)], 'Gabrielian': [('Gabrielian', ['Mugurdich Chojhauji'], 1857, None)], 'Gade': [('Gade', ['John A. (John Allyne)'], 1875, 1955)], 'Gadow': [('Gadow', ['Hans'], 1855, 1928)], 'Gaebelein': [('Gaebelein', ['Arno Clemens'], 1861, 1945)], 'Gaffarel': [('Gaffarel', ['Paul'], 1843, 1920)], 'Gage': [('Gage', ['George W.'], 1887, 1957), ('Gage', ['Harry Lawrence'], 1887, 1982), ('Gage', ['Matilda Joslyn'], 1826, 1898), ('Gage', ['Thomas'], 1603, 1656), ('Gage', ['Thomas'], 1721, 1787)], 'Gagneur': [('Gagneur', ['M.-L. (Marie-Louise)'], 1832, 1902)], ...
Če so poleg
"g"
še druge črke, vsebuje še priimke, ki se začnejo s temi črkami; če ga pokličemo s praznim nizem, pa vsebuje vse avtorje.V program dodaj (izven funkcije!) par vrstic, ki naredijo tole: če trenutni direktorij ne vsebuje datoteke "authors.json", pokliče funkcijo
zberi_podatke("")
in slovar, ki ga funkcija vrne kot rezultat, shrani v datoteko authors.json. Kot je očitno iz končnice, mora biti datoteka zapisana v obliki json.Testi ne bodo preverjali, da ne pišeš datoteke, če že obstaja. Tvoj problem, če bo program brez potrebe počasen.
Vse naslednje funkcije. ki potrebujejo podatke o avtorjih, naj nalagajo to datoteko, namesto da brskajo po HTML-jih. Na ta način se bodo izvajale precej hitreje.
Koristne funkcije:
- modul
json
; glej zapiske.
- modul
Ocena 8
Pazi: Ta in nadaljnje funkcije predpostavljajo, da bereš podatke iz jsona. Pri tem se terke spremenijo v sezname, zato bodo testi pričakovali, četverko s podatki o avtorjih kot sezname in ne terke. Pretvarjanje bi bilo možno, vendar nima smisla, da si zapletamo življenje.
Funkcija
v_obdobju(rojen, umrl, zacetek, konec)
vrneTrue
, če je oseba, ki je živela med letirojen
inumrl
, vsaj del življenja živela znotraj obdobja medzacetek
inkonec
.Pesnik, rojen v 1800 in umrl v 1848, je živel, na primer v obdobjih 1800-1900, 1750-1810, 1848-1552, ne pa v obdobju 1850-1900 ali 1750-1799.
Ena izmed letnic,
rojen
aliumrl
, je lahko tudiNone
. V tem primeru preveri le, ali se letnica, ki je znana, nahaja znotraj odbobja. (Tudi za osebo, ki je umrla 1551, ne bomo trdili, da je živela v 1500-1550, čeprav najbrž je, sicer je ne bi bilo na seznamu.)Predpostaviti smeš, da ne gre za P. D. Q. Bacha in je letnica rojstva manjša ali enaka letnici smrti. Letnica začetka obdobja je manjša ali enaka letnici konca.
Da te odvrnemo od zank in drugih nepotrebnih komplikacij, na primer
range
, pa so letnice lahko tudi izjemno velike, na primer 10^22 in niso nujno cela števila.Koristne funkcije
- Operator
<=
(pa še kakšenis
,not
,and
inor
) bo pametnemu povsem zadoščal. :)
- Operator
Funkcija
avtorji_v_obdobju(zacetek, konec)
vrne seznam vseh avtorjev, ki so živeli v podanem obdobju. Vsak avtor je opisan s četverko, kot so shranjene v authors.json. Za avtorja se šteje, da je živel v podanem obdobju, če tako pravi prejšnja funkcija.Seznam naj bo urejen po priimkih, med tistimi z enakim priimkom pa po ostalih elementih imena.
Klic
avtorji_v_obdobju(1310, 1311)
vrne[['Amir Khusraw Dihlavi', [], 1253, 1325], ['Bury', ['Richard de'], 1287, 1345], ['Dante Alighieri', [], 1265, 1321], ['Gao', ['Ming'], 1306, 1359], ['Joinville', ['Jean', 'sire de'], 1224, 1317], ['Juan Manuel', ['Infante of Castile'], 1282, 1347], ['Liu', ['Ji'], 1311, 1375], ['Llull', ['Ramon'], 1232, 1316], ['Ma', ['Zhiyuan'], 1250, 1324], ['Petrarca', ['Francesco'], 1304, 1374], ['Polo', ['Marco'], 1254, 1324], ['Rolle', ['Richard', 'of Hampole'], 1290, 1349], ['Ruiz', ['Juan'], 1283, 1350], ['Ruusbroec', ['Jan van'], 1293, 1381], ['Shi', ["Nai'an"], 1290, 1365], ['Wang', ['Mian'], 1287, 1359], ['Wang', ['Shifu'], 1260, 1316], ['Zhu', ['Mingshi'], 1260, 1340]]
Koristne funkcije:
- Za urejenja bo dovolj poklicati
sorted
na končnem seznamu, brez posebnih ceremonij. Ta bo urejal po prvem elementu in potem po ostalih.
- Za urejenja bo dovolj poklicati
Funkcija
razpon()
vrne par števil z najzgodnejšo letnico rojstva in najkasnejšo letnico smrti v podatkih.Funkcija mora vrniti
(-1810, 2023)
. Vendar ne goljufaj in to dejansko izračunaj.(Kateri pisatelj je bil rojen leta -1810? Le poteši si radovednost. Ni napaka. Je zanimivo.)
Funkcija
pokritost(zacetek, konec)
vrne seznam, ki vsebuje toliko števil, kolikor je let medzacetek
in (vključno)konec
. Element z indeksomi
pove, koliko avtorjev v bazi je bilo živih v letuzacetek + i
. Upoštevaj le pisatelje z znanima letnicama rojstva in smrti.
Ocena 9
V tej nalogi se bomo ukvarjali z deli avtorjev. Upoštevajte le pisne knjige, ne avdio zapisov - v spodnjem primeru torej le prvo delo, ne drugega.
<li class="pgdbetext"><a href="/ebooks/16527">1001 задача для умственного счета</a> (Russian) (as Author)</li>
<li class="pgdbaudio"><a href="/ebooks/19681">Детство</a> (Russian) (as Author)</li>
Funkcija
razberi_delo(s)
dobi niz, ki morda vsebuje opis dela. Če gre za opis dela, vrne njegov naslov in jezik; sicer vrneNone
.Opis dela je oblikovan tako, da
- naslovu dela
- sledi presledek,
- nato je v oklepajih naveden jezik; lahko vsebuje več besed ("Old English") ali vezaje ("Napoletano-Calabrese"), (opomba: ignorirajte jezike, kateri opis vsebuje kak drug znak kot črke, presledke in vezaje; opravičujem se v času sestavljanja naloge spregledanim govorcem jezika
"Gaellic, Scottish"
- ta jezik ignorirajte, ker njegov opis vsebuje vejico) - sledi presledek,
- nato pa v oklepajih niz
as Author
.
Če ni oklepajev z jezikom in oklepajev z
as Author
, ne gre za opis dela.razberi_delo("Lightships and Lighthouses (English) (as Author)")
vrne("Lightships and Lighthouses", "English")
.razberi_delo("Histoire de la Litterature Anglaise (Volume 1 de 5) (French) (as Author)")
vrne'Histoire de la Litterature Anglaise (Volume 1 de 5)', 'French')
.razberi_delo("My Reminiscences (English) (as Translator)")
vrneNone
.Opisi nekaterih del obsegajo več kot eno vrstico (torej: vsebujejo znake
\n
ali\r
). Ta dela ignoriraj. (Lepše bi bilo, če jih ne bi. Vendar bi vam bilo upoštevanje teh tako ali tako del najbrž samo otežilo nalogo, predvsem pa smo to posebnost spregledali v času pisanja testov, zato jih tudi testi ignorirajo.)
Uporabne funkcije
re.match
. Da bo preprosteje, izdam del izraza, ki bo ulovil jezik:\(([\w\- ]+)\)
:\w
pomeni poljubno črko ali števko.[\w\- ]
pomeni poljubno črko ali števko ali-
ali presledek. Vzvratna poševnica pred-
je potrebna, ker ima-
znotraj[]
sicer poseben pomen;a-f
bi pomenil vse znake med a in f.[\w\- ]+
pomeni zaporedje z vsaj enim takšnim znakom.([\w\- ]+)
: z oklepaji označimo ta del vzorca kot skupino, tako da jo bomo lahko potem izločili zgroups
.\(([\w\- ]+)\)
:\(
in\)
pomenita oklepaj in zaklepaj; vzvratna poševnica je potrebna, ker imata(
in)
v regularnih sicer poseben pomen (glej gornjo vrstico).
V podanem dokumentu bi lahko delo in jezik sicer dobili tudi na drugačen, nekoliko preprostejši način. Vendar povadimo regularne izraze. Kdor ima težave, naj prebere zapiske. Če ne bo dovolj, pa pošlje mail.
Funkcija
dela()
vrne seznam z vsemi deli vseh avtorjev v vseh HTML-jih, ki ste jih pripravili v nalogi za oceno 6. Delo se šteje kot delo, če ga gornja funkcija prepozna kot delo.Elementi seznama naj bodo šesterke z naslednjimi elementi
- ime dela,
- jezik,
- priimek avtorja,
- ostali deli imena avtorja,
- leto rojstva,
- leto smrti.
Prva dva elementa sta torej takšna, kot ju vrne gornja funkcija, ostali štirje so takšni, s kakršnimi smo avtorje opisovali v prejšnjih.
Vrstni red elementov v seznamu je poljuben.
Ker se bo ta funkcija najbrž izvajala več kot 10 sekund, bodo testi prihranili tvoj čas tako, jo bodo nehali testirati, ko se v direktoriju pojavi datoteka works.json.
Koristne funkcije:
- Elementi, ki jih vrača
BeautifulSoup
imajo atributparent
, ki vrne očeta vozlišča. - Elementi imajo tudi metodo
find_previous_sibling(name)
, ki pregleduje prejšnje brate vozlišča in vrne prvega s podanim imenom. Če jeel
nek element, boel.find_previous_sibling("img")
med brati elementael
našel najbližji prejšnji elementimg
.
Podobno kot smo shranili avtorje, shranimo tudi dela. V program dodaj (izven funkcije!) dve, tri vrstice, ki naredijo tole: če trenutni direktorij ne vsebuje datoteke "works.json", pokliče funkcijo
dela()
ter seznam, ki ga funkcija vrne kot rezultat, shrani v datoteko works.json - datoteka mora biti očitno v obliki json.Funkcija
dela_po_jezikih()
vrne slovar, katerega ključi so vsi jeziki, v katerih so napisana dela avtorjev, pripadajoče vrednosti pa število del v tem jeziku.
Ocena 10
Čestitam, prišli ste do nalog z oceno 10. Za vzpodbudo jih ni veliko in niso težke. Z malo spretnosti bo vsaka vsebovala le eno vrstico in potem (mogoče malo daljši, a ne zapleten) return
.
Funkcijo
preveri_delo
definiraj s takimi argumenti:preveri_delo(delo, avtor=None, naslov=None, jezik=None, leto=None)
. Poklicati jo bo možno z, recimopreveri_delo(delo, jezik="English", leto=1950)
.Funkcija prejme opis posameznega dela v obliki šesterke, kakršne smo sestavljali v funkciji
dela()
ter ime (ali del imena) avtorja, ime (ali del imena) dela, jezik dela ali leto. Katerikoli argument (razen prvega) je lahko tudiNone
; če je tako, ga ne upoštevamo. Funkcija vrneTrue
, če velja vse naslednje.Ime avtorja vsebuje podani niz
avtor
. Ime avtorja predtem obdelamo tako, da postavimo imena na začetek in jih združimo s presledki, priimek pa damo na konec. Tako iz"Dostojevski", ["Fjodor", "Mihajlovič"]
nastane"Fjodor Mihajlovič Dostojevski"
; funkcija vrneTrue
, če jeavtor
, na primer"Dostojevski"
,"Mihaj"
ali tudi"ovič Dos"
.Ime dela vsebuje podani podniz
naslov
.naslov
"čin in kaz"
, se ujema z"Zločin in kazen"
.Delo je napisano v zahtevanem jeziku.
Avtor je bil živ v podanem letu
leto
.
Tiste dele poizvedbe, ki so
None
, ignoriramo. Če je, recimo, podan le avtor in jezik, funkcija preveri le, ali gre za delo podanega avtorja v podanem jeziku, naslov dela in leto pa ignorira.Kadar je podan argument
leto
, vendar za avtorja ni znano leto rojstva ali smrti, funkcija vrneFalse
. (Da si ne zapletamo življenja, vrnemoFalse
tudi, če je, recimo, leto rojstva neznano, leto smrti pa sicer morda ravno enako iskanemu letu.)Napiši funkcijo
poisci(avtor=None, naslov=None, jezik=None, leto=None)
, ki vrne seznam vseh del, ki ustrezajo podanim kriterijem.Koristne funkcije:
preveri_delo
:)
Testi
- 8. januar 2024, 18:23