Python请求获取的完整指南

1,577 阅读9分钟

requests 库是在 Python 中进行 HTTP 请求的主要标准。使用Python requests库进行请求是非常简单的。它把做HTTP请求的复杂性抽象在美丽而简单的API后面,这样你就可以集中精力与服务进行交互并在你的应用程序中消费数据。

HTTP GET请求

HTTP(HyperText Transfer Protocol)方法,如GET和POST,决定了你在发出HTTP请求时要执行的动作。除了GET和POST,还有其他几种标准方法,你在本例后面会用到。

最标准的HTTP方法之一是GET。GET 方法表示你正试图从一个指定的资源中获取或检索数据。

安装 requests Python 模块

你可以通过运行以下命令来安装requests库。

python3 -m pip install requests

# OR

pip install requests

如果你希望使用Pipenv来管理Python包,你可以运行下面的:

pipenv install requests

一旦requests 模块被安装,你就可以在你的应用程序中使用它。例如,导入 requests 看起来像下面这样:

import requests

Python requests get

要在Python 中创建一个GET 请求,请使用requests.get()方法。get() 方法需要三个参数,并返回一个带有状态码的响应。requests get() 方法向指定的 URL 发送一个 GET 请求。

语法

requests.get(url, params={key: value}, args)

args指的是下面参数表中的零个或多个命名参数,例子:

requests.get(url, timeout=2.50)

参数

参数说明
网址必须的。请求的网址。
参数可选的。它是一个字典,是要作为查询字符串发送的图元组或字节的列表。
默认的
允许重定向可选的。一个布尔值,用于启用/禁用重定向。
默认为(允许重定向)。
auth可选的。一个元组,用于启用安全的HTTP认证。
默认值
认证可选的。它是一个字符串或元组,指定证书文件或密钥。
默认
饼干可选的。它是一个cookie的字典,用于向指定的url发送cookie。
默认
头文件可选的。它是一个HTTP头文件的字典,用于发送给指定的URL。
默认
代理人可选的。它是一个向代理网址发送协议的字典。
默认
可选的。它是一个布尔指示,如果响应应该立即下载(False)或流(True)。
默认False
timeout可选的。它是一个数字,或一个元组,表示等待客户端建立连接并发送响应的时间。
默认,表示请求将继续,直到连接关闭。
验证可选的。一个布尔值或一个字符串,表示是否测试服务器的TLS证书。
默认为

我们将调用Github的API。

import requests

data = requests.get('https://api.github.com/users/KrunalLathiya')
print(data.json()['login'])

输出

KrunalLathiya

我们得到了数据形式的响应,然后我们使用json()来解析这些数据。

所以,我们以字典的形式获得数据,然后,我们需要调用值的键,我们将获得值。

响应对象

requests.get()方法返回响应,这是一个强大的对象,用于检查请求结果。再一次,让我们 看看上面的ExampleExample,但是这一次,我们不会解析json。

import requests

data = requests.get('https://api.github.com/users/KrunalLathiya')
print(data)

输出

<Response [200]>

在这个例子中,你已经捕获了get()的返回值,也就是response的实例,并将其存储在名为a response的变量中。现在你可以使用 response 来查看关于你的 GET 请求结果的很多信息。

我们在响应中得到了状态码,是200。所以这意味着页面在那里。

让我们发送一个GET请求,在这个请求中我们没有得到200的状态码。

import requests

data = requests.get('https://api.github.com/KrunalLathiya')
print(data)

输出

<Response [404]>

这意味着该页面不存在,我们得到了状态代码为404的未找到页面的错误。

状态代码

我们可以从响应中收集的第一个信息是状态代码。状态代码会通知你请求的状态。

例如,200 OK状态意味着你的请求是成功的,而404状态意味着你正在寻找的资源没有被发现。

在上面的例子中,我们得到了200和404的状态代码。

通过访问.status_code,你可以看到服务器返回的状态代码。

import requests

data = requests.get('https://api.github.com/KrunalLathiya')
print(data.status_code)

输出

404

有时,你必须使用状态代码信息来在你的代码中做出决定。例如,根据返回的代码,把if-else语句

if response.status_code == 200:
    print('You got the success!')
elif response.status_code == 404:
    print('Page not Found.')

你可以通过改写if语句来简化上面的ExampleExample:

if response:
    print('You got the success!')
else:
    print('Something went wrong.')

根据状态代码引发异常

你不需要在if语句中检查响应的状态码。相反,你必须在请求不成功的情况下引发一个异常。你可以用.raise_for_status()来做。

请看下面的代码:

