2013-11-28 4 views
0

Я пишу сценарий для DL всей коллекции подкастов BBC из разных шоу-хостов. В моем скрипте используются BS4, Mechanize и wget.Лучший способ проверить, доступен ли файл по URL-адресу?

Я хотел бы знать, как я могу проверить, дает ли запрос URL-адреса код ответа «404» из сервера. Я написал ниже функцию:

def getResponseCode(br, url): 
    print("Opening: " + url) 
    try: 
     response = br.open(url) 
     print("Response code: " + str(response.code)) 
     return True 
    except (mechanize.HTTPError, mechanize.URLError) as e: 
     if isinstance(e,mechanize.HTTPError): 
      print("Mechanize error: " + str(e.code)) 
     else: 
      print("Mechanize error: " + str(e.reason.args)) 
     return False 

я прохожу в него моих Browser() объекта и строки URL. Он возвращает либо True, либо False в зависимости от того, является ли ответ «404» или «200» (на самом деле, «Механизмы» и «Исключение», если это что-то иное, чем «200», следовательно, обработка Исключения).

В main() Я в основном перебираю эту функцию, передавая несколько URL-адресов из списка URL-адресов, которые я очистил с помощью BS4. Когда функция возвращает True, я перехожу к загрузке MP3 с помощью wget.

Однако. Моя проблема:

  • URL-адрес является прямым путем к Подкаст MP3-файлам на удаленном сервере и я заметил, что когда URL доступен, br.open(<URL>) будет висеть. Я подозреваю, что это потому, что Mechanize - кэширование/загрузка фактических данных с сервера. Я не хочу , потому что я просто хочу вернуть True, если код ответа '200'. Как я могу не кэшировать/DL и просто проверить код ответа?

Я попытался с помощью br.open_novisit(url, data=None) однако похмелья все еще сохраняется ...

+0

Почему вы используете Механизатор? Вы пытаетесь имитировать фактический браузер? Если да, то почему? Между тем, почему вы пытаетесь загрузить файл, чтобы увидеть, может ли wget его загрузить, а не просто загрузить? И почему вы используете wget? – abarnert

+0

«Почему вы используете Механизатор?» Я был в предположении, что Mechanize предоставил способ захватить HTML-данные для обработки BeautifulSoup4, то есть response = br.open (url), soup = response.read(), прежде чем использовать метод soup.findAll(), чтобы вернуть все искомые элементы. .. «Вы пытаетесь имитировать фактический браузер?» Нет. «Почему вы пытаетесь загрузить файл, чтобы увидеть, может ли wget его загрузить?» Я не пытаюсь DL файл, а затем wget DL это. Ну, не в последнюю очередь то, что я намеревался в любом случае. Я новичок. Если есть лучший способ сделать это, я с радостью просмотрю ваше предложение/код. –

+0

Механизируйте попытки имитировать браузер. Он может захватывать HTML-данные, но есть намного более простые способы сделать это, не используя такой сверхпрочный инструмент. Кроме того, если вы не пытаетесь DL-файл, а затем имеете wget DL, что вы пытаетесь сделать? По какой-то причине вам нужен wget? Если вы уже знаете, как получить данные, почему бы просто не сохранить данные в файл? – abarnert

ответ

1

Я не думаю, что есть хороший способ получить Mechanize делать то, что вы хотите. Весь смысл Mechanize заключается в том, что он пытается имитировать браузер, посещающий URL-адрес, и браузер, посещающий URL-адрес, загружает страницу. Если вы не хотите этого делать, не используйте для этого API.

Помимо этого, независимо от того, какой API вы используете, отправив запрос на URL-адрес GET, вы просите сервер отправить вам весь ответ. Зачем это просто повесить на него как можно скорее? Используйте запрос HEAD, чтобы спросить у сервера, доступен ли он. (Иногда серверы будут не HEAD вещи, даже если они должны, так что вам придется падать обратно GET Но пересечь этот мост, если вы придете к нему.).

Например:

req = urllib.request.Request(url, method='HEAD') 
resp = urllib.request.urlopen(req) 
return 200 <= resp.code < 300 

Но возникает вопрос:

Когда функция возвращает Правда, я правильно загрузить MP3 с Wget.

Почему? Почему бы просто не использовать wget в первую очередь? Если URL-адрес является готовым, он получит URL-адрес; если нет, это даст вам ошибку - так же легко, как и Mechanize. И это позволяет избежать попадания в каждый URL дважды.

В этом случае попробуйте сценарий wget, вместо использования встроенной поддержки в stdlib или стороннем модуле, таком как requests?


Если вы просто ищете способ распараллелить вещи, которые легко сделать в Python:

def is_good_url(url): 
    req = urllib.request.Request(url, method='HEAD') 
    resp = urllib.request.urlopen(req) 
    return url, 200 <= resp.code < 300 

with futures.ThreadPoolExecutor(max_workers=8) as executor: 
    fs = [executor.submit(is_good_url, url) for url in urls] 
    results = (f.result() for f in futures.as_completed(fs)) 
    good_urls = [url for (url, good) in results if good] 

И изменить это на самом деле загрузить действительные URL, вместо того, чтобы просто делать заметки из которых они действительны, просто измените функцию задачи на то, что извлекает и сохраняет данные из GET вместо того, чтобы делать HEAD. ThreadPoolExecutor Example в документах делает почти то, что вы хотите.

Смежные вопросы