Συζήτηση
Γεια χαρά, Επισκέπτης
Όνομα χρήστη: Κωδικός: Να με θυμάσαι

ΘΕΜΑ: Υλοποίηση Προγράμματος τύπου wget.

Υλοποίηση Προγράμματος τύπου wget. 13 Χρόνια 2 Μήνες πριν #1301

  • kamar
  • Το Άβαταρ του/της kamar
  • Αποσυνδεμένος
  • python
  • Δημοσιεύσεις: 409
  • Ληφθείσες Ευχαριστίες 88
Πολλές φορές θα χρειαστεί να κατεβάσουμε κάποιο αρχείο από το διαδίκτυο, από τη γραμμή εντολών. Υπάρχουν κάποια καλά προγράμματα όπως το wget. Εδώ είναι μια εκπαιδευτική υλοποίηση που χρησιμοποιεί τα modyle urllib.request και urllib.parse της Python3.
#!/usr/bin/env python3
#-*-coding: utf-8-*-
# filename: downloadme.py
 
import urllib.request
import urllib.parse
import sys
 
def download_me(the_urls, block_size=8192):
    """Downloads a file from a site.
USAGE: python3 downloadme.py http://1 http://2 ...
Author: Konstas Marmatakis <marmako[at]gmail[dot]com>
License: GNU/GPL v 3.0
 
    """
 
    for the_url in the_urls: ## Αν έχουμε πάνω από μία διευθύνσεις δικτύου
        the_url = urllib.parse.unquote(the_url) ## Σβήνουμε αν υπάρχουν χαρακτήρες '%20f' κλπ.
        print(the_url)
        file_name = the_url.split('/')[-1] # Διαχωρίζουμε το αρχείο από τη διεύθυνση.
        site = urllib.request.urlopen(the_url) # Ανοίγουμε το αρχείο.
        file_size = int(site.getheader("Content-Length")) # Παίρνουμε το μήκος του αρχείου
 
        print("Κατεβάζω: {0} Bytes: {1} KBytes: {2:.2f}".format(file_name,\
                file_size, int(file_size/1024)))
 
        try:
            fh = open(file_name, 'wb') # Ανοίγουμε τοπικά θέση για να γράψουμε.
            megethos_arxeiou_kt = 0 # Αρχικό μέγεθος αρχείου 0 bytes.
 
            while True:
                buffer = site.read(block_size) # Διαβάζουμε 8192 bytes.
                if not buffer: # Αν δεν έχουμε να διαβάσουμε σταματάμε.
                    break
 
                megethos_arxeiou_kt += len(buffer) # Τι έχουμε κατεβάσει.
                fh.write(buffer) # Γράφουμε το αρχείο.
                prcnt = (megethos_arxeiou_kt / file_size) 
 
                katastasi = "{0:>6,d}kb {1:.2%}".format(round(megethos_arxeiou_kt/1024),\
                prcnt)
                sys.stdout.write("\rΚατέβηκαν: " + katastasi)
                sys.stdout.flush()
 
            sys.stdout.write("\n")
 
        finally:
            fh.close()
 
if __name__ == '__main__':
    if len(sys.argv) > 1:
        del sys.argv[0]
        download_me(sys.argv)
    else:
        print("Usage: downloadme.py http://url/to/the/file/file http://url/to/the/file/file2 ...")

Σημείωσεις:
Το πρόγραμμα τρέχει στη γραμμή εντολών και σε windows.
Το πρόγραμμα δέχεται και πολλαπλά url.
Χρησιμοποιείται η urllib.parse.unquote για να αντικατασταθούν οι χαρακτήρες %xx, αν υπάρχουν στο url.
Αν θέλετε να το τρέξετε από το IDLE καλά είναι να αντικατασταθούν τα sys.stdout.write με την print και να αφαιρεθεί το sys.stdout.flush(), για να υπάρξει καλύτερο οπτικό αποτέλεσμα στην ενημερωτική οθόνη του προγράμματος.
Γράφω σε Python 3
Πρέπει να είστε εγγεγραμμένο μέλος του Φόρουμ για να κάνετε μια δημοσίευση.

Απ: Υλοποίηση Προγράμματος τύπου wget. 13 Χρόνια 2 Μήνες πριν #1302

  • pmav99
  • Το Άβαταρ του/της pmav99
  • Αποσυνδεμένος
  • Author
  • Δημοσιεύσεις: 684
  • Ληφθείσες Ευχαριστίες 111
Για να εμφανίζεται το μήνυμα βοήθειας, αλλά και να μπορούν να επεκταθούν οι δυνατότητες του script με σχετική ευκολία, ίσως είναι καλύτερα να χρησιμοποιηθεί το πακέτο argparse.
import argparse
 
if __name__ == '__main__':
    # Create the command line parser
    parser = argparse.ArgumentParser(description = 'A wget-like utility made in python.')
    parser.add_argument('urls', metavar = 'url', type = str, nargs = '+',
                        help = 'the list of urls to be downloaded')
 
    # Parse the command line arguments
    args = parser.parse_args()
 
    download_me(args.urls)

Δε θα έπρεπε να γίνεται έλεγχος με κάποιο τρόπο ότι η λίστα των urls που δόθηκε είναι έγκυρη? Ότι αρχίζει δηλαδή με "http" ή "ftp" κτλ. Υπάρχει τρόπος στη standard library να γίνεται αυτός ο έλεγχος ή απλά πρέπει να ελεγχθεί το string?
Πρέπει να είστε εγγεγραμμένο μέλος του Φόρουμ για να κάνετε μια δημοσίευση.

