Information om denne video
Underviser: Simon Rotendahl Video: 14:34 Lektion nr. 20 af 27
Hvordan bliver vejret i dag?
I videoen her, så fortsætter vi med web scraping. Som eksempel vil vi tage fat i DMI, og trække et billed ud fra deres hjemmeside, som vi så vil gemme på vores computer, alt sammen ved bare at køre et Python program/script, efter vi har lavet programmet skal vi aldrig åbne en webbrowser, for at få den nyeste version af det billed. Selv hvis du ikke skal arbejde med hjemmesider, så se stadig med, hjemmesider er, som sagt tidligere, strømme, og dem kender vi jo allerede lidt til.
Hvis du får problemer, så husk at checke om hjemmesiden du prøver dig på, er bruger https, da denne metode kun virker med http!
Download guide til executable fra et Python script her.
I næste video skal vi kigge på pakken openpyxl!

Hej Simon
Tak for et godt kursus
Linket til PDF’en virker desværre ikke, kan du ikke lægge den op på hjemmesiden?
Casper
Hej Casper,
Undskyld det sene svar, det sker af og til at mine notifikationer bliver fanget i mit email programs spam filter, det er jeg ked af.
Jeg kan godt se at linket til PDF’en er i stykker, så jeg har lavet et nyt her, og så sat gang i at få uploadet PDF’en direkte til siden, som det var meningen den skulle oprindeligt.
https://drive.google.com/file/d/10KLo5nDPdgWRyPif1jcCD_QTbUnldHRh/view?usp=share_link
Mvh.
Simon
Hej Simon
Når jeg kører følgende kode:
import urllib.request as urllibR
import bs4
url = ‘http://dbase.adventurecorps.com/results.php?bw_eid=96&bwr=Go’
BW = urllibR.urlopen(url)
BWBS = bs4.BeautifulSoup(BW.read(), “html5lib”)
images = []
for link in BWBS.find_all(‘img’):
images.append(link.get(‘src’))
for img in images:
if ‘dnk’ in img:
billede = img
urllibR.urlretrieve(billede, ‘DKflag.gif’)
Så får jeg følgende fejl:
File “C:\DEVAPPS\Python\Python38\lib\urllib\request.py”, line 383, in _parse
raise ValueError(“unknown url type: %r” % self.full_url)
ValueError: unknown url type: ‘images/flags/dnk.gif’
Hvordan løser jeg dette?
Mvh.
Brian
Hej Brian,
Det sker fordi den hjemme side du har gemmer filerne med interne links, så du kan se at du rigtig nok får et link til billedet, nemlig “images/flags/dnk.gif”, men når du så kører “urllibR.urlretrieve(billede, ‘DKflag.gif’)” så svarer det til at skrive “images/flags/dnk.gif” i google chrome, og det giver så en fejl. Du kan se at hvis du går på linket her “http://dbase.adventurecorps.com/images/flags/dnk.gif”, så får du rigtig nok billedet. Så det jeg ville gøre er at have to urls i starten altså
hjem = “http://dbase.adventurecorps.com/”
url = “http://dbase.adventurecorps.com/results.php?bw_eid=96&bwr=Go”
og så tilføje den til billede navnet når du retriever, altså
urllibR.urlretrieve(hjem+billede, “DKflag.gif”)
Det bør løse det. Jeg håber det giver mening, ellers må du sige til :)
Mvh.
Simon
Det giver bestemt mening! :-)
Det skal bestemt prøves.
Jeg ved ikke om det kunne være en idé, at opdatere webscraping med hvordan man imødegår https-sider. Langt de fleste sider anvender jo efterhånden https.
Ellers et super godt kursus :-)
Mvh
Brian
Godt det giver mening, og tak for feedbacken, det kunne helt sikkert være en god ide at opdatere webscraping. Jeg tør ikke love noget, men jeg vil forsøge at for lavet en udvidelse med det på et tidspunkt :)
Mvh.
Simon
Hej
Jeg har et problem med den sidste del af videoen. Min terminal giver mig et nameError på ordet billed. Der siger, at det ikke er defineret, selvom jeg som dig har skrevet billed = img og derefter print(billed). Fejlen henviser til kodelinjen print(billed), ikke til linjen billed = img
Mon du kan give et hint?
Ellers rigtig fine videoer om webscraping, det synes jeg er meget relevant og jeg aner en stor brugbarhede forude, så gerne mere af det eller henvise til gode links/kurser.
Koden er:
import urllib.request as urllibR
import bs4
url = “https://www.dmi.dk/lokation/show/DK/2624652/Aarhus/”
dmi = urllibR.urlopen(url)
dmiBS = bs4.BeautifulSoup(dmi.read(), “lxml”)
images = []
for link in dmiBS.find_all(“img”):
images.append(link.get(“src”))
for img in images:
if “=Lysende_natskyer_lille.jpg” in img:
billed = img
urllibR.urlretrieve(billed, “Vejr.png”)
print(billed)
Vh Thomas
Hej Thomas,
Tak for de pæne ord :) og ja webscraping er rigtig brugbart, og det bliver brugt meget nu til dags, hvilket også var grunden til at jeg syntes det var godt med en intro til det i kurset her. Mht. anbefalinger til andre steder så er det lidt svært, da webscraping faktisk ikke er noget jeg selv er blevet undervist i, det er kommet som en sideeffekt af at jeg har lært alt mulig andet og jeg kan derfor ikke bare pege på det materiale jeg lærte af desværre. Med det sagt så har jeg selv brugt ‘freecodecamp.org’ nogle gange når jeg skal sætte mig ind i nye ting, så jeg vil anbefale det, det er også gratis, jeg er nemlig ikke så glad for at anbefale betalte ting, som jeg ikke selv har brugt :)
https://www.freecodecamp.org/news/tag/web-scraping/
Udover det er YouTube selvfølgelig altid en god ressource. Jeg kender desværre ikke danske ressourcer på området :/
Okay mht. problemet. Problemet stammer fra at hvis den side du er på ikke har det billede du søger, så vil ‘billed’ variablet aldrig blive “sat”, altså hvis
if “=Lysende_natskyer_lille.jpg” in img:
aldrig er sandt, så kør vi aldrig linjen
billed = img
og det er det der sker, det er også det nameError betyder, den siger at du referer til en navn (billed) som ingen værdi har (da billed = img aldrig blev kørt).
Jeg har lavet en version af koden som vil vise det lidt bedre, og den kan findes på linket nederst i kommentaren her (det er på et link, da kommentarfeltet her på siden ikke viser indrykninger), så hav den åben mens du læser det næste.
Du kan se her at i linje så sætter jeg
billed = “jeg fandt ikke noget :(”
dvs. at lige meget hvad, så får vi ikke nameError, da billed vil have en værdi. Inde i ‘for img in images:’ løkken printer vi nu img, så vi kan se alle de billeder der er der, det gør vi da vi så kan se om det billede vi søger efter faktisk er der.
Du kan så se i linje 19, her har jeg if’en
‘if billed != “jeg fandt ikke noget :(“:’
det gør sådan at vi kun gemmer billedet hvis at billed har ændret sig fra “jeg fandt ikke noget :(“, ellers vil det give en fejl når den prøver at hente billedet, da “jeg fandt ikke noget :(” jo ikke er en url.
Til sidst, du vil se jeg skriver
urllibR.urlretrieve(“https://www.dmi.dk/”+billed, “Vejr.png”)
i stedet for bare
urllibR.urlretrieve(billed, “Vejr.png”)
og der er fordi DMI har ændret sig siden jeg lavede videoen, nu er alle billeder på siden noget i stil med
“/fileadmin/user_upload/Bruger_upload/Nyhed/2020/5/kobjaelder_TN.jpg”
og det er ikke en gyldig url, men vis man sætter “https://www.dmi.dk/” foran så er den gyldig, og vi har at
“https://www.dmi.dk/” + “/fileadmin/user_upload/Bruger_upload/Nyhed/2020/5/kobjaelder_TN.jpg” = “https://www.dmi.dk//fileadmin/user_upload/Bruger_upload/Nyhed/2020/5/kobjaelder_TN.jpg”
hvilket er en gyldig url.
Det var en lang smøre, jeg håber det hjalp, ellers siger du bare til. Det her er desværre ulempen ved at lave materiale om webscraping, den webscraper vi har her er jo meget specifik på et billede, så når hjemmesiden ændre sig, så kan det ødelægge webscraperen, man kan lave den mere automatisk, så den selv kan håndtere sådanne ting, men det er nærmest et kursus i sig selv :)
Kode – https://pastebin.com/5LZixaaN
Mvh.
Simon
Hej Simon
Først tak for et godt kursus, jeg er allerede blevet meget klogere på Python :)
Jeg har to spørgsmål:
1. Som allerede nævnt af Jessie, så er DMI’s side lavet helt om, og det er ikke længere et billede af byvejr m.fl. de har, men et “element”(?) af flere komponenter. Derfor har jeg forsøgt at finde en anden vejr hjemmeside jeg kunne lave scraping på, men kan konstatere at de fleste sider er bygget sådan op (nu om dage). Mit spørgmål er, findes der en metode til at hente disse elementer – evt. som et screen dump eller findes der måske en helt anden metode man kan anvende her!?
2. Lige præcis sådan noget som vejr, nyheder og den slags er noget man gerne vil have en “update” på en gang om dagen, eller sådan noget. Er det muligt at lave et script det køre dette igennem en gang i døgnet, og sender det til en mail eksempelvis – eller skal man lave en “exe” fil og lave en eller anden ting med i stedet?
Til info, så endte det med at jeg brugte en widget fra https://vejr.eu/sted/ som image til min web scraping… i tilfælde af der er andre der mangler et billede til opgaven.
Hej Kenneth,
Tak for de pæne ord, og ja kan godt se at DMI har ændret sig en del siden jeg lavede videoen for ca. to år siden. Heldigvis, som det lyder til for dig, har videoen været general nok til at kunne anvendes på en anden side, det er jeg glad for at høre :)
1. Ja der er en standard metode for det, det er det der hedder API’er (application programming interface, der er et link til Wiki i bunden). Kort sagt er en API et slags program/bibliotek som et firma har lavet, så man kan tilgå det firmas data, så f.eks YouTube har en API, så man kan tilgå videoer igennem terminalen på ens computer. Jeg har fundet et konkret eksempel på YouTube med en guide til hvordan du bruger Spotify og YouTube API’er således at dine likede sange på YouTube bliver tilføjet til din Spotify, den er dog på engelsk (link i bunden). Du kan følge den hvis du vil, den er dog mest ment til at du kan se et helt konkret eksempel på brugen af API’er.
2. Det er det helt sikkert. Hvordan man vil gøre det kommer an på hvor “vigtigt” det er, hvis det f.eks skal bruges af andre så ville man måske lave et visuelt program ud af det, som kan køre i baggrunden på computeren (lidt over niveau for kurset her). Man kan få computeren til at kører scriptet på et bestemt tidspunkt hver dag (det er forskelligt fra Windows, Mac og Linux, så alt efter hvad du har ville man gøre det anderledes). Man kan også lave det til en kørbar fil (executeable/exe), og så doubleclicke på den en gang om dagen (link i bunden). Jeg ville gøre det sidste. Du kan også sende mails direkte fra Python, så du kan gøre alt sammen i samme script (link i bunden).
Jeg ved det var en masse ting, og en masse links, men ellers ville det blive en meget lang besked, hvis der er nogle af tingene du gerne vil vide mere om, så er du mere end velkommen til at spørge :)
Mvh.
Simon
API – https://en.wikipedia.org/wiki/Application_programming_interface
YouTube eksempel på API – https://www.youtube.com/watch?v=7J_qcttfnJA
Lave Python fil til exe – https://dev.to/eshleron/how-to-convert-py-to-exe-step-by-step-guide-3cfi
Send mails med Python – https://www.freecodecamp.org/news/send-emails-using-code-4fcea9df63f/
Hej Simon.
Siden du har lavet denne video, har DMI lavet deres hjemmeside om, således at deres grafer ikke længere ligger som billeder, men i stedet for, får jeg denne html tekst frem, når jeg vælger et element (grafen) på siden:
Jeg har dog prøvet at kører videre med DMI hjemmesiden alligevel, for der er jo andre billeder på siden som også kan bruges på samme måde tænker jeg.
Men jeg får nu denne fejl i terminalen når jeg forsøger at gemme (jeg har fuldstændig samme kode som dig):
Traceback (most recent call last):
File “.\20 Webscraping med Python del 2.py”, line 17, in
urllibR.urlretrieve(billed, ‘Vejr.png’)
File “C:\Users\jessi\AppData\Local\Programs\Python\Python38-32\lib\urllib\request.py”, line 247, in urlretrieve
with contextlib.closing(urlopen(url, data)) as fp:
File “C:\Users\jessi\AppData\Local\Programs\Python\Python38-32\lib\urllib\request.py”, line 222, in urlopen
return opener.open(url, data, timeout)
File “C:\Users\jessi\AppData\Local\Programs\Python\Python38-32\lib\urllib\request.py”, line 509, in open
req = Request(fullurl, data)
File “C:\Users\jessi\AppData\Local\Programs\Python\Python38-32\lib\urllib\request.py”, line 328, in __init__
self.full_url = url
File “C:\Users\jessi\AppData\Local\Programs\Python\Python38-32\lib\urllib\request.py”, line 354, in full_url
self._parse()
File “C:\Users\jessi\AppData\Local\Programs\Python\Python38-32\lib\urllib\request.py”, line 383, in _parse
raise ValueError(“unknown url type: %r” % self.full_url)
ValueError: unknown url type: ‘/fileadmin/user_upload/Bruger_upload/Nyhed/2020/3/Bunkering_fra_siden_TN.png’
Dog har jeg et andet for loop, som ser således ud (sådan at billede teksten passer med de oplysninger jeg har fundet):
for img in images:
if ‘Bunkering_fra_siden_TN.png’ in img:
billed = img
Kan du umiddelbart se hvad der er der går galt?
På forhånd tak.
Venlig hilsen Jessie Winther Nielsen
Hej Jessie,
Du må undskylde det sene svar, jeg har haft problemer med min mail, så jeg har ikke fået besked om kommentare.
Det er lidt svært for mig at se uden at se hele koden, har du mulighed for at copy paste din kode in på pastebin på linket herunder, og så sende det til mig. Grunden til pastebin det er så indrykkende bliver bibeholdt, det gør de ikke i kommentarene her :)
https://pastebin.com/
Hej Simon
Du omtaler en PDF i video, hvor ligge den?
Mvh Steen
Hej Steen
Det må du undskylde, jeg havde glemt at ligge den PDF op. Den kommer op på siden hurtigst muligt, indtil da, kan du finde den på Google Drev, ved linket her :)
https://drive.google.com/open?id=1RHQmt4g4UDqo69TH-SD755V9mHIXB7Gl