Столкнулся с проблемой. Разрабатываю мобильный клиент для просмотра групп ВКонтакте. В аттачах к постам показываю ссылки. Мне нужно открыть такую ссылку в стандартном браузере девайса, если ссылка ведет на страницу в сети или начать загрузку средствами моего приложения, если ссылка указывает на файл. Я не думал, что это может стать настоящей проблемой, поскольку, например модуль urlparse
оказался абсолютно бесполезным:
print(urlparse('http://play.google.com/store/details?id=org.name.old&rdid=org.name.old).path) >>> play.google.com/store/details
И такая ссылка:
print(urlparse('http://page/file.txt).path) >>> /file.txt
И тут становится совершенно непонятно, как определить, на что указывает ссылка http://play.google.com/store/details?id=org.name.old&rdid=org.name.old
. Очевидно, что, например, модуль os
здесь тоже мало чем поможет.
Неужели нужно применять os.path.splitext
, выдергивая из ссылки расширение, если оно есть, и проверять, принадлежит ли это расширение к известным типам файлов?
Необходимо определить, оканчивается ли ссылка каким-то конкретным расширением, указанным в коде.
Если оканчивается, скачивает.
В противном случае — открывает в стандартном браузере страницу.
from urllib.parse import urlsplit import webbrowser import wget url = 'http://play.google.com/store/details?id=org.name.old&rdid=org.name.old' # Или же http://page.com/file.txt if not urlsplit(url)[2].endswith(".txt") and not urlsplit(url)[2].endswith(".mp4"): # И так далее. webbrowser.open_new_tab(url) else: wget.download(url, out="dl_content/file.txt")
Можно получать только заголовок http
ответа, и в нем смотреть content-type
. Если это он содержит text/html
, значит это web-страница.
Пример:
import requests url = 'https://yandex.ru' r = requests.head(url) print(r.headers['content-type']) # 'text/html; charset=UTF-8' # Ссылка на скачивание заглавной страницы Википедии в виде pdf url = 'https://ru.wikipedia.org/api/rest_v1/page/pdf/Заглавная_страница' r = requests.head(url) print(r.headers['content-type']) # 'application/pdf'
Для обработки редиректов при запросе нужно указывать allow_redirects=True
(по-умолчанию для функции head
отключено):
url = 'http://ya.ru' # Редиректит на https://ya.ru r = requests.head(url, allow_redirects=True) print(r.headers['content-type']) # 'text/html; charset=UTF-8'
Если Content-Disposition http заголовок говорит, что attachment, то скачивайте ссылку как файл (имя в заголовке может быть указано). Одно и то же содержимое может показываться inline или cкачиваться в зависимости от этого заголовка, rfc 6266:
If the disposition type matches «attachment» (case-insensitively),
this indicates that the recipient should prompt the user to save the
response locally, rather than process it normally (as per its media
type).
На Питоне:
import urllib.request with urllib.request.urlopen(url) as r: if r.headers.get_content_disposition() == 'attachment': download(r) else: process_as_usual(r)