Làm cách nào để tải xuống tệp qua HTTP bằng Python?


875

Tôi có một tiện ích nhỏ mà tôi sử dụng để tải xuống tệp MP3 từ một trang web theo lịch trình và sau đó xây dựng / cập nhật tệp podcast podcast mà tôi đã thêm vào iTunes.

Việc xử lý văn bản tạo / cập nhật tệp XML được viết bằng Python. Tuy nhiên, tôi sử dụng wget bên trong .battệp Windows để tải xuống tệp MP3 thực tế. Tôi muốn có toàn bộ tiện ích được viết bằng Python.

Tôi đã vật lộn để tìm cách tải xuống tệp bằng Python, vì vậy tôi đã sử dụng nó wget.

Vậy, làm cách nào để tải xuống tệp bằng Python?



Nhiều câu trả lời dưới đây không phải là một sự thay thế thỏa đáng cho wget. Trong số những thứ khác, wget(1) bảo tồn dấu thời gian (2) tự động xác định tên tệp từ url, nối thêm .1(v.v.) nếu tệp đã tồn tại (3) có nhiều tùy chọn khác, một số trong đó bạn có thể đặt vào .wgetrc. Nếu bạn muốn bất kỳ thứ nào trong số đó, bạn phải tự thực hiện chúng trong Python, nhưng đơn giản hơn là chỉ cần gọi wgettừ Python.
ShreevatsaR

2
Giải pháp ngắn gọn cho Python 3:import urllib.request; s = urllib.request.urlopen('http://example.com/').read().decode()
Basj

Câu trả lời:


450

Trong Python 2, sử dụng urllib2 đi kèm với thư viện chuẩn.

import urllib2
response = urllib2.urlopen('http://www.example.com/')
html = response.read()

Đây là cách cơ bản nhất để sử dụng thư viện, trừ mọi xử lý lỗi. Bạn cũng có thể làm những thứ phức tạp hơn như thay đổi tiêu đề. Các tài liệu có thể được tìm thấy ở đây.


11
Điều này sẽ không hoạt động nếu có khoảng trắng trong url bạn cung cấp. Trong trường hợp đó, bạn sẽ cần phân tích url và urlencode đường dẫn.
Jason Sundram

91
Đây là giải pháp Python 3: stackoverflow.com/questions/7243750/ từ
tommy.carstensen

6
Chỉ để tham khảo. Cách để urlencode đường dẫn làurllib2.quote
André Puel

11
@JasonSundram: Nếu có khoảng trắng trong đó, thì đó không phải là URI.
Zaz

1
Điều này không hoạt động trên các cửa sổ với các tập tin lớn hơn. Bạn cần phải đọc tất cả các khối!
Avia

1115

Thêm một, sử dụng urlretrieve:

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

(đối với Python 3+ sử dụng import urllib.requesturllib.request.urlretrieve)

Một số khác, với một "thanh tiến trình"

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()

1
Thật kỳ lạ, điều này làm việc cho tôi trên Windows khi phương pháp urllib2 sẽ không. Tuy nhiên, phương pháp urllib2 hoạt động trên Mac.
InFreefall

6
Lỗi: file_size_dl + = block_sz nên là + = len (bộ đệm) vì lần đọc cuối cùng thường không phải là một block_sz đầy đủ. Ngoài ra trên windows bạn cần mở tệp đầu ra là "wb" nếu đó không phải là tệp văn bản.
Cà tím Jeff

1
Tôi cũng vậy, urllib và urllib2 không hoạt động nhưng urlretret hoạt động tốt, đã bị thất vọng - cảm ơn :)
funk-shun

2
Bao bọc toàn bộ (ngoại trừ định nghĩa của file_name) if not os.path.isfile(file_name):để tránh ghi đè các podcast! hữu ích khi chạy nó dưới dạng cronjob với các url được tìm thấy trong tệp .html
Sriram Murali

2
@PabloG bây giờ chỉ còn hơn 31 phiếu;) Dù sao, thanh trạng thái rất thú vị nên tôi sẽ +1
Cinder

340

Trong năm 2012, sử dụng thư viện yêu cầu python

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

Bạn có thể chạy pip install requestsđể có được nó.

Yêu cầu có nhiều ưu điểm so với các lựa chọn thay thế vì API đơn giản hơn nhiều. Điều này đặc biệt đúng nếu bạn phải xác thực. urllib và urllib2 khá không trực quan và đau đớn trong trường hợp này.


2015-12-30

Mọi người đã bày tỏ sự ngưỡng mộ đối với thanh tiến độ. Thật tuyệt, chắc chắn. Hiện tại có một số giải pháp sẵn có, bao gồm 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)

