当我们使用requests.get()的时候,发生了什么

写在前面


当我们想要获取一个网页的数据时,比较简便的方式是调用requests.get()这个方法,初次使用你会觉得很简单很神奇,但是这里面到底进行了什么操作,你是否又知道呢?当你整明白了这些之后,你就可以设计一个调度器去调度请求,这样在你学Scrapy的时候会有更深的理解


解析过程


我们先来看看requests的get方法中实现了什么


def get(url, params=None, **kwargs):

    kwargs.setdefault('allow_redirects', True)
    return request('get', url, params=params, **kwargs)


从上面可以看到,kwargs是设置一个http请求所需要的参数。get方法先设置一下allow_redirects参数,这个参数是指明在请求的时候是否允许重定向,True表示允许。然后调用request方法。那这个方法又实现了什么呢?


def request(method, url, **kwargs):

    # By using the 'with' statement we are sure the session is closed, thus we
    # avoid leaving sockets open which can trigger a ResourceWarning in some
    # cases, and look like a memory leak in others.
    with sessions.Session() as session:
        return session.request(method=method, url=url, **kwargs)


这个方法先创建一个Session对象,然后调用Session的request方法,把request方法中传入的参数作为参数调用。看到这里就可以知道,对同一个站点,使用requests.get()请求该站点的不同页面的时候,这两个请求是独立的(简单理解就是第一个请求模拟登录了该网站,然后第二个请求去访问有登录限制的页面会出现Error),因为每次调用就会生成一个Session对象,维持一次会话。当你模拟登录某网站的时候,你再去访问带有登录限制的网页的时候,会自动带上有登录成功后服务器返回给你的Cookies,这个时候就可以正常访问。


我们接着看


    def request(self, method, url,
        params=None,
        data=None,
        headers=None,
        cookies=None,
        files=None,
        auth=None,
        timeout=None,
        allow_redirects=True,
        proxies=None,
        hooks=None,
        stream=None,
        verify=None,
        cert=None,
        json=None):
 
        # Create the Request.
        req = Request(
            method = method.upper(),
            url = url,
            headers = headers,
            files = files,
            data = data or {},
            json = json,
            params = params or {},
            auth = auth,
            cookies = cookies,
            hooks = hooks,
        )
        prep = self.prepare_request(req)

        proxies = proxies or {}

        settings = self.merge_environment_settings(
            prep.url, proxies, stream, verify, cert
        )

        # Send the request.
        send_kwargs = {
            'timeout': timeout,
            'allow_redirects': allow_redirects,
        }
        send_kwargs.update(settings)
        resp = self.send(prep, **send_kwargs)

        return resp


根据一个请求的参数(超时,代理,url,重定向等)构建一个Request对象,初始化请求参数,然后调用一下prepare_request方法,这个又是啥?再定位到该方法


def prepare_request(self, request):
        cookies = request.cookies or {}

        # Bootstrap CookieJar.
        if not isinstance(cookies, cookielib.CookieJar):
            cookies = cookiejar_from_dict(cookies)

        # Merge with session cookies
        merged_cookies = merge_cookies(
            merge_cookies(RequestsCookieJar(), self.cookies), cookies)

        # Set environment's basic authentication if not explicitly set.
        auth = request.auth
        if self.trust_env and not auth and not self.auth:
            auth = get_netrc_auth(request.url)

        p = PreparedRequest()
        p.prepare(
            method=request.method.upper(),
            url=request.url,
            files=request.files,
            data=request.data,
            json=request.json,
            headers=merge_setting(request.headers, self.headers, dict_class=CaseInsensitiveDict),
            params=merge_setting(request.params, self.params),
            auth=merge_setting(auth, self.auth),
            cookies=merged_cookies,
            hooks=merge_hooks(request.hooks, self.hooks),
        )
        return p


prepare_request实现的其实是根据传过来的Request对象,提出出该请求的相关参数,然后构建出一个PreparedRequest对象,初始化该对象,最后返回一个PreparedRequest实例


再回到request方法,在前面的操作完成之后,最后调用了send方法,把PreparedRequest对象发出去,然后这个方法会返回一个response响应。至此,对get()方法的分析就告一段落了


说了那么多其实也就是下图所示流程

总结.jpg


总结



了解了requests的请求过程,我们就可以利用这个东西去做一个爬虫的请求队列,这样就可以多个Spider共享,也算是是为分布式抓取开了个头吧

你可能感兴趣的:(当我们使用requests.get()的时候,发生了什么)