Python请求:会话中的URL基

2024-04-28 06:58:53 发布

您现在位置:Python中文网/ 问答频道 /正文

在使用会话时,似乎每次都需要提供完整的URL,例如

session = requests.Session()
session.get('http://myserver/getstuff')
session.get('http://myserver/getstuff2')

这有点乏味。有什么方法可以做到:

session = requests.Session(url_base='http://myserver')
session.get('/getstuff')
session.get('/getstuff2')

Tags: 方法httpurlbasegetsessionrequestsmyserver
3条回答

这个功能已经在论坛上被问过几次了123。如here所述,首选的方法是子类化,如下所示:

from requests import Session
from urlparse import urljoin

class LiveServerSession(Session):
    def __init__(self, prefix_url=None, *args, **kwargs):
        super(LiveServerSession, self).__init__(*args, **kwargs)
        self.prefix_url = prefix_url

    def request(self, method, url, *args, **kwargs):
        url = urljoin(self.prefix_url, url)
        return super(LiveServerSession, self).request(method, url, *args, **kwargs)

您只需如下使用:

baseUrl = 'http://api.twitter.com'
with LiveServerSession(baseUrl) as s:
    resp = s.get('/1/statuses/home_timeline.json')

请求工具带.sessions.BaseUrlSession https://github.com/requests/toolbelt/blob/f5c86c51e0a01fbc8b3b4e1c286fd5c7cb3aacfa/requests_toolbelt/sessions.py#L6

注意:这使用标准库中的urljoin。当心urljoin的行为。

In [14]: from urlparse import urljoin

In [15]: urljoin('https://localhost/api', '/resource')
Out[15]: 'https://localhost/resource'

In [16]: urljoin('https://localhost/api', 'resource')
Out[16]: 'https://localhost/resource'

In [17]: urljoin('https://localhost/api/', '/resource')
Out[17]: 'https://localhost/resource'

In [18]: urljoin('https://localhost/api/', 'resource')
Out[18]: 'https://localhost/api/resource'

import requests 
from functools import partial

def PrefixUrlSession(prefix=None):                                                                                                                                                                                                                                                                                                                 
     if prefix is None:                                                                                                                                                                                                                                                                                                                             
         prefix = ""                                                                                                                                                                                                                                                                                                                                
     else:                                                                                                                                                                                                                                                                                                                                          
         prefix = prefix.rstrip('/') + '/'                                                                                                                                                                                                                                                                                                          

     def new_request(prefix, f, method, url, *args, **kwargs):                                                                                                                                                                                                                                                                                      
         return f(method, prefix + url, *args, **kwargs)                                                                                                                                                                                                                                                                                            

     s = requests.Session()                                                                                                                                                                                                                                                                                                                         
     s.request = partial(new_request, prefix, s.request)                                                                                                                                                                                                                                                                                            
     return s             

您可以将request.Session子类化并重载其__init__request方法,如下所示:

# my_requests.py
import requests


class SessionWithUrlBase(requests.Session):
    # In Python 3 you could place `url_base` after `*args`, but not in Python 2.
    def __init__(self, url_base=None, *args, **kwargs):
        super(SessionWithUrlBase, self).__init__(*args, **kwargs)
        self.url_base = url_base

    def request(self, method, url, **kwargs):
        # Next line of code is here for example purposes only.
        # You really shouldn't just use string concatenation here,
        # take a look at urllib.parse.urljoin instead.
        modified_url = self.url_base + url

        return super(SessionWithUrlBase, self).request(method, modified_url, **kwargs)

然后可以在代码中使用子类而不是requests.Session

from my_requests import SessionWithUrlBase


session = SessionWithUrlBase(url_base='https://stackoverflow.com/')
session.get('documentation')  # https://stackoverflow.com/documentation

此外,您还可以对requests.Session进行修补,以避免修改现有的代码库(此实现应100%兼容),但请确保在任何代码调用之前进行实际修补requests.Session()

# monkey_patch.py
import requests


class SessionWithUrlBase(requests.Session):
    ...

requests.Session = SessionWithUrlBase

然后:

# main.py
import requests
import monkey_patch


session = requests.Session()
repr(session)  # <monkey_patch.SessionWithUrlBase object at ...>

相关问题 更多 >