Đây thực chất là việc thực hiện @kvance được mô tả 30 tháng trước.


Làm cách nào để lưu hoặc giải nén nếu tệp zip thực sự là một thư mục chứa nhiều tệp trong đó?
Abdul Muneer

6
Làm thế nào để điều này xử lý các tệp lớn, mọi thứ được lưu trữ vào bộ nhớ hoặc điều này có thể được ghi vào một tệp mà không yêu cầu bộ nhớ lớn?
bibstha

8
Có thể truyền phát các tệp lớn bằng cách đặt stream = True trong yêu cầu. Sau đó, bạn có thể gọi iter_content () trên phản hồi để đọc một đoạn dữ liệu tại một thời điểm.
kvance

7
Tại sao một thư viện url cần phải có một cơ sở giải nén tập tin? Đọc tệp từ url, lưu nó và sau đó giải nén nó theo bất cứ cách nào nổi thuyền của bạn. Ngoài ra, một tệp zip không phải là một 'thư mục' như nó hiển thị trong các cửa sổ, Đó là một tệp.
Harel

2
@Ali :: r.textDành cho nội dung văn bản hoặc unicode. Trả lại dưới dạng unicode. r.content: Đối với nội dung nhị phân. Trả về dưới dạng byte. Đọc về nó ở đây: docs.python-requests.org/en/latest/user/quickstart
hughdbrown

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

Các wbtrong open('test.mp3','wb')mở một tập tin (và xóa bất kỳ tập tin hiện có) trong chế độ nhị phân, do đó bạn có thể lưu dữ liệu với nó thay vì chỉ văn bản.


30
Nhược điểm của giải pháp này là, toàn bộ tệp được tải vào ram trước khi lưu vào đĩa, chỉ cần lưu ý nếu sử dụng tệp này cho các tệp lớn trên hệ thống nhỏ như bộ định tuyến có ram giới hạn.
tripplet

2
@tripplet vậy chúng ta sẽ sửa nó như thế nào?
Lucas Henrique

11
Để tránh đọc toàn bộ tệp vào bộ nhớ, hãy thử chuyển một đối số đến file.readđó là số byte cần đọc. Xem: gist.github.com/hughdbrown/c145b8385a2afa6570e2
hughdbrown

@hughdbrown Tôi thấy tập lệnh của bạn hữu ích, nhưng có một câu hỏi: tôi có thể sử dụng tệp để xử lý hậu kỳ không? giả sử tôi tải xuống tệp jpg mà tôi muốn xử lý với OpenCV, tôi có thể sử dụng biến 'dữ liệu' để tiếp tục hoạt động không? hoặc tôi phải đọc lại từ tệp đã tải xuống?
Rodrigo E. Principe

5
Sử dụng shutil.copyfileobj(mp3file, output)thay thế.
Aurélien Ooms

129

Con trăn 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')

    Lưu ý: Theo tài liệu, urllib.request.urlretrievelà "giao diện cũ" và "có thể bị phản đối trong tương lai" (cảm ơn gerrit )

Con trăn 2

  • urllib2.urlopen(cảm ơn Corey )

    import urllib2
    response = urllib2.urlopen('http://www.example.com/')
    html = response.read()
  • urllib.urlretrieve(cảm ơn PabloG )

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

2
Nó chắc chắn đã mất một lúc, nhưng ở đó, cuối cùng là api đơn giản mà tôi mong đợi từ một con trăn stdlib :)
ThorSummoner

Câu trả lời rất tốt đẹp cho python3, cũng thấy docs.python.org/3/library/...
Edouard Thiel

@EdouardThiel Nếu bạn nhấp vào urllib.request.urlretrievephía trên, nó sẽ đưa bạn đến liên kết chính xác đó. Chúc mừng!
bmaupin

2
urllib.request.urlretrieveđược ghi nhận là "giao diện cũ" và "có thể bị phản đối trong tương lai".
gerrit

@gerrit Mình thêm ghi chú, cảm ơn vì đã ngẩng cao đầu!
bmaupin


21

Phiên bản cải tiến của mã PabloG cho 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)

Tôi sẽ xóa dấu ngoặc đơn từ dòng đầu tiên, vì nó không phải là tính năng quá cũ.
Arpad Horvath

21

Cách đơn giản nhưng Python 2 & Python 3tương thích đi kèm với sixthư viện:

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

1
Đây là cách tốt nhất để làm điều đó cho khả năng tương thích 2 + 3.
Fush

