Dateien herunterladen und in einem Verzeichnis ablegen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
pixewakb
User
Beiträge: 1413
Registriert: Sonntag 24. April 2011, 19:43

Wo genau hakt es jetzt im Quellcode? Grob verstehe ich, was Du da machen willst.

Code: Alles auswählen

def get_url(start_wk, end_wk):
    for week in range(start_wk, end_wk):
        pass
    return week
Ich rate oben mal, was Du eigentlich willst. Ich vermute, dass Du die Zahl der Wochen zwischen den zwei Wochen-Daten haben möchtest. Wenn Du in der For-Schleife direkt ein return verbaust, dann wird die Schleife direkt beim ersten Wert für Woche verlassen und 1 zurückgeliefert. Mein Quellcode ändert das. Wenn es nur um die Differenz geht, würde ich die Schleife weglassen und direkt "return end_wk - start_wk" dahinschreiben. Du siehst, dass Du da keine URL erhältst, d. h. der Funktionsname ist falsch.

PS Hättest Du den Link direkt gepostet, wären es nicht 3 Seiten Diskussion geworden.
aaron
User
Beiträge: 92
Registriert: Donnerstag 1. Dezember 2016, 23:10

Das ist meine Lösung

Code: Alles auswählen

def week(start_date, end_date):
    weeks = rrule.rrule(rrule.WEEKLY, dtstart = start_date, until=end_date)
    return weeks.count()
Benutzeravatar
pixewakb
User
Beiträge: 1413
Registriert: Sonntag 24. April 2011, 19:43

Sprachlich scheinst Du besser unterwegs zu sein, als ich. Schön, wenn es klappt.
Sirius3
User
Beiträge: 18265
Registriert: Sonntag 21. Oktober 2012, 17:20

@aaron: ich seh gerade, dass ich in »fetch_whole_year« eigentlich auch schon viel zu viel mache. Besser wäre es noch ein »fetch_single_week« zu nehmen:

Code: Alles auswählen

def fetch_single_week(symbol, year, week):
    if not exists_file(symbol, year, week):
        data = pull_file(symbol, year, week)
        print_data_length(data)
        save_file(symbol, year, week, data)
    else:
        print("File for {}/{}/{} already fetched.".format(symbol, year, week))
womit man dann einen einzelnen Download ganz einfach testen kann:

Code: Alles auswählen

fetch_single_week("Alpha", 2015, 41)
aaron
User
Beiträge: 92
Registriert: Donnerstag 1. Dezember 2016, 23:10

Hallo Sirius könntest Du dir bitte noch einmal das Script anschauen. Ich bekommen folgende Fehlermeldung:

Code: Alles auswählen

python TickDataCsv27.py 
Traceback (most recent call last):
  File "TickDataCsv27.py", line 89, in <module>
    main()
  File "TickDataCsv27.py", line 86, in main
    fetch_single_week("EURAUD", 2015, 41)
  File "TickDataCsv27.py", line 71, in fetch_single_week
    if not exists_file(symbol, year, week):
  File "TickDataCsv27.py", line 56, in exists_file
    return os.path.isfile(generate_filename(symbol, year, week))
  File "TickDataCsv27.py", line 48, in generate_filename
    return os.path.join("data", symbol, year, '{}.csv.gz'.format(week))
  File "/usr/lib64/python2.7/posixpath.py", line 75, in join
    if b.startswith('/'):
AttributeError: 'int' object has no attribute 'startswith'
Ich habe noch eine Funktion für das Herunterladen der Daten zwischen einem Startdatum und einem Enddatum eingebaut.
Sirius3
User
Beiträge: 18265
Registriert: Sonntag 21. Oktober 2012, 17:20

Das Problem kann man auf die Funktion generate_filename zurückführen, und dass year eine Zahl und kein String ist.

Code: Alles auswählen

def generate_filename(symbol, year, week):
    return os.path.join("data", symbol, str(year), '{}.csv.gz'.format(week))
aaron
User
Beiträge: 92
Registriert: Donnerstag 1. Dezember 2016, 23:10

Die Funktion fetch_single_week funktioniert einwandfrei. Ich habe eine neue Funktion geschrieben

Code: Alles auswählen

# Start date (Year, Month, Day)
start_date = datetime.date(2015, 1, 4)
# End date (Year, Month, Day)
end_date = datetime.date(2016, 2, 9)

