美文网首页
当我们使用requests.get()的时候,发生了什么

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

作者: LinxsCoding | 来源:发表于2018-06-01 19:35 被阅读230次

    写在前面

    当我们想要获取一个网页的数据时,比较简便的方式是调用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()的时候,发生了什么

          本文链接:https://www.haomeiwen.com/subject/crgksftx.html