headers & cookies - Will update to the current headers/cookies and just be for this request
        driver_args & driver_kwargs - Gets passed and expanded out to the driver

def get_site(self, url, cookies={}, page_format='html', return_on_error=[], retry_enabled=True,
                 num_tries=0, num_apikey_tries=0, headers={}, api=False, track_stat=True, timeout=30,
                 force_requests=False, driver_args=(), driver_kwargs={}, parser='beautifulsoup',
                 custom_source_checks=[]):
        """
        headers & cookies - Will update to the current headers/cookies and just be for this request
        driver_args & driver_kwargs - Gets passed and expanded out to the driver
        """
        self._reset_response()

        num_tries += 1
        # Save args and kwargs so they can be used for trying the function again
        tmp_args = locals().copy()
        get_site_args = [tmp_args['url']]
        # Remove keys that dont belong to the keywords passed in
        del tmp_args['url']
        del tmp_args['self']
        get_site_kwargs = tmp_args

        # Check driver_kwargs for anything that we already set
        kwargs_cannot_be = ['headers', 'cookies', 'timeout']
        for key_name in kwargs_cannot_be:
            if driver_kwargs.get(key_name) is not None:
                del driver_kwargs[key_name]
                logger.warning("Cannot pass `{key}` in driver_kwargs to get_site(). `{key}` is already set by default"
                               .format(key=key_name))

        # Check if a url is being passed in
        if url is None:
            logger.error("Url cannot be None")
            return None

        ##
        # url must start with http....
        ##
        prepend = ''
        if url.startswith('//'):
            prepend = 'http:'

        elif not url.startswith('http'):
            prepend = 'http://'

        url = prepend + url

        ##
        # Try and get the page
        ##
        rdata = None
        try:
            source_text = self._get_site(url, headers, cookies, timeout, driver_args, driver_kwargs)
            if custom_source_checks:
                # Check if there are any custom check to run
                for re_text, status_code in custom_source_checks:
                    if re.search(re_text, source_text):
                        if self.response is None:
                            # This is needed when using selenium and we still need to pass in the 'response'
                            self.response = type('', (), {})()
                        self.response.status_code = status_code
                        self.status_code = status_code
                        raise requests.exceptions.HTTPError("Custom matched status code", response=self.response)

            rdata = self.parse_source(source_text, page_format, parser)

        ##
        # Exceptions from Selenium
        ##
        # Nothing yet

        ##
        # Exceptions from Requests
        ##
        except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as e:
            """
            Try again with a new profile (do not get new apikey)
            Wait n seconds before trying again
            """
            e_name = type(e).__name__
            if num_tries < self._num_retries and retry_enabled is True:
                logger.info("{} [get_site]: try #{} on {} Error {}".format(e_name, num_tries, url, e))
                time.sleep(2)
                self.new_profile()
                return self.get_site(*get_site_args, **get_site_kwargs)

            else:
                logger.error("{} [get_site]: try #{} on{}".format(e_name, num_tries, url))

        except requests.exceptions.TooManyRedirects as e:
            logger.exception("TooManyRedirects [get_site]: {}".format(url))

        ##
        # Exceptions shared by Selenium and Requests
        ##
        except (requests.exceptions.HTTPError, SeleniumHTTPError) as e:
            """
            Check the status code returned to see what should be done
            """
            status_code = str(e.response.status_code)
            # If the client wants to handle the error send it to them
            if int(status_code) in return_on_error:
                raise e.with_traceback(sys.exc_info()[2])

            try_again = self._get_site_status_code(url, status_code, api, num_tries, num_apikey_tries)
            if try_again is True and retry_enabled is True:
                # If True then try request again
                return self.get_site(*get_site_args, **get_site_kwargs)

        # Every other exceptions that were not caught
        except Exception:
            logger.exception("Unknown Exception [get_site]: {url}".format(url=url))

        return rdata