Какой самый быстрый способ выполнить HTTP GET в Python?
Какой самый быстрый способ выполнить HTTP GET на Python, если я знаю, что содержимое будет строкой? Я ищу документацию на что-то вроде однострочного кода:
contents = url.get("http://example.com/foo/bar")
Но всё, что я могу найти с помощью Google, это httplib
и urllib
, и мне не удаётся найти какой-либо краткий способ в этих библиотеках.
Есть ли в стандартной библиотеке Python 2.5 какой-либо аналогичный способ, как указано выше, или мне стоит написать функцию url_get
?
- Я предпочёл бы не захватывать вывод, используя
wget
илиcurl
.
5 ответ(ов)
Если вы хотите получить решение с использованием httplib2
в виде однострочника, рассмотрите возможность создания анонимного объекта Http
:
import httplib2
resp, content = httplib2.Http().request("http://example.com/foo/bar")
Таким образом, весь код выполняется в одной строке, и вы сразу получаете ответ и содержимое запроса.
На самом деле в Python мы можем читать HTTP-ответы так же, как файлы. Вот пример, как можно считать JSON-ответ из API:
import json
from urllib.request import urlopen
with urlopen(url) as f:
resp = json.load(f)
return resp['some_key']
В этом примере мы используем urlopen
для открытия URL, после чего читаем содержимое ответа с помощью json.load()
. Результат сохраняется в переменной resp
, и мы можем получить значение по нужному ключу.
Этот код работает (для меня) без дополнительных импортов – также с использованием HTTPS:
try:
import urllib2 as urlreq # Python 2.x
except ImportError:
import urllib.request as urlreq # Python 3.x
req = urlreq.Request("http://example.com/foo/bar")
req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36')
urlreq.urlopen(req).read()
Я часто сталкиваюсь с проблемами при попытке получить содержимое, когда не указываю "User-Agent" в заголовках. Обычно в таких случаях запросы отменяются с сообщением вроде: urllib2.HTTPError: HTTP Error 403: Forbidden
или urllib.error.HTTPError: HTTP Error 403: Forbidden
.
Чтобы отправить заголовки вместе с запросом в Python, вы можете использовать модуль urllib.request
в Python 3 или urllib2
в Python 2. Пример ниже показывает, как это сделать для API GitHub, чтобы получить последние релизы.
Python 3:
import urllib.request
# Создание запроса с заголовками
request = urllib.request.Request(
"https://api.github.com/repos/cirosantilli/linux-kernel-module-cheat/releases/latest",
headers={"Accept": 'application/vnd.github.full+json;text/html'}
)
# Открытие URL и чтение содержимого
contents = urllib.request.urlopen(request).read()
print(contents)
Python 2:
import urllib2
# Создание запроса с заголовками
request = urllib2.Request(
"https://api.github.com",
headers={"Accept": 'application/vnd.github.full+json;text/html'}
)
# Открытие URL и чтение содержимого
contents = urllib2.urlopen(request).read()
print(contents)
В обоих примерах мы создаем запрос с определёнными заголовками, используя словарь. Заголовок "Accept"
указывает серверу, в каком формате мы ожидаем получить ответ.
Ваша проблема с отсутствием прогресса при загрузке с помощью wget действительно важна. Решение theller'а полезно, но вы можете улучшить его, добавив одну строку после оператора print
в функции reporthook
. Вот улучшенный код с отображением прогресса:
import sys, urllib
def reporthook(a, b, c):
# Выводим прогресс в процентах
print("% 3.1f%% из %d байт\r" % (min(100, float(a * b) / c * 100), c), end="")
sys.stdout.flush()
for url in sys.argv[1:]:
i = url.rfind("/")
file = url[i+1:]
print(url, "->", file)
urllib.urlretrieve(url, file, reporthook)
print() # Печатаем новую строку по окончании загрузки
Обратите внимание, что я добавил end=""
в print
, чтобы избежать перехода на новую строку, и теперь при каждом обновлении прогресса информация будет выводиться на одной строке. Также стоит упомянуть, что для использования этой функции вам нужно выполнять скрипт с аргументами, перечисляющими URL-адреса, которые нужно загрузить.
Как скачать файл по HTTP?
Почему используется string.join(list), а не list.join(string)?
Создание словаря с помощью генератора словарей
Как получить полный путь к директории текущего файла?
Найти все файлы с расширением .txt в директории на Python