Απ: Υλοποίηση Προγράμματος τύπου wget. 13 Χρόνια 2 Μήνες πριν #1303

  • kamar
  • Το Άβαταρ του/της kamar
  • Αποσυνδεμένος
  • python
  • Δημοσιεύσεις: 409
  • Ληφθείσες Ευχαριστίες 88
import argparse
Αυτόματα το script δεν «στέκει» μόνο του, καθώς η βιβλιοθήκη είναι εξωτερική και όχι ενσωματωμένη.
Όμως σαν ιδέα είναι καλή και όποιος θέλει μπορεί να την υλοποιήσει.
Υπάρχει τρόπος στη standard library να γίνεται αυτός ο έλεγχος ή απλά πρέπει να ελεγχθεί το string.
Αρχικά θα πρέπει να ελεγχθεί το string. Μπορούμε όμως να τσεκάρουμε τους response codes με το module http.server (200=ok). Επίσης μπορεί να προκύψει πρόβλημα αν το site είναι ftp και ζητήσει username και password, οπότε θα χρησιμοποιηθεί το module ftplib.
Γράφω σε Python 3
Πρέπει να είστε εγγεγραμμένο μέλος του Φόρουμ για να κάνετε μια δημοσίευση.

Απ: Υλοποίηση Προγράμματος τύπου wget. 13 Χρόνια 2 Μήνες πριν #1304

  • pmav99
  • Το Άβαταρ του/της pmav99
  • Αποσυνδεμένος
  • Author
  • Δημοσιεύσεις: 684
  • Ληφθείσες Ευχαριστίες 111
kamar έγραψε:
import argparse
Αυτόματα το script δεν «στέκει» μόνο του, καθώς η βιβλιοθήκη είναι εξωτερική και όχι ενσωματωμένη.
Όμως σαν ιδέα είναι καλή και όποιος θέλει μπορεί να την υλοποιήσει.
Μα h argparse είναι τμήμα της standard library. Υπάρχει και στην έκδοση 2 και στην έκδοση 3
Πρέπει να είστε εγγεγραμμένο μέλος του Φόρουμ για να κάνετε μια δημοσίευση.
Οι ακόλουθοι χρήστες είπαν "Σε Ευχαριστώ": kamar

Απ: Υλοποίηση Προγράμματος τύπου wget. 13 Χρόνια 2 Μήνες πριν #1305

  • kamar
  • Το Άβαταρ του/της kamar
  • Αποσυνδεμένος
  • python
  • Δημοσιεύσεις: 409
  • Ληφθείσες Ευχαριστίες 88
Python 2.6.6 (r266:84292, Sep 15 2010, 16:22:56) 
[GCC 4.4.5] on linux2
Type "copyright", "credits" or "license()" for more information.
 
    ****************************************************************
    Personal firewall software may warn about the connection IDLE
    makes to its subprocess using this computer's internal loopback
    interface.  This connection is not visible on any external
    interface and no data is sent to or received from the Internet.
    ****************************************************************
 
IDLE 2.6.6      
>>> import argparse
>>> 
Python 3.1.2 (release31-maint, Sep 17 2010, 20:27:33) 
[GCC 4.4.5] on linux2
Type "copyright", "credits" or "license()" for more information.
>>> import argparse
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    import argparse
ImportError: No module named argparse
>>>
:(

Κάτι μου ξέφυγε. Ευχαριστώ.

EDIT
import optparse
για κώδικα σε 3.1.x
Γράφω σε Python 3
Τελευταία διόρθωση: 13 Χρόνια 2 Μήνες πριν από kamar. Αιτία: Προσθήκη μικρής διόρθωσης
Πρέπει να είστε εγγεγραμμένο μέλος του Φόρουμ για να κάνετε μια δημοσίευση.

Linux Distros 13 Χρόνια 2 Μήνες πριν #1306

  • pmav99
  • Το Άβαταρ του/της pmav99
  • Αποσυνδεμένος
  • Author
  • Δημοσιεύσεις: 684
  • Ληφθείσες Ευχαριστίες 111
ναι έχεις δίκιο στην 3.1 δεν υπάρχει η argparse...

Εσύ είσαι με Ubuntu και δεν έχει περάσει στα repo ακόμα η 3.2 σωστά?

Με optparse δεν αλλάζουν και πολλά. Ιδίως μάλιστα για ένα τόσο απλό script. Για την ιστορία ΕΔΩ γίνεται σύγκριση τους. Έχω την αίσθηση ότι στο μέλλον το argparse θα είναι το στάνταρ.
Πρέπει να είστε εγγεγραμμένο μέλος του Φόρουμ για να κάνετε μια δημοσίευση.

Απ: Υλοποίηση Προγράμματος τύπου wget. 13 Χρόνια 2 Μήνες πριν #1307

  • kamar
  • Το Άβαταρ του/της kamar
  • Αποσυνδεμένος
  • python
  • Δημοσιεύσεις: 409
  • Ληφθείσες Ευχαριστίες 88
Ναι. Και η 3.1 είναι minimal υλοποίηση.
Γράφω σε Python 3
Πρέπει να είστε εγγεγραμμένο μέλος του Φόρουμ για να κάνετε μια δημοσίευση.
Συντονιστές: pmav99
Χρόνος δημιουργίας σελίδας: 0.312 δευτερόλεπτα

Μοιράσου το!

Powered by CoalaWeb

Λίστα Ταχυδρομείου