where in our model of the python standard library should we add urllib and urlopen




كيف أقوم بتنزيل ملف عبر HTTP باستخدام Python؟ (13)

بايثون 3

  • urllib.request.urlopen

    import urllib.request
    response = urllib.request.urlopen('http://www.example.com/')
    html = response.read()
    
  • urllib.request.urlretrieve

    import urllib.request
    urllib.request.urlretrieve('http://www.example.com/songs/mp3.mp3', 'mp3.mp3')
    

بايثون 2

  • urllib2.urlopen (بفضل Corey )

    import urllib2
    response = urllib2.urlopen('http://www.example.com/')
    html = response.read()
    
  • urllib.urlretrieve (بفضل PabloG )

    import urllib
    urllib.urlretrieve('http://www.example.com/songs/mp3.mp3', 'mp3.mp3')
    

لدي أداة صغيرة يمكنني استخدامها لتنزيل ملف MP3 من موقع ويب وفقًا لجدول زمني ثم بناء / تحديث ملف podcast XML الذي قمت بإضافته بوضوح إلى iTunes.

تتم كتابة معالجة النصوص التي تقوم بإنشاء / تحديث ملف XML في Python. يمكنني استخدام wget داخل ملف .bat Windows لتنزيل ملف MP3 الفعلي. كنت أفضل أن يكون مكتوبًا بالكامل في بيثون.

أنا ناضلت على الرغم من العثور على وسيلة لفي الواقع تحميل الملف في بيثون ، وبالتالي لماذا لجأت إلى wget .

لذا ، كيف يمكنني تنزيل الملف باستخدام بايثون؟


urlretrieve و requests.get بسيط ، ولكن الحقيقة لا. لقد جلبت بيانات للمواقع الزوجية ، بما في ذلك النصوص والصور ، وربما يحل هذان العنصران أعلاه معظم المهام. ولكن من أجل حل عالمي أشير إلى استخدام urlopen. نظرًا لتضمينها في مكتبة Python 3 القياسية ، يمكن تشغيل شفرتك على أي جهاز يشغّل Python 3 بدون تثبيت مسبق للموقع - par

import urllib.request
url_request = urllib.request.Request(url, headers=headers)
url_connect = urllib.request.urlopen(url_request)
len_content = url_content.length

#remember to open file in bytes mode
with open(filename, 'wb') as f:
    while True:
        buffer = url_connect.read(buffer_size)
        if not buffer: break

        #an integer value of size of written data
        data_wrote = f.write(buffer)

#you could probably use with-open-as manner
url_connect.close()

توفر هذه الإجابة حلاً لـ HTTP 403 Forbidden عند تنزيل الملف عبر http باستخدام Python. لقد حاولت فقط طلبات ووحدات urllib ، قد توفر الوحدة النمطية الأخرى شيئًا أفضل ، ولكن هذا هو الحل الذي اعتدت على حل معظم المشكلات فيه.


إذا كان لديك wget مثبتًا ، فيمكنك استخدام parallel_sync.

تثبيت النقط parallel_sync

from parallel_sync import wget
urls = ['http://something.png', 'http://somthing.tar.gz', 'http://somthing.zip']
wget.download('/tmp', urls)
# or a single file:
wget.download('/tmp', urls[0], filenames='x.zip', extract=True)

المستند: https://pythonhosted.org/parallel_sync/pages/examples.html

هذا قوي جدا. يمكنه تحميل الملفات بالتوازي ، وإعادة محاولة الفشل ، ويمكنه أيضًا تنزيل الملفات على جهاز بعيد.


إذا كانت السرعة مهمة بالنسبة لك ، فقد قمت بإجراء اختبار أداء صغير للوحدات النمطية urllib و wget ، وفيما يتعلق ب wget حاولت مرة واحدة مع شريط الحالة ومرة ​​واحدة بدون. أخذت ثلاثة ملفات مختلفة بحجم 500 ميغا بايت للاختبار مع (ملفات مختلفة - للتخلص من احتمال وجود بعض التخزين المؤقت تحت غطاء المحرك). اختبارها على آلة ديبيان ، مع python2.