21
import os,requests
def download(url):
    get_response = requests.get(url,stream=True)
    file_name  = url.split("/")[-1]
    with open(file_name, 'wb') as f:
        for chunk in get_response.iter_content(chunk_size=1024):
            if chunk: # filter out keep-alive new chunks
                f.write(chunk)


download("https://example.com/example.jpg")

17

Đã viết thư viện wget trong Python thuần túy chỉ cho mục đích này. Nó được bơm lên urlretrievevới các tính năng này như phiên bản 2.0.


3
Không có tùy chọn để lưu với tên tệp tùy chỉnh?
Alex

2
@Alex đã thêm -o tùy chọn FILENAME cho phiên bản 2.1
anatoly techtonik

Thanh tiến trình không xuất hiện khi tôi sử dụng mô-đun này dưới Cygwin.
Joe Coder

Bạn nên thay đổi từ -ođể -Otránh nhầm lẫn, vì nó nằm trong GNU wget. Hoặc ít nhất cả hai tùy chọn phải hợp lệ.
erik

@eric Tôi không chắc chắn rằng tôi muốn wget.pythay thế tại chỗ cho thật wget. Các -ohành vi đã khác nhau - nó tương thích với curlcách này. Một lưu ý trong tài liệu sẽ giúp giải quyết vấn đề? Hoặc đó là tính năng cần thiết cho một tiện ích có tên tương thích với dòng lệnh?
anatoly techtonik

16

Sau đây là các cuộc gọi được sử dụng phổ biến nhất để tải xuống tệp trong python:

  1. urllib.urlretrieve ('url_to_file', file_name)

  2. urllib2.urlopen('url_to_file')

  3. requests.get(url)

  4. wget.download('url', file_name)

Lưu ý: urlopenurlretrieveđược phát hiện là hoạt động tương đối tệ khi tải xuống các tệp lớn (kích thước> 500 MB). requests.getlưu trữ tệp trong bộ nhớ cho đến khi tải xuống hoàn tất.


14

Tôi đồng ý với Corey, urllib2 hoàn chỉnh hơn urllib và có thể là mô-đun được sử dụng nếu bạn muốn làm những việc phức tạp hơn, nhưng để làm cho câu trả lời hoàn chỉnh hơn, urllib là mô-đun đơn giản hơn nếu bạn chỉ muốn những điều cơ bản:

import urllib
response = urllib.urlopen('http://www.example.com/sound.mp3')
mp3 = response.read()

Sẽ làm việc tốt. Hoặc, nếu bạn không muốn đối phó với đối tượng "phản hồi", bạn có thể gọi trực tiếp read () :

import urllib
mp3 = urllib.urlopen('http://www.example.com/sound.mp3').read()

10

Trong python3, bạn có thể sử dụng urllib3 và tắt các libraires. Tải xuống chúng bằng cách sử dụng pip hoặc pip3 (Tùy thuộc vào việc python3 có mặc định hay không)

pip3 install urllib3 shutil

Sau đó chạy mã này

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)

Lưu ý rằng bạn tải xuống urllib3nhưng sử dụng urllibtrong mã


7

Bạn cũng có thể nhận được phản hồi tiến trình với urlretrease:

def report(blocknr, blocksize, size):
    current = blocknr*blocksize
    sys.stdout.write("\r{0:.2f}%".format(100.0*current/size))

def downloadFile(url):
    print "\n",url
    fname = url.split('/')[-1]
    print fname
    urllib.urlretrieve(url, fname, report)

7

Nếu bạn đã cài đặt wget, bạn có thể sử dụngallel_sync.

Pip cài đặtallel_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)

Bác sĩ: https://pythonhosted.org/abul_sync/pages/examples.html

Điều này là khá mạnh mẽ. Nó có thể tải xuống các tệp song song, thử lại khi thất bại và thậm chí có thể tải xuống các tệp trên một máy từ xa.


Lưu ý rằng đây chỉ dành cho Linux
jjj

4

Nếu tốc độ quan trọng với bạn, tôi đã thực hiện một bài kiểm tra hiệu suất nhỏ cho các mô-đun urllibwget, và liên quan đếnwget tôi đã cố gắng một lần với thanh trạng thái và một lần không. Tôi đã lấy ba tệp 500 MB khác nhau để kiểm tra (các tệp khác nhau - để loại trừ khả năng có một số bộ đệm đang diễn ra dưới mui xe). Đã thử nghiệm trên máy debian, với python2.

Đầu tiên, đây là các kết quả (chúng tương tự nhau trong các lần chạy khác nhau):

$ 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
==============

