Использование Python для загрузки документа, на который явно не ссылается URL-адрес

Я написал поисковый робот на Python 2.6 с использованием Bing API, который ищет определенные документы, а затем загружает их для последующей классификации. Я использовал строковые методы и urllib.urlretrieve() для загрузки результатов, URL-адрес которых заканчивается на .pdf, .ps и т. д., но у меня возникают проблемы, когда документ «скрыт» за URL-адресом, например:

http://www.oecd.org/officialdocuments/displaydocument/?cote=STD/CSTAT/WPNA(2008)25&docLanguage=En

Итак, два вопроса. Есть ли вообще способ узнать, есть ли у URL-адреса файл pdf/doc и т. д., на который он ссылается, если он не делает этого явно (например, www.domain.com/file.pdf)? Есть ли способ заставить Python поймать этот файл?

Редактировать: спасибо за ответы, некоторые из которых предлагают загрузить файл, чтобы убедиться, что он имеет правильный тип. Единственная проблема в том, что... я не знаю, как это сделать (см. вопрос № 2 выше). urlretrieve(<above url>) дает только html-файл с href, содержащим тот же URL-адрес.


person JonC    schedule 21.10.2010    source источник
comment
Я сам присматривался к чему-то подобному. Я использую os.system() для вызова curl -I url и анализа результата заголовка, чтобы получить то, что мне нужно.   -  person MRR0GERS    schedule 21.10.2010


Ответы (7)


В этом случае то, что вы называете «документом, на который явно не ссылаются в URL-адресе», похоже, является тем, что известно как «перенаправление». По сути, сервер сообщает вам, что вы должны получить документ по другому URL-адресу. Обычно urllib python автоматически следует этим перенаправлениям, так что вы получите правильный файл. (и, как уже упоминалось, вы можете проверить заголовок mime-типа ответа, чтобы увидеть, является ли он pdf).

Однако рассматриваемый сервер делает здесь что-то странное. Вы запрашиваете URL-адрес, и он перенаправляет вас на другой URL-адрес. Вы запрашиваете другой URL-адрес, и он снова перенаправляет вас... на тот же URL-адрес! И снова... И снова... В какой-то момент urllib решит, что этого уже достаточно, и перестанет следовать редиректу, чтобы не попасть в бесконечный цикл.

Так как же вы можете получить pdf, когда вы используете свой браузер? Потому что, по-видимому, сервер будет обслуживать PDF-файл только в том случае, если у вас включены файлы cookie. (почему? вы должны спросить людей, ответственных за сервер...) Если у вас нет файла cookie, он просто будет перенаправлять вас навсегда.

(проверьте urllib2 и cookielib для поддержки файлов cookie, это руководство может помочь)

По крайней мере, это то, что я думаю, является причиной проблемы. На самом деле я еще не пробовал делать это с помощью файлов cookie. Также может случиться так, что сервер «не хочет» обслуживать PDF-файл, потому что он обнаруживает, что вы не используете «обычный» браузер (в этом случае вам, вероятно, придется возиться с заголовком User-Agent), но он было бы странным способом сделать это. Итак, я предполагаю, что он где-то использует «сеансовый файл cookie», и, если у вас его еще нет, он продолжает пытаться перенаправить.

person Steven    schedule 21.10.2010
comment
Теория файлов cookie подтверждается: например, запрет на использование файлов cookie для этого сайта в Firefox, а затем запрос этого URL-адреса приводит к ошибке цикла перенаправления (даже если предположить, что это может быть вызвано тем, что файлы cookie не принимаются) - person Steven; 21.10.2010

По URL-адресу невозможно сказать, что он вам даст. Даже если он заканчивается на .pdf, он все равно может дать вам HTML или что угодно.

Вы можете сделать запрос HEAD и посмотреть тип содержимого, который, если сервер вам не лжет, сообщит вам, является ли это PDF-файлом.

В качестве альтернативы вы можете загрузить его, а затем выяснить, является ли то, что вы получили, PDF.

person Douglas Leeder    schedule 21.10.2010
comment
Спасибо за ответ. Для приведенного выше URL-адреса тип содержимого возвращается как text/html, даже если он косвенно указывает на .pdf. И загрузка дает только html-файл с href на тот же URL... есть идеи? - person JonC; 21.10.2010
comment
Проверьте мой ответ в контексте отсутствия расширения файла или ложного расширения файла, Python 3.X и веб-приложения stackoverflow.com/a/39356849/ 1209842 - person Claude COULOMBE; 06.09.2016

Как уже было сказано, невозможно отличить тип контента от URL-адреса. Но если вы не против получить заголовки для каждого URL-адреса, вы можете сделать это:

obj = urllib.urlopen(URL)

headers = obj.info()
if headers['Content-Type'].find('pdf') != -1:
   # we have pdf file, download whole
...

Таким образом, вам не нужно будет загружать каждый URL-адрес только его заголовки. Это все еще не совсем экономия сетевого трафика, но от этого лучше не станет.

Также вы должны использовать MIME-типы вместо моей грубой находки ('pdf').

person Stan    schedule 21.10.2010

Нет. Невозможно сказать, на какой ресурс ссылается URL-адрес, просто взглянув на него. Сервер полностью зависит от того, что он дает вам, когда вы запрашиваете определенный URL-адрес.

person Björn Pollex    schedule 21.10.2010

Проверьте тип mime с помощью функции urllib.info(). Это может быть не на 100% точно, это действительно зависит от того, что сайт возвращает как заголовок Content-Type. Если он ведет себя хорошо, он вернет правильный тип пантомимы.

PDF-файл должен возвращать application/pdf, но это может быть не так.

В противном случае вам, возможно, придется просто скачать его и попробовать.

person Xorlev    schedule 21.10.2010

Вы не можете увидеть это непосредственно по URL-адресу. Вы можете попробовать загрузить только заголовок HTTP-ответа и найти заголовок Content-Type. Однако вы должны доверять серверу в этом - он может ответить неправильным заголовком Content-Type, не соответствующим данным, представленным в теле.

person Femaref    schedule 21.10.2010

Определите тип файла в Python 3.x и веб-приложении с URL-адресом файла, который не может иметь расширения или поддельного расширения. Вы должны установить python-magic, используя

pip3 install python-magic

Для Mac OS X вам также следует установить libmagic, используя

brew install libmagic

Фрагмент кода

import urllib
import magic
from urllib.request import urlopen

url = "http://...url to the file ..."
request = urllib.request.Request(url)
response = urlopen(request)
mime_type = magic.from_buffer(response.read())
print(mime_type)
person Claude COULOMBE    schedule 06.09.2016