أولاً ، هذه هي النتائج (فهي متشابهة في فترات مختلفة):

$ python wget_test.py 
urlretrive_test : starting
urlretrive_test : 6.56
==============
wget_no_bar_test : starting
wget_no_bar_test : 7.20
==============
wget_with_bar_test : starting
100% [......................................................................] 541335552 / 541335552
wget_with_bar_test : 50.49
==============

الطريقة التي أجريت بها الاختبار هي استخدام ديكور "الملف الشخصي". هذا هو الرمز الكامل:

import wget
import urllib
import time
from functools import wraps

def profile(func):
    @wraps(func)
    def inner(*args):
        print func.__name__, ": starting"
        start = time.time()
        ret = func(*args)
        end = time.time()
        print func.__name__, ": {:.2f}".format(end - start)
        return ret
    return inner

url1 = 'http://host.com/500a.iso'
url2 = 'http://host.com/500b.iso'
url3 = 'http://host.com/500c.iso'

def do_nothing(*args):
    pass

@profile
def urlretrive_test(url):
    return urllib.urlretrieve(url)

@profile
def wget_no_bar_test(url):
    return wget.download(url, out='/tmp/', bar=do_nothing)

@profile
def wget_with_bar_test(url):
    return wget.download(url, out='/tmp/')

urlretrive_test(url1)
print '=============='
time.sleep(1)

wget_no_bar_test(url2)
print '=============='
time.sleep(1)

wget_with_bar_test(url3)
print '=============='
time.sleep(1)

يبدو أن urllib هو الأسرع


رمز المصدر يمكن أن يكون:

import urllib
sock = urllib.urlopen("http://diveintopython.org/")
htmlSource = sock.read()                            
sock.close()                                        
print htmlSource  

طريقة بسيطة ولكن Python 2 & Python 3 تأتي مع six مكتبات:

from six.moves import urllib
urllib.request.urlretrieve("http://www.example.com/songs/mp3.mp3", "mp3.mp3")

في python3 يمكنك استخدام urllib3 و libraires shutil. تنزيلها باستخدام pip أو pip3 (بالاعتماد على ما إذا كان python3 هو الإعداد الافتراضي أم لا)

pip3 install urllib3 shutil

ثم قم بتشغيل هذا الرمز

import urllib.request
import shutil

url = "http://www.somewebsite.com/something.pdf"
output_file = "save_this_name.pdf"
with urllib.request.urlopen(url) as response, open(output_file, 'wb') as out_file:
    shutil.copyfileobj(response, out_file)

لاحظ أنك تقوم بتنزيل urllib3 ولكنك تستخدم urllib في التعليمات البرمجية


في عام 2012 ، استخدم مكتبة طلبات python

>>> import requests
>>> 
>>> url = "http://download.thinkbroadband.com/10MB.zip"
>>> r = requests.get(url)
>>> print len(r.content)
10485760

يمكنك تشغيل pip install requests للحصول عليها.

تحتوي الطلبات على العديد من المزايا على البدائل لأن API أكثر بساطة. هذا صحيح بشكل خاص إذا كان عليك القيام المصادقة. urllib و urllib2 غير بديهية ومؤلمة إلى حد ما في هذه الحالة.

2015/12/30

أعرب الناس عن إعجابهم بشريط التقدم. إنه رائع ، بالتأكيد. هناك العديد من الحلول الجاهزة الآن ، بما في ذلك tqdm :

from tqdm import tqdm
import requests

url = "http://download.thinkbroadband.com/10MB.zip"
response = requests.get(url, stream=True)

with open("10MB", "wb") as handle:
    for data in tqdm(response.iter_content()):
        handle.write(data)

هذا هو الأساس في تنفيذkvance وصفها قبل 30 شهرا.