Cách tôi thực hiện kiểm tra là sử dụng trang trí "hồ sơ". Đây là mã đầy đủ:

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 dường như là nhanh nhất


Phải có một cái gì đó hoàn toàn khủng khiếp đang diễn ra dưới mui xe để làm cho thanh tăng thời gian rất nhiều.
Alistair Carscadden

4

Chỉ để hoàn thiện, bạn cũng có thể gọi bất kỳ chương trình nào để truy xuất tệp bằng subprocessgói. Các chương trình dành riêng để truy xuất tệp mạnh hơn các hàm Python như urlretrieve. Ví dụ: wgetcó thể tải xuống các thư mục đệ quy ( -R), có thể xử lý FTP, chuyển hướng, proxy HTTP, có thể tránh tải xuống lại các tệp hiện có ( -nc) và aria2có thể thực hiện tải xuống đa kết nối có khả năng tăng tốc độ tải xuống của bạn.

import subprocess
subprocess.check_output(['wget', '-O', 'example_output_file.html', 'https://example.com'])

Trong Jupyter Notebook, người ta cũng có thể gọi các chương trình trực tiếp bằng !cú pháp:

!wget -O example_output_file.html https://example.com

3

Mã nguồn có thể là:

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

3

Bạn có thể sử dụng PycURL trên Python 2 và 3.

import pycurl

FILE_DEST = 'pycurl.html'
FILE_SRC = 'http://pycurl.io/'

with open(FILE_DEST, 'wb') as f:
    c = pycurl.Curl()
    c.setopt(c.URL, FILE_SRC)
    c.setopt(c.WRITEDATA, f)
    c.perform()
    c.close()

2

Tôi đã viết như sau, hoạt động trong vanilla Python 2 hoặc Python 3.


import sys
try:
    import urllib.request
    python3 = True
except ImportError:
    import urllib2
    python3 = False


def progress_callback_simple(downloaded,total):
    sys.stdout.write(
        "\r" +
        (len(str(total))-len(str(downloaded)))*" " + str(downloaded) + "/%d"%total +
        " [%3.2f%%]"%(100.0*float(downloaded)/float(total))
    )
    sys.stdout.flush()

def download(srcurl, dstfilepath, progress_callback=None, block_size=8192):
    def _download_helper(response, out_file, file_size):
        if progress_callback!=None: progress_callback(0,file_size)
        if block_size == None:
            buffer = response.read()
            out_file.write(buffer)

            if progress_callback!=None: progress_callback(file_size,file_size)
        else:
            file_size_dl = 0
            while True:
                buffer = response.read(block_size)
                if not buffer: break

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

                if progress_callback!=None: progress_callback(file_size_dl,file_size)
    with open(dstfilepath,"wb") as out_file:
        if python3:
            with urllib.request.urlopen(srcurl) as response:
                file_size = int(response.getheader("Content-Length"))
                _download_helper(response,out_file,file_size)
        else:
            response = urllib2.urlopen(srcurl)
            meta = response.info()
            file_size = int(meta.getheaders("Content-Length")[0])
            _download_helper(response,out_file,file_size)

import traceback
try:
    download(
        "https://geometrian.com/data/programming/projects/glLib/glLib%20Reloaded%200.5.9/0.5.9.zip",
        "output.zip",
        progress_callback_simple
    )
except:
    traceback.print_exc()
    input()

Ghi chú:

  • Hỗ trợ gọi lại "thanh tiến trình".
  • Tải xuống là bản thử nghiệm 4 MB .zip từ trang web của tôi.

hoạt động tuyệt vời, chạy nó thông qua jupyter có những gì tôi muốn :-)
Samir Ouldsaadi

1

Điều này có thể hơi muộn, nhưng tôi đã thấy mã của pabloG và không thể giúp thêm os.system ('cls') để làm cho nó trông TUYỆT VỜI! Kiểm tra xem nó:

    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()

Nếu chạy trong một môi trường khác ngoài Windows, bạn sẽ phải sử dụng một cái gì đó khác sau đó 'cls'. Trong MAC OS X và Linux, nó phải 'rõ ràng'.


3
clskhông làm bất cứ điều gì trên OS X của tôi hoặc trên máy chủ Ubuntu của tôi. Một số làm rõ có thể là tốt.
kqw

Tôi nghĩ bạn nên sử dụng clearcho linux, hoặc thậm chí tốt hơn thay thế dòng in thay vì xóa toàn bộ đầu ra dòng lệnh.
Arijoon