Die Codezeilen oben stören mich. Geht es vielleicht innerhalb der Funktion? 

def fetch_time_period(symbol, start_date, end_date):
    for week in range(start_date.isocalendar()[1], end_date.isocalendar()[1]):
        year = str(start_date.isocalendar()[0])
        if not exists_file(symbol, year, week):
            data = pull_file(symbol, year, week)
            print_data_length(data)
            save_file(symbol, year, week, data)
        else:
            print("File for {}/{}/{} already fetched.".format(symbol, year, week))
def main():
Als Ergebnis hätte ich gern:
fetch_time_period("symbol", "2015, 1, 4", "2016, 2, 9")

Aktuell sieht es so aus:
fetch_time_period("symbol", start_date, end_date)

Die Funktion läuft zwar, aber nach dem 5. Durchlauf bricht diese unerwartet ab.
Sirius3
User
Beiträge: 18265
Registriert: Sonntag 21. Oktober 2012, 17:20

@aaron: Dir ist klar, dass das so nicht funktionieren kann. Welchen Wert hat denn year so über die Jahre?
aaron
User
Beiträge: 92
Registriert: Donnerstag 1. Dezember 2016, 23:10

der Wert von year über die Jahre. Ich verstehe die Frage nicht ganz. Also wir beginnen 02.01.1999 bis letzte Kalenderwoche des laufenden Jahres. Und es geht jede Woche so weiter. Das meinst du aber mit Sicherheit nicht. year = str(start_date.isocalendar()[0]) scheint falsch zu sein.

year = datetime.datetime.start_date().year ??

Stichwort timedelta?
aaron
User
Beiträge: 92
Registriert: Donnerstag 1. Dezember 2016, 23:10

Bitte schaut euch die Funktion an. ich möchte ein Anfangsdatum und ein Enddatum eingeben. ich bekomme die Fehlermeldung
for week in range(datetime.date(start_date).isocalendar()[1], datetime.date(end_date).isocalendar()[1]):
TypeError: an integer is required

Code: Alles auswählen

def fetch_time_period(symbol, start_date, end_date):
    for week in range(datetime.date(start_date).isocalendar()[1], datetime.date(end_date).isocalendar()[1]):
            year = str(start_date.isocalendar()[0])
        if not exists_file(symbol, year, week):
            data = pull_file(symbol, year, week)
            print_data_length(data)
            save_file(symbol, year, week, data)
        else:
            print("File for {}/{}/{} already fetched.".format(symbol, year, week))

def main():
    # "symbol", "year, month, day", "year, month, day"
    fetch_time_period("symbol", "2015,1,4", "2016, 3, 4")

if __name__ == '__main__':
    main()
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Man kann keine ranges mit datetime-Objekten machen. Selbst wenn man koennte, der default von "+1" wuerde keinen Sinn machen - was ist die 1? Eine Sekunde, ein Jahr, ein Aeon? Das muss also schon angegeben werden.

Aber in Python ist so etwas ja schoen einfach selbst geschrieben:

Code: Alles auswählen

import datetime as dt

def daterange(from_, to, step):
    current = from_
    while current < to:
        yield current
        current += step


def main():
    for point in daterange(dt.datetime.now(), dt.datetime.now() + dt.timedelta(days=10), dt.timedelta(days=1)):
        print(point)

if __name__ == '__main__':
    main()
Benutzeravatar
kbr
User
Beiträge: 1507
Registriert: Mittwoch 15. Oktober 2008, 09:27

@aaron: Du übergibst an

Code: Alles auswählen

datetime.date(start_date).isocalendar()[1]
'start_date' als String. Dies verursacht die Fehlermeldung. Statt "2015,1,4" musst Du die drei Integer separat als positionierte Argumente übergeben. Dann kannst Du aber auch direkt den Monat als Integer an range übergeben, denn nichts anderes erhältst Du durch Dein Konstrukt zurück.

Dann wird auch ersichtlich, dass Dein 'for week in range...' nicht das bewirkt, was Du vermutest.
aaron
User
Beiträge: 92
Registriert: Donnerstag 1. Dezember 2016, 23:10