قد يكون هذا متأخرا بعض الشيء ، لكنني رأيت رمز pabloG ولا يمكن أن يساعد في إضافة os.system ('cls') لجعله يبدو مذهلاً! تحقق من ذلك :

    import urllib2,os

    url = "http://download.thinkbroadband.com/10MB.zip"

    file_name = url.split('/')[-1]
    u = urllib2.urlopen(url)
    f = open(file_name, 'wb')
    meta = u.info()
    file_size = int(meta.getheaders("Content-Length")[0])
    print "Downloading: %s Bytes: %s" % (file_name, file_size)
    os.system('cls')
    file_size_dl = 0
    block_sz = 8192
    while True:
        buffer = u.read(block_sz)
        if not buffer:
            break

        file_size_dl += len(buffer)
        f.write(buffer)
        status = r"%10d  [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
        status = status + chr(8)*(len(status)+1)
        print status,

    f.close()

إذا كنت تعمل في بيئة أخرى غير Windows ، فسيتعين عليك استخدام شيء آخر ثم "cls". في MAC OS X و Linux يجب أن يكون "واضح".


كتب مكتبة wget في بيثون نقية فقط لهذا الغرض. يتم ضخه مع urlretrieve مع هذه الميزات كما في الإصدار 2.0.


نسخة محسنة من شفرة PabloG لـ Python 2/3:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import ( division, absolute_import, print_function, unicode_literals )

import sys, os, tempfile, logging

if sys.version_info >= (3,):
    import urllib.request as urllib2
    import urllib.parse as urlparse
else:
    import urllib2
    import urlparse

def download_file(url, dest=None):
    """ 
    Download and save a file specified by url to dest directory,
    """
    u = urllib2.urlopen(url)

    scheme, netloc, path, query, fragment = urlparse.urlsplit(url)
    filename = os.path.basename(path)
    if not filename:
        filename = 'downloaded.file'
    if dest:
        filename = os.path.join(dest, filename)

    with open(filename, 'wb') as f:
        meta = u.info()
        meta_func = meta.getheaders if hasattr(meta, 'getheaders') else meta.get_all
        meta_length = meta_func("Content-Length")
        file_size = None
        if meta_length:
            file_size = int(meta_length[0])
        print("Downloading: {0} Bytes: {1}".format(url, file_size))

        file_size_dl = 0
        block_sz = 8192
        while True:
            buffer = u.read(block_sz)
            if not buffer:
                break

            file_size_dl += len(buffer)
            f.write(buffer)

            status = "{0:16}".format(file_size_dl)
            if file_size:
                status += "   [{0:6.2f}%]".format(file_size_dl * 100 / file_size)
            status += chr(13)
            print(status, end="")
        print()

    return filename

if __name__ == "__main__":  # Only run if this file is called directly
    print("Testing with 10MB download")
    url = "http://download.thinkbroadband.com/10MB.zip"
    filename = download_file(url)
    print(filename)

واحد آخر ، وذلك باستخدام urlretrieve :

import urllib
urllib.urlretrieve ("http://www.example.com/songs/mp3.mp3", "mp3.mp3")

(استخدم Python 3+ "import urllib.request" و urllib.request.urlretrieve)

بعد واحد آخر ، مع "شريط التقدم"

import urllib2

url = "http://download.thinkbroadband.com/10MB.zip"

file_name = url.split('/')[-1]
u = urllib2.urlopen(url)
f = open(file_name, 'wb')
meta = u.info()
file_size = int(meta.getheaders("Content-Length")[0])
print "Downloading: %s Bytes: %s" % (file_name, file_size)

file_size_dl = 0
block_sz = 8192
while True:
    buffer = u.read(block_sz)
    if not buffer:
        break

    file_size_dl += len(buffer)
    f.write(buffer)
    status = r"%10d  [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
    status = status + chr(8)*(len(status)+1)
    print status,

f.close()

import urllib2
mp3file = urllib2.urlopen("http://www.example.com/songs/mp3.mp3")
with open('test.mp3','wb') as output:
  output.write(mp3file.read())

يقوم wb open('test.mp3','wb') بفتح ملف (ومسح أي ملف موجود) في الوضع الثنائي حتى يمكنك حفظ البيانات به بدلاً من النص فقط.





urllib