在Python中最快的HTTP GET方法是什么?


612

如果我知道内容将是字符串,那么用Python进行HTTP GET的最快方法是什么?我正在搜索文档,以查找像以下这样的快速单行代码:

contents = url.get("http://example.com/foo/bar")

但是,所有我能找到使用谷歌是httpliburllib-我无法找到这些库中的快捷方式。

标准Python 2.5是否具有上述某种形式的快捷方式,还是应该编写一个函数url_get

  1. 我宁愿不捕获对wget或的炮击输出curl

我在这里找到了我需要的东西:stackoverflow.com/a/385411/1695680
ThorSummoner

Answers:


869

Python 3:

import urllib.request
contents = urllib.request.urlopen("http://example.com/foo/bar").read()

Python 2:

import urllib2
contents = urllib2.urlopen("http://example.com/foo/bar").read()

urllib.request和的文档read


44
一切都清理干净了吗?看来我应该打给closeread。那有必要吗?
Frank Krueger

4
将其关闭是个好习惯,但是如果您要寻找一种快速的单线产品,则可以忽略它。:-)
尼克·普雷斯塔

28
当urlopen返回的对象超出范围时,它将被删除(并最终确定,将其关闭)。因为Cpython是引用计数的,所以您可以依靠紧接在之后的情况read。但是,一个with块将是Jython中,等更清晰,更安全
蛛网膜下腔出血

8
它不适用于仅HTTPS的网站。requests效果很好
OverCoder '16

6
如果您使用的是Amazon Lambda,并且需要获取URL,则2.x解决方案可用并且是内置的。它似乎也可以与https一起使用。这无非r = urllib2.urlopen("http://blah.com/blah")然后text = r.read()。它是同步的,它只等待“文本”中的结果。
Fattie

412

您可以使用一个称为request的库。

import requests
r = requests.get("http://example.com/foo/bar")

这很容易。然后您可以这样做:

>>> print(r.status_code)
>>> print(r.headers)
>>> print(r.content)

1
@JoeBlow记住,您必须导入外部库才能使用它们
MikeVelazco

1
几乎所有Python库都可以在AWS Lambda中使用。对于纯Python,您只需“供应”该库(复制到模块的文件夹中而不是使用pip install)。对于非纯库,还有一个额外的步骤-您需要pip install将lib库保存到一个AWS Linux实例(运行相同的OS变体lambda)上,然后复制这些文件,以便与AWS Linux具有二进制兼容性。您不能始终在Lambda中使用的唯一库只有二进制分发库,这是非常罕见的。
克里斯·约翰逊

6
@lawphotog这确实适用于python3,但您必须这样做pip install requests
akarilimano

甚至urllib2标准库也推荐请求
Asfand Qazi

关于Lambda:如果您希望在AWS Lambda函数中使用请求。还有一个预装的boto3请求库。 from botocore.vendored import requests 用法 response = requests.get('...')
kmjb

29

如果您希望使用httplib2的解决方案成为一体,请考虑实例化匿名Http对象。

import httplib2
resp, content = httplib2.Http().request("http://example.com/foo/bar")

19

看一下httplib2,它提供了很多您想要的东西,它旁边有许多非常有用的功能。

import httplib2

resp, content = httplib2.Http().request("http://example.com/foo/bar")

其中content是响应主体(作为字符串),而resp将包含状态和响应标头。

虽然它不包含在标准python安装中(但只需要标准python),但是绝对值得一试。


6

强大的urllib3库就足够简单了。

像这样导入它:

import urllib3

http = urllib3.PoolManager()

并发出这样的请求:

response = http.request('GET', 'https://example.com')

print(response.data) # Raw data.
print(response.data.decode('utf-8')) # Text.
print(response.status) # Status code.
print(response.headers['Content-Type']) # Content type.

您也可以添加标题:

response = http.request('GET', 'https://example.com', headers={
    'key1': 'value1',
    'key2': 'value2'
})

可以在urllib3文档中找到更多信息。

urllib3比内置模块urllib.requesthttp模块更安全,更易于使用,并且稳定。


1
事实很不错,您可以轻松提供HTTP动词
Tom

5

theller的wget解决方案确实很有用,但是,我发现它无法在整个下载过程中打印出进度。如果在reporthook中的print语句后添加一行,那是完美的。

import sys, urllib

def reporthook(a, b, c):
    print "% 3.1f%% of %d bytes\r" % (min(100, float(a * b) / c * 100), c),
    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

4

这是Python中的wget脚本:

# From python cookbook, 2nd edition, page 487
import sys, urllib

def reporthook(a, b, c):
    print "% 3.1f%% of %d bytes\r" % (min(100, float(a * b) / c * 100), c),
for url in sys.argv[1:]:
    i = url.rfind("/")
    file = url[i+1:]
    print url, "->", file
    urllib.urlretrieve(url, file, reporthook)
print

4

无需其他必要的导入,此解决方案(对我而言)有效-也适用于https:

try:
    import urllib2 as urlreq # Python 2.x
except:
    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: Forbiddenurllib.error.HTTPError: HTTP Error 403: Forbidden


4

如何发送标头

Python 3:

import urllib.request
contents = urllib.request.urlopen(urllib.request.Request(
    "https://api.github.com/repos/cirosantilli/linux-kernel-module-cheat/releases/latest",
    headers={"Accept" : 'application/vnd.github.full+json"text/html'}
)).read()
print(contents)

Python 2:

import urllib2
contents = urllib2.urlopen(urllib2.Request(
    "https://api.github.com",
    headers={"Accept" : 'application/vnd.github.full+json"text/html'}
)).read()
print(contents)

2

如果您专门使用HTTP API,那么还有更方便的选择,例如Nap

例如,以下是自20145月1日起从Github获取要点的方法:

from nap.url import Url
api = Url('https://api.github.com')

gists = api.join('gists')
response = gists.get(params={'since': '2014-05-01T00:00:00Z'})
print(response.json())

更多示例:https : //github.com/kimmobrunfeldt/nap#examples


2

出色的解决方案轩,塞勒。

为了使其与python 3配合使用,请进行以下更改

import sys, urllib.request

def reporthook(a, b, c):
    print ("% 3.1f%% of %d bytes\r" % (min(100, float(a * b) / c * 100), c))
    sys.stdout.flush()
for url in sys.argv[1:]:
    i = url.rfind("/")
    file = url[i+1:]
    print (url, "->", file)
    urllib.request.urlretrieve(url, file, reporthook)
print

另外,您输入的URL之前应带有“ http://”,否则将返回未知的URL类型错误。


1

对于python >= 3.6,您可以使用dload

import dload
t = dload.text(url)

对于json

j = dload.json(url)

安装:
pip install dload


0

实际上,在python中,我们可以从文件中读取url,这是从API读取json的示例。

import json

from urllib.request import urlopen

with urlopen(url) as f:

resp = json.load(f)

return resp['some_key']

尽管我们感谢您的回答,但如果它在其他答案的基础上提供附加价值,那会更好。在这种情况下,您的答案没有提供其他价值,因为另一个用户已经发布了该解决方案。如果以前的答案对您有所帮助,则应投票赞成,而不要重复相同的信息。
Toby Speight

0

如果您需要较低级别的API:

import http.client

conn = http.client.HTTPSConnection('example.com')
conn.request('GET', '/')

resp = conn.getresponse()
content = resp.read()

conn.close()

text = content.decode('utf-8')

print(text)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.