Ich teste soeben das Script und da fallt mir auf, daß das Script mit einer Fehlermeldung abbricht.
Es wird ein Symbol abgefragt, welches nicht auf dem Server vorhanden ist, weil das Symbol nicht vorhanden ist, oder das Datum in der Zukunft liegt. Wenn das Script feststellt, daß einer dieser Fälle eingetroffen ist, dann soll das Script nicht abbrechen, sondern mit der nächsten Aufgabe weitermachen und in ein Logfile schreiben, daß die Files 1.csv.gz - 10.csv.gz heruntergeladen worden sind, aber das File 11.csv.gz noch nicht vorhanden ist.

Code: Alles auswählen

python TickDataCsv27.py 
133135278
data/Alpha/2017/1.csv.gz
161435294
data/Alpha/2017/2.csv.gz
145706620
data/Alpha/2017/3.csv.gz
124924322
data/Alpha/2017/4.csv.gz
135177334
data/Alpha/2017/5.csv.gz
95338134
data/Alpha/2017/6.csv.gz
125369326
data/Alpha/2017/7.csv.gz
122297816
data/Alpha/2017/8.csv.gz
138437782
data/Alpha/2017/9.csv.gz
122760250
data/Alpha/2017/10.csv.gz
Traceback (most recent call last):
  File "TickDataCsv27.py", line 88, in <module>
    main()
  File "TickDataCsv27.py", line 81, in main
    fetch_whole_year("Alpha", 2017)
  File "TickDataCsv27.py", line 60, in fetch_whole_year
    data = pull_file(symbol, year, week)
  File "TickDataCsv27.py", line 19, in pull_file
    response = urllib2.urlopen(url)
  File "/usr/lib64/python2.7/urllib2.py", line 154, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/lib64/python2.7/urllib2.py", line 437, in open
    response = meth(req, response)
  File "/usr/lib64/python2.7/urllib2.py", line 550, in http_response
    'http', request, response, code, msg, hdrs)
  File "/usr/lib64/python2.7/urllib2.py", line 475, in error
    return self._call_chain(*args)
  File "/usr/lib64/python2.7/urllib2.py", line 409, in _call_chain
    result = func(*args)
  File "/usr/lib64/python2.7/urllib2.py", line 558, in http_error_default
    raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
urllib2.HTTPError: HTTP Error 404: Not Found
Sirius3
User
Beiträge: 18265
Registriert: Sonntag 21. Oktober 2012, 17:20

@aaron: das Stichwort heißt Exception-Handling.
aaron
User
Beiträge: 92
Registriert: Donnerstag 1. Dezember 2016, 23:10

Bitte schaut Euch einmal die Funktion an. Ich verstehe die Fehlermeldung nicht. Ist die Idee richtig?

Code: Alles auswählen

def fetch_time_period(symbol, start_date, end_date):
    for week in rrule.rrule(rrule.WEEKLY, dtstart = datetime.start_date, until = datetime.end_date):
        if not exists_file(symbol, year, week):
            data = pull_file(symbol, year, week)
            print_data_length(data)
            save_file(symbol, year, week, data)
        else:
            print("File for {}/{}/{} already fetched.".format(symbol, year, week))
            
def main():
    fetch_time_period("Alpha", "2015,1,4", "2016, 3, 4")

if __name__ == '__main__':
    main()
Die Fehlermeldung sieht so aus:

Code: Alles auswählen

Traceback (most recent call last):
  File "TickDataCsv27.py", line 92, in <module>
    main()
  File "TickDataCsv27.py", line 89, in main
    fetch_time_period("Alpha", "2015,1,4", "2016, 3, 4")
  File "TickDataCsv27.py", line 60, in fetch_time_period
    for week in rrule.rrule(rrule.WEEKLY, dtstart = datetime.start_date, until = datetime.end_date):
AttributeError: 'module' object has no attribute 'start_date'
Zuletzt geändert von Anonymous am Dienstag 21. März 2017, 22:52, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 18265
Registriert: Sonntag 21. Oktober 2012, 17:20

@aaron: warum glaubst Du, dass das Modul datetime ein Attribut start_date hat?
aaron
User
Beiträge: 92
Registriert: Donnerstag 1. Dezember 2016, 23:10

Gut datetime heraus genommen. Jetzt sieht der Code so aus:

Code: Alles auswählen