4
câu trả lời này chỉ sao chép một câu trả lời khác và thêm một cuộc gọi đến một hàm không dùng nữa ( os.system()) để khởi chạy một quy trình con để xóa màn hình bằng cách sử dụng một lệnh cụ thể của nền tảng ( cls). Làm thế nào điều này có bất kỳ upvote ?? IMHO hoàn toàn vô giá trị "trả lời".
Corey Goldberg

1

urlretrieve và request.get rất đơn giản, tuy nhiên thực tế thì không. Tôi đã tìm nạp dữ liệu cho các trang web đôi, bao gồm văn bản và hình ảnh, hai trang trên có thể giải quyết hầu hết các tác vụ. nhưng đối với một giải pháp phổ quát hơn, tôi đề nghị sử dụng urlopen. Vì nó được bao gồm trong thư viện chuẩn Python 3, mã của bạn có thể chạy trên bất kỳ máy nào chạy Python 3 mà không cần cài đặt trước gói trang web

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

#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()

Câu trả lời này cung cấp giải pháp cho HTTP 403 Bị cấm khi tải xuống tệp qua http bằng Python. Tôi đã thử chỉ yêu cầu và các mô-đun urllib, mô-đun khác có thể cung cấp một cái gì đó tốt hơn, nhưng đây là mô-đun tôi đã sử dụng để giải quyết hầu hết các vấn đề.


0

Câu trả lời muộn, nhưng đối với python>=3.6bạn có thể sử dụng:

import dload
dload.save(url)

Cài đặt dloadvới:

pip3 install dload

0

Tôi muốn tải xuống tất cả các tập tin từ một trang web. Tôi đã thử wgetnhưng không thành công nên tôi quyết định chọn tuyến Python và tôi đã tìm thấy chủ đề này.

Sau khi đọc nó, tôi đã tạo ra một ứng dụng dòng lệnh nhỏ soupget, mở rộng các câu trả lời xuất sắc của PabloGStan và thêm một số tùy chọn hữu ích.

Nó sử dụng BeatiouslySoup để thu thập tất cả các URL của trang và sau đó tải xuống các URL có (các) tiện ích mở rộng mong muốn. Cuối cùng, nó có thể tải xuống nhiều tệp song song.

Đây là:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import (division, absolute_import, print_function, unicode_literals)
import sys, os, argparse
from bs4 import BeautifulSoup

# --- insert Stan's script here ---
# if sys.version_info >= (3,): 
#...
#...
# def download_file(url, dest=None): 
#...
#...

# --- new stuff ---
def collect_all_url(page_url, extensions):
    """
    Recovers all links in page_url checking for all the desired extensions
    """
    conn = urllib2.urlopen(page_url)
    html = conn.read()
    soup = BeautifulSoup(html, 'lxml')
    links = soup.find_all('a')

    results = []    
    for tag in links:
        link = tag.get('href', None)
        if link is not None: 
            for e in extensions:
                if e in link:
                    # Fallback for badly defined links
                    # checks for missing scheme or netloc
                    if bool(urlparse.urlparse(link).scheme) and bool(urlparse.urlparse(link).netloc):
                        results.append(link)
                    else:
                        new_url=urlparse.urljoin(page_url,link)                        
                        results.append(new_url)
    return results

if __name__ == "__main__":  # Only run if this file is called directly
    # Command line arguments
    parser = argparse.ArgumentParser(
        description='Download all files from a webpage.')
    parser.add_argument(
        '-u', '--url', 
        help='Page url to request')
    parser.add_argument(
        '-e', '--ext', 
        nargs='+',
        help='Extension(s) to find')    
    parser.add_argument(
        '-d', '--dest', 
        default=None,
        help='Destination where to save the files')
    parser.add_argument(
        '-p', '--par', 
        action='store_true', default=False, 
        help="Turns on parallel download")
    args = parser.parse_args()

    # Recover files to download
    all_links = collect_all_url(args.url, args.ext)

    # Download
    if not args.par:
        for l in all_links:
            try:
                filename = download_file(l, args.dest)
                print(l)
            except Exception as e:
                print("Error while downloading: {}".format(e))
    else:
        from multiprocessing.pool import ThreadPool
        results = ThreadPool(10).imap_unordered(
            lambda x: download_file(x, args.dest), all_links)
        for p in results:
            print(p)

Một ví dụ về cách sử dụng của nó là:

python3 soupget.py -p -e <list of extensions> -d <destination_folder> -u <target_webpage>

Và một ví dụ thực tế nếu bạn muốn thấy nó hoạt động:

python3 soupget.py -p -e .xlsx .pdf .csv -u https://healthdata.gov/dataset/chemicals-cosmetics
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.