from requests import get, HTTPError

for url in ['https://api.github.com/users/KrunalLathiya', 'https://api.github.com/data']:
    try:
        response = get(url)
        # If the response was successful, no Exception will be raised
        response.raise_for_status()
    except HTTPError as http_err:
        print(f'HTTP error occurred: {http_err}')
    except Exception as err:
        print(f'Other error occurred: {err}')
    else:
        print('Successfull GET Request')

在这个ExampleExample中,我们只是从请求模块中导入了所需的方法。

我们已经导入了getHTTPError。

然后我们将它们用于......循环,并使用了异常处理机制。

如果一个请求的响应是成功的,那么将不会产生任何异常;否则,将产生HTTPError异常。

在上面的代码例子中,我们传递了两个列表项。一个是有效的,另一个是无效的。

请看输出结果:

Successfull GET Request
HTTP error occurred: 404 Client Error: Not Found for url: https://api.github.com/data

你可以看到第一个GET请求是成功的,而第二个GET请求是失败的,并返回404客户错误。

如果你调用.raise_for_status(),HTTPError将针对某些状态代码被引发。如果状态代码表明请求成功,程序将继续进行,不会引发异常。

内容

GET请求在消息体中经常有一些有价值的信息,被称为有效载荷。使用Response的属性和方法,你可以看到不同格式的有效载荷。

from requests import get

res = get('https://api.github.com/users/KrunalLathiya')

print(res.content)

输出

b'{"login":"KrunalLathiya","id":14403830,"node_id":"MDQ6VXNlcjE0NDAzODMw",
"avatar_url":"https://avatars1.githubusercontent.com/u/14403830?v=4",
"gravatar_id":"","url":"https://api.github.com/users/KrunalLathiya",
"html_url":"https://github.com/KrunalLathiya",
"followers_url":"https://api.github.com/users/KrunalLathiya/followers",
"following_url":"https://api.github.com/users/KrunalLathiya/following{/other_user}",
"gists_url":"https://api.github.com/users/KrunalLathiya/gists{/gist_id}",
"starred_url":"https://api.github.com/users/KrunalLathiya/starred{/owner}{/repo}",
"subscriptions_url":"https://api.github.com/users/KrunalLathiya/subscriptions",
"organizations_url":"https://api.github.com/users/KrunalLathiya/orgs",
"repos_url":"https://api.github.com/users/KrunalLathiya/repos",
"events_url":"https://api.github.com/users/KrunalLathiya/events{/privacy}",
"received_events_url":"https://api.github.com/users/KrunalLathiya/received_events",
"type":"User",
"site_admin":false,"name":"Krunal","company":"Freelancer",
"blog":"https://appdividend.com","location":"Rajkot",
"email":null,"hireable":true,"bio":"Web Developer and Author",
"twitter_username":null,"public_repos":121,"public_gists":0,
"followers":546,"following":13,"created_at":"2015-09-20T19:22:19Z",
"updated_at":"2020-06-07T13:10:25Z"}'

响应对象的内容属性给出了有效载荷的原始字节数。你经常需要使用字符编码(如UTF-8)将它们转换为字符串。

当你访问.text时,响应将为你做这个:

from requests import get

res = get('https://api.github.com/users/KrunalLathiya')

print(res.text)

将序列化的JSON转换为字典

如果你仔细检查响应内容,你可以看到它是一个序列化的json。你可以使用 .json() 方法将 json 转换为字典:

from requests import get

res = get('https://api.github.com/users/KrunalLathiya')

print(res.json())

输出

{'login': 'KrunalLathiya', 'id': 14403830, 'node_id': 'MDQ6VXNlcjE0NDAzODMw', 
'avatar_url': 'https://avatars1.githubusercontent.com/u/14403830?v=4', 
'gravatar_id': '', 'url': 'https://api.github.com/users/KrunalLathiya', 
'html_url': 'https://github.com/KrunalLathiya', 
'followers_url': 'https://api.github.com/users/KrunalLathiya/followers', 
'following_url': 'https://api.github.com/users/KrunalLathiya/following{/other_user}', 
'gists_url': 'https://api.github.com/users/KrunalLathiya/gists{/gist_id}', 
'starred_url': 'https://api.github.com/users/KrunalLathiya/starred{/owner}{/repo}', 
'subscriptions_url': 'https://api.github.com/users/KrunalLathiya/subscriptions', 
'organizations_url': 'https://api.github.com/users/KrunalLathiya/orgs', 
'repos_url': 'https://api.github.com/users/KrunalLathiya/repos', 
'events_url': 'https://api.github.com/users/KrunalLathiya/events{/privacy}', 
'received_events_url': 'https://api.github.com/users/KrunalLathiya/received_events', 
'type': 'User', 'site_admin': False, 'name': 'Krunal', 
'company': 'Freelancer', 'blog': 'https://appdividend.com', 
'location': 'Rajkot', 'email': None, 
'hireable': True, 'bio': 'Web Developer and Author', 
'twitter_username': None, 'public_repos': 121, 
'public_gists': 0, 'followers': 546, 'following': 13, 
'created_at': '2015-09-20T19:22:19Z', 
'updated_at': '2020-06-07T13:10:25Z'}

你可以看到,我已经得到了Dictionary形式的数据。

现在,我可以用Dictionary的键来访问它的一个一个的值。

from requests import get

res = get('https://api.github.com/users/KrunalLathiya')

print(res.json()['login'])

输出

KrunalLathiya

.json()方法的返回值类型是Dictionary,这样你就可以通过key访问对象中的值。

你可以用状态代码和消息体做很多事情。但是,如果你需要更多的信息,比如关于响应本身的元数据,你将需要看一下响应的头信息。

标头

响应头文件可以给我们提供有用的信息,例如响应有效载荷的内容类型和对响应进行缓存的时间限制。要查看这些头信息,请访问.headers。

from requests import get

res = get('https://api.github.com/users/KrunalLathiya')

print(res.headers)

输出

{'date': 'Thu, 18 Jun 2020 08:06:29 GMT', 'content-type': 'application/json; charset=utf-8', 'server': 'GitHub.com', 'status': '200 OK', 'cache-control': 'public, max-age=60, s-maxage=60', 'vary': 'Accept, Accept-Encoding, Accept, X-Requested-With, Accept-Encoding', 'etag': 'W/"cd0a64256ac419c62d91c62feebf0f95"', 'last-modified': 'Sun, 07 Jun 2020 13:10:25 GMT', 'x-github-media-type': 'github.v3; format=json', 'access-control-expose-headers': 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset', 'access-control-allow-origin': '*', 'strict-transport-security': 'max-age=31536000; includeSubdomains; preload', 'x-frame-options': 'deny', 'x-content-type-options': 'nosniff', 'x-xss-protection': '1; mode=block', 'referrer-policy': 'origin-when-cross-origin, strict-origin-when-cross-origin', 'content-security-policy': "default-src 'none'", 'content-encoding': 'gzip', 'X-Ratelimit-Limit': '60', 'X-Ratelimit-Remaining': '54', 'X-Ratelimit-Reset': '1592469405', 'Accept-Ranges': 'bytes', 'Content-Length': '513', 'X-GitHub-Request-Id': '9E0F:3387:F368EE:140B639:5EEB2084'}

.headers返回一个类似字典的对象,允许你通过键来访问头的值。

from requests import get

res = get('https://api.github.com/users/KrunalLathiya')

print(res.headers['server'])

输出

GitHub.com

不过,这个类似字典的头信息对象有一些特别之处。HTTP规范定义的头信息是不区分大小写的,这意味着我们可以访问这些头信息而不用担心它们的大小写。

请求头信息

要定制头信息,你可以使用头信息参数将HTTP头信息的字典传递给get()。

例如,你可以改变之前的搜索请求,通过在Accept头中指定文本匹配媒体类型来突出结果中的匹配搜索词。

from requests import get


response = get(
    'https://api.github.com/search/repositories',
    params={'q': 'requests+language:php'},
    headers={'Accept': 'application/vnd.github.v3.text-match+json'},
)

# View the new `text-matches` array which provides information
# about your search term within the results
json_response = response.json()
repository = json_response['items'][0]
print(f'Text matches: {repository["text_matches"]}')

输出

Text matches: [{'object_url': 'https://api.github.com/repositories/117567334', 'object_type': 'Repository', 'property': 'description', 'fragment': 'Easily build Eloquent queries from API requests', 'matches': [{'text': 'requests', 'indices': [39, 47]}]}]

Accept头告诉服务器你的应用程序可以处理哪些内容类型。

因为你希望突出显示匹配的搜索词,所以你使用头值application/vnd.Github.v3.text-match+json是GitHub专有的Accept头,内容是特定的JSON格式。

总结

在这个Python requests get ExampleExample中,我们已经看到了如何向服务器发送GET请求,处理响应,将数据从json转换为字典,以及请求头信息。

最后,Python请求get()示例结束。

另见

如何安装Python模块

如何升级pip

如何安装Numpy