# Funktion noch nicht funktionsfähig.
def fetch_time_period(symbol, start_date, end_date):
    for week in rrule.rrule(rrule.WEEKLY, dtstart = start_date, until = end_date):
        if not exists_file(symbol, year, week):
            data = pull_file(symbol, year, week)
            print_data_length(data)
            save_file(symbol, year, week, data)
        else:
            print("File for {}/{}/{} already fetched.".format(symbol, year, week))
Jetzt sieht die Fehlermeldung so aus. Mit toordinal habe ich auch schon herumexperimentiert. Ich habe die Dokumentation auch schon zig mal gelesen. Was ist falsch an der Idee?

Code: Alles auswählen

Traceback (most recent call last):
  File "TickDataCsv27.py", line 92, in <module>
    main()
  File "TickDataCsv27.py", line 89, in main
    fetch_time_period("Alpha", "2015,1, 4", "2016, 3, 4")
  File "TickDataCsv27.py", line 60, in fetch_time_period
    for week in rrule.rrule(rrule.WEEKLY, dtstart = start_date, until = end_date):
  File "/usr/lib/python2.7/site-packages/dateutil/rrule.py", line 240, in __init__
    dtstart = datetime.datetime.fromordinal(dtstart.toordinal())
AttributeError: 'str' object has no attribute 'toordinal'
Benutzeravatar
kbr
User
Beiträge: 1507
Registriert: Mittwoch 15. Oktober 2008, 09:27

@aaron: Nun versuchst Du den String "2015,1,4" als Attribute von datetime anzusprechen und dtstart zuzuweisen, gleiches bei until. Das geht natürlich nicht und schaut – leider – schwer nach Raten aus. Wenn start_date und end_date denn unbedingt dieses Format haben müssen, dann könntest Du diese beiden Strings wie folgt für rrule konvertieren:

Code: Alles auswählen

def fetch_time_period(symbol, start_date, end_date):
    # start_date sei: "2015, 1, 4"
    start_date = datetime.date(*map(int, start_date.split(',')))
    # selbiges mit end_date:
    ...
    for week in rrule.rrule(rrule.WEEKLY, dtstart=start_date, until=end_date):
        ...
oder Dir einen besser passenden Datentyp für die Parameter überlegen; also direkt datetime.date Objekte. Was ich Dir auch sehr empfehlen würde. Denn obiges ist weder schön und noch ist sofort einsichtig, was dort passiert. Und das eher von Nachteil.
Benutzeravatar
kbr
User
Beiträge: 1507
Registriert: Mittwoch 15. Oktober 2008, 09:27

@aaron: In einem meiner letzten Posts hatte ich mit dem Hinweis auf

Code: Alles auswählen

datetime.date(start_date).isocalendar()[1]
etwas falsches geschrieben: Wenn Du ein gültiges Date-Objekt als start_date übergibst erhältst Du durch .isocalendar()[1] nicht wieder den Monat, sondern die Woche des betreffenden Jahres zurück. Sorry. Allerdings hat dies keinen Einfluß auf die vorhandenen Fehler.
aaron
User
Beiträge: 92
Registriert: Donnerstag 1. Dezember 2016, 23:10

Ich teste zur Zeit das Script. Ich habe beim Download einiger Symbole folgende Fehlermeldung bekommen: Nach einigem Googlen habe ich gelesen, daß es mit dem Cache auf dem Server zu tun haben könnte. Es gab einen Tipp wie cache = False. Was kann ich tun? Eine komprimierte Datei ist ca. 10 Megabyte groß. Ich wollte 53 Dateien am Stück herunterladen und schon nach der 5 Datei bleibt das Script mit der Fehlermeldung hängen.

Code: Alles auswählen

Traceback (most recent call last):
  File "TickDataCsv27.py", line 81, in <module>
    main()
  File "TickDataCsv27.py", line 76, in main
    fetch_whole_year(symbol, 2015)
  File "TickDataCsv27.py", line 53, in fetch_whole_year
    print_data_length(data)
  File "TickDataCsv27.py", line 28, in print_data_length
    data = f.read()
  File "/usr/lib/python2.7/gzip.py", line 261, in read
    self._read(readsize)
  File "/usr/lib/python2.7/gzip.py", line 320, in _read
    self._add_read_data( uncompress )
  File "/usr/lib/python2.7/gzip.py", line 338, in _add_read_data
    self.extrabuf = self.extrabuf[offset:] + data
MemoryError
Antworten