Mam pytanie, właśnie zacząłem naukę Pythona i mam zadanie wskazać najbliższy termin kursu(Daty mam wyciągnięte już z HTMLa) względem podanej daty. Jak najlepiej to rozpisać
A możesz pokazać co zrobiłeś do tej pory? Wybacz, ale po takim opisie problemu nie mogę dociec w czym tkwi jego istota..
W Pythonie jest moduł datetime. W szczególności powinno Cię zainteresować timedelta
, np.:
from datetime import datetime
from datetime import date
from datetime import timedelta
today = date.today() # -> datetime.date(2018, 10, 24)
tomorrow = date(2018, 10, 25)
tomorrow - today # -> datetime.timedelta(days=1)
Serechiel napisał(a):
A możesz pokazać co zrobiłeś do tej pory? Wybacz, ale po takim opisie problemu nie mogę dociec w czym tkwi jego istota..
import requests
from bs4 import BeautifulSoup
ALT + ENTER -> auto podpowiedz
CTRL + SHIFT + F10) -> Run
CTRL + / -> komentarz
CTRL + D -. Duplikacja linii
page = requests.get("https://reaktor.pwn.pl/kurs/python-developer/")
html = BeautifulSoup(page.content,'html.parser')
print(html)
terms = html.findAll(class_ = "column small-12 large-5")
edition = html.findAll(class_ = "column small-12 large-3 text-center")
print(terms[0])
print(terms[1])
print(edition)
for element in sekwencja
for index, term in enumerate(terms):
terms[index] = str(term).replace('
for index, ed in enumerate(edition):
edition[index] = str(ed).replace('
print(terms)
print(edition)</p>
file = open("python_developer.txt","w")
file.write("Terminy kursu: Python Developer \n")
for index, term in enumerate(terms):
file.write('\n\t' + terms[index] + '\n\t' + edition[index])
page = requests.get("https://reaktor.pwn.pl/kurs/analityk-danych//")
html = BeautifulSoup(page.content,'html.parser')
terms = html.findAll(class_ = "column small-12 large-5")
edition = html.findAll(class_ = "column small-12 large-3 text-center")
for index, term in enumerate(terms):
terms[index] = str(term).replace('
for index, ed in enumerate(edition):
edition[index] = str(ed).replace('
print(terms)
print(edition)</p>
file.write("Terminy kursu: Analityk Danych \n")
for index, term in enumerate(terms):
file.write('\n\t' + terms[index] + '\n\t' + edition[index])
file.close()>
Z tego sktyptu wyciągam daty kursów poszczegółnych modułów. Zadanie polega na podpowiedzeniu który kurs startuje najbliżej wyznaczonej dacie(daty wybieramy dowoli)
To jak już Masz te daty, to Stwórz z nich obiekty klasy date
, (some_date = date(2018, 10, 26)
), Wrzuć do listy i mając daną datę:
given_date = date(2018, 10, 24)
dates = [date(2018, 11, 3), date(2018, 11, 10), date(2018, 10, 29)]
def find_closest_date(date, dates):
return date + min(x - g_date for x in dates)
find_closest_date(given_date, dates) # -> datetime.date(2018, 10, 29)
EDIT: Jeśli Masz, sporo dat, ale nie w formacie date
, to bez sensu jest męczyć się i tworzyc te obiekty ręcznie, jak Sparsujesz je do tuple
, to można użyć unpacking i wygenerować całą listę obiektów naraz:
[date(*dat[0:4]) for dat in [(2018, 10, 11), (2018, 10, 22)]]
Dziwne ale chyba nie rozumie komendy date bo wyskakuje bład i wskazuje "=" w wierszu date, (some_date = date(2018, 10, 26)), jako wadliwe
szopen469 napisał(a):
Dziwne ale chyba nie rozumie komendy date bo wyskakuje bład i wskazuje "=" w wierszu date, (some_date = date(2018, 10, 26)), jako wadliwe
Pokaż kod.
<import requests
from bs4 import BeautifulSoup
ALT + ENTER -> auto podpowiedz
CTRL + SHIFT + F10) -> Run
CTRL + / -> komentarz
CTRL + D -. Duplikacja linii
page = requests.get("https://reaktor.pwn.pl/kurs/python-developer/")
html = BeautifulSoup(page.content,'html.parser')
print(html)
terms = html.findAll(class_ = "column small-12 large-5")
edition = html.findAll(class_ = "column small-12 large-3 text-center")
print(terms[0])
print(terms[1])
print(edition)
for element in sekwencja
for index, term in enumerate(terms):
terms[index] = str(term).replace('
for index, ed in enumerate(edition):
edition[index] = str(ed).replace('
print(terms)
print(edition)</p>
file = open("python_developer.txt","w")
file.write("Terminy kursu: Python Developer \n")
for index, term in enumerate(terms):
file.write('\n\t' + terms[index] + '\n\t' + edition[index])
page = requests.get("https://reaktor.pwn.pl/kurs/analityk-danych//")
html = BeautifulSoup(page.content,'html.parser')
terms = html.findAll(class_ = "column small-12 large-5")
edition = html.findAll(class_ = "column small-12 large-3 text-center")
for index, term in enumerate(terms):
terms[index] = str(term).replace('
for index, ed in enumerate(edition):
edition[index] = str(ed).replace('
print(terms)
print(edition)</p>
file.write("Terminy kursu: Analityk Danych \n")
for index, term in enumerate(terms):
file.write('\n\t' + terms[index] + '\n\t' + edition[index])
file.close()
date, (some_date = date(2018, 10, 26)),
date, (some_date = date(2018, 11, 24)),
date, (some_date = date(2018, 11, 24)),
given_date = date(2018, 10, 23)
dates = [date(2018, 10, 27), date(2018, 11, 24), date(2018, 11, 24)]
def find_closest_date(date, dates):
return date + min(x - g_date for x in dates)
find_closest_date(given_date, dates)
-> datetime.date(2018, 10, 29)>
Mała uwaga:
file = open("python_developer.txt","w")
https://docs.quantifiedcode.com/python-anti-patterns/maintainability/not_using_with_to_open_files.html
I chyba bardziej pasuje tu "a", "w" powoduje nadpisanie zawartości pliku. Dobrą praktyką jest też dodanie obsługi błędów
W skrócie:
try:
with open("plik", "a") as file:
operacje
except FileNotFoundError:
coś tam
Ogólnie - "w" gdy chcemy zapisać raz do pliku i go nie zmieniać, "a" - gdy zamierzamy coś dopisać
Dziwne ale chyba nie rozumie komendy date bo wyskakuje bład i wskazuje "=" w wierszu date, (some_date = date(2018, 10, 26)), jako wadliwe
Nie zauważyłem tam importu modułu datetime.
szopen469 napisał(a):
Dziwne ale chyba nie rozumie komendy date bo wyskakuje bład i wskazuje "=" w wierszu date, (some_date = date(2018, 10, 26)), jako wadliwe
Bo tam Masz błąd składniowy, ma być: some_date = date(2018, 10, 26)
. Poza tym po co ta linijka jest przepisana trzy razy ze zmenionymi datami?
Teraz nie może zdefiniować g-date
NameError: name 'g_date' is not defined
co do tuple chyba to ciut za wysoki poziom na kogoś kto na razie ogarnia podstawy typu wyciąganie info ze stron ;)
Napisałem 3 razy bo chciałem sprawdzić jak to dokładnie działa.
Nie Poprawiłeś w kodzie, powinno być wszędzie g_date
albo given_date
. Jak Będziesz miał daty w dates
, jakoś tam dodane, to powinno działać:
from datetime import date
def find_closest_date(date, dates):
return date + min(x - given_date for x in dates)
date1 = date(2018, 11, 3)
date2 = date(2018, 11, 17)
date3 = date(2018, 10, 30)
given_date = date(2018, 10, 27)
dates = [date1, date2, date3]
print(find_closest_date(given_date, dates)) # -> 2018-10-30
Chyba to jest właśnie to. Dzięki wielkie. :D
No może poza faktem że uparcie wskazuje najniższą datę :/
Jak chcesz najbliższą przyszłą, trzeba dodać tam warunek który sprawdzi czy data już nie minęła :)
from datetime import date
#Cały try except można wywalić, gdy mamy 100% pewności że data nie będzie większa od wszystkich w dates.
def find_closest_date(date, dates):
try:
return date + min(x - given_date for x in dates if x >= given_date)
except ValueError as exc:
return None
date1 = date(2018, 11, 3)
date2 = date(2018, 11, 17)
date3 = date(2018, 10, 30)
given_date = date(2018, 12, 2)
dates = [date1, date2, date3]
print(find_closest_date(given_date, dates)) # -> 2018-10-30
Jeśli byś chciał po prostu najbliższą od wprowadzonej, wystarczy pokombinować z abs()
:)
Z treści zadania wynikałoby że najbliższa od wprowadzonej, No pomyśle czy abs da rade
W takim razie:
return min(dates, key=lambda x: abs(x - date))
Minimalna według klucza wartości bezwzględnej z odejmowania :)
Metoda ma jedną wadę - gdy odległość pomiędzy datami jest jednakowa, zwraca datę wcześniej występującą w liście dat zaproponowanych.
Dlatego że jest to sortowanie zachowujące kolejność elementów w przypadku równości ich wartości do sortowania :p
(Czyli sortowanie jest stabilne, niestabilne zapewnia losowość gdy klucz do sortowania jest jednakowy)
Ale to pozwoli ci się w pewien sposób jeszcze pobawić z tym programem - w przypadku jednakowych odległości możesz brać dwie minimalne wartości zamiast jednej :).
I w końcu działa tak jak trzeba, dzięki za pomoc. Teraz tylko zobaczę jak można by tym poprzekrztałcać