Python: загрузка большого файла по локальному пути и установка пользовательских заголовков http - PullRequest
5 голосов
/ 08 апреля 2009

Я ищу, чтобы загрузить файл с URL-адреса http в локальный файл. Файл достаточно велик, поэтому я хочу загрузить его и сохранить его, а не read() и write() весь файл как одну гигантскую строку.

Интерфейс urllib.urlretrieve по сути то, что я хочу. Однако я не вижу способа установить заголовки запросов при загрузке через urllib.urlretrieve, что мне нужно сделать.

Если я использую urllib2, я могу установить заголовки запроса через его Request объект. Однако в urllib2 я не вижу API для загрузки файла непосредственно по пути на диске, например urlretrieve. Похоже, что вместо этого мне придется использовать цикл для перебора возвращаемых данных в виде фрагментов, записи их в файл самостоятельно и проверки, когда мы закончим.

Как лучше всего построить функцию, которая работает как urllib.urlretrieve, но позволяет передавать заголовки запросов?

Ответы [ 2 ]

3 голосов
/ 08 января 2010

Чем вредно написание собственной функции с использованием urllib2?

import os
import sys
import urllib2

def urlretrieve(urlfile, fpath):
    chunk = 4096
    f = open(fpath, "w")
    while 1:
        data = urlfile.read(chunk)
        if not data:
            print "done."
            break
        f.write(data)
        print "Read %s bytes"%len(data)

и использование объекта запроса для установки заголовков

request = urllib2.Request("http://www.google.com")
request.add_header('User-agent', 'Chrome XXX')
urlretrieve(urllib2.urlopen(request), "/tmp/del.html")
2 голосов
/ 08 апреля 2009

Если вы хотите использовать urllib и urlretrieve, создайте подкласс urllib.URLopener и используйте его метод addheader() для настройки заголовков (т.е.: addheader('Accept', 'sound/basic'), который я извлекаю из строки документации для urllib.addheader).

Чтобы установить URLopener для использования urllib, см. Пример в разделе urllib._urlopener документации (обратите внимание на подчеркивание):

import urllib

class MyURLopener(urllib.URLopener):
    pass # your override here, perhaps to __init__

urllib._urlopener = MyURLopener

Однако, вам будет приятно услышать ваш комментарий к комментариям к вопросу, чтение пустой строки из read() действительно является сигналом к ​​остановке. Вот как urlretrieve обрабатывает, например, когда остановиться. TCP / IP и сокеты абстрагируют процесс чтения, блокируя ожидание дополнительных данных, если соединение на другом конце не является EOF и не закрыто, и в этом случае read () из соединения возвращает пустую строку. Пустая строка означает, что данные не поступают ... вам не нужно беспокоиться об упорядоченной сборке пакетов, поскольку все это было обработано за вас. Если вы беспокоитесь за urllib2, я думаю, вы можете безопасно использовать его.

...