Exemple #1
0
class HTTPRequest:

    def __init__(self):
        self.session = Session()

    def request_with_cookie(self,method,url,**kwargs):
        logger.info("正在以 {} 方式 请求 {},参数是 {} ".format(method,url,kwargs))
        return self.session.request(method=method,url=url,**kwargs)


    def upload(self, url, token, account_id, use_type, file_name="1.jpg", **kwargs):
        file_path = os.path.join(DOCS_DIR, file_name)
        # 因为后端采用的是 multipart/form-data方式,其中有 内容分隔符(boundary), 原生request不支持此方式
        file = {"file": ("1.jpg", open(file_path, "rb"), "multipart/form-data"), "use_type": use_type}
        #file = {"upload": ("1.jpg", open(file_path, "rb"), "multipart/form-data"), "type": use_type}
        file = MultipartEncoder(fields=file)
        #headers = {"Content-Type": file.content_type, "token": token}
        #print(headers)
        headers = {"Content-Type": file.content_type, "token": token, "account_id": account_id}
        response = self.session.request("post", url=url, headers=headers, data=file, **kwargs)
        print(file)# 因为转化过了 所以不能用files
        logger.info("正在请求上传文件 URL:{}, file_name:{}".format(url, file_name))
        return response

    #用于在测试类结束的时候,关闭seesion
    def session_close(self):
        self.session.close()
Exemple #2
0
class HttpRequest:
    def __init__(self):
        self.session = Session()

    def __del__(self):
        self.session.close()

    def request(self, method, url, data=None, params=None, json=None, headers=None, cookies=None, timeout=None):
        if method.lower() == 'get':
            my_log.info(f'Sending {method}:{url} {params}')
            res = self.session.get(url=url, params=params, headers=headers, cookies=cookies, timeout=timeout)
        elif method.lower() == 'post':
            if json:
                my_log.info(f'Sending {method}:{url} {json}')
                res = self.session.post(url=url, json=json, headers=headers, cookies=cookies, timeout=timeout)
            else:
                my_log.info(f'Sending {method}:{url} {data}')
                res = self.session.post(url=url, data=data, headers=headers, cookies=cookies, timeout=timeout)
        else:
            res = None
        if res.status_code == 404:
            my_log.error(f'404 not found!')
            raise RuntimeError
        return res.text

    def close(self):
        self.session.close()
Exemple #3
0
class HTTPRequest2(object):
    """记录cookies信息给下一次请求使用"""

    def __init__(self):
        # 创建session对象
        self.session = Session()

    def request(self, method, url,
                params=None, data=None,
                headers=None, cookies=None, json=None):

        method = method.lower()
        if method == "post":
            # 判断是否使用json来传参(适用于接口项目有使用json传参)
            if json:
                logging.info("正在发送请求,请求地址:{}, 请求参数:{}".format(url, json))
                return self.session.post(url=url, json=json, headers=headers, cookies=cookies)
            else:
                logging.info("正在发送请求,请求地址:{}, 请求参数:{}".format(url, data))
                return self.session.post(url=url, data=data, headers=headers, cookies=cookies)
        elif method == "get":
            logging.info("正在发送请求,请求地址:{}, 请求参数:{}".format(url, params))
            return self.session.get(url=url, params=params, headers=headers, cookies=cookies)

    def close(self):
        self.session.close()
Exemple #4
0
def is_session(s: Session, member_id: int) -> Session:
    url = 'http://canvas.tongji.edu.cn/api/v1/planner/items?per_page=50&start_date=' + \
        datetime.now().strftime('%Y-%m-%d')
    r = s.get(url)
    data = json.loads(r.text.replace('while(1);', ''))
    if 'error' in data or r.status_code == 401:
        print("检测到canvas登录状态丢失,现尝试重新登录canvas")
        s.close()
        s = createlink(member_id)
    return s
class HttpClient:
    """ 使用requests库封装的高可靠 Http client

    :param max_connect_retries: The maximum number of retries each connection
        should attempt.Note, this applies only to failed DNS lookups, socket
        connections and connection timeouts, never to requests where data has
        made it to the server.
    :param max_request_tries: The maximum times of tries each request
        should attempt.
    """
    def __init__(self, max_connect_retries=0, max_request_tries=0):

        self.timeout = DEFAULT_TIMOUT
        self.max_connect_retries = (max_connect_retries
                                    or DEFAULT_CONNECT_RETRIES)
        self.max_request_tries = max_request_tries or DEFAULT_REQUEST_TRIES
        self.session = Session()
        retries = Retry(connect=2, read=2, status=2, redirect=2)
        self.session.mount('https://', HTTPAdapter(max_retries=retries))
        self.session.mount('http://', HTTPAdapter(max_retries=retries))

    def get(self, url, content_type='json', max_request_times=0, timeout=0):
        max_times = max_request_times or self.max_request_tries
        has_request_times = 0
        data = None

        while has_request_times < max_times:
            try:
                res = self.session.get(url, timeout=timeout or self.timeout)
                data = res.json() if content_type == 'json' else res.text
                if not data:
                    has_request_times = has_request_times + 1
                    continue
                else:
                    break
            except requests.exceptions.ConnectionError as e:
                print("socket连接错误或读取超时", e.__class__)
                break
            except Exception:
                # raise
                has_request_times = has_request_times + 1
                continue
        if not data:
            print("尝试了{}次请求依然失败".format(has_request_times + 1))
        else:
            print("尝试了{}次请求成功".format(has_request_times + 1))

        self.session.close()
        return data

    def post(self, url):
        pass
Exemple #6
0
class HTTPRequest(object):
    def __init__(self):
        # 创建session对象
        self.session = Session()

    # 记录cookies信息,给下一次请求使用
    def request(self,
                method,
                url,
                params=None,
                data=None,
                headers=None,
                cookies=None,
                json=None):
        # 将方法名转化为小写
        method = method.lower()
        if method == "post":
            # 判断是否使用json来传参,适用于接口项目使用json传参
            if json:
                logging.info("正在发送请求,请求地址:{},请求参数:{}".format(url, json))
                response = self.session.post(url=url,
                                             json=json,
                                             headers=headers,
                                             cookies=cookies)
                return response
            else:
                logging.info("正在发送请求,请求地址:{},请求参数:{}".format(url, data))
                response = self.session.post(url=url,
                                             data=data,
                                             headers=headers,
                                             cookies=cookies)
                return response
        elif method == "get":
            logging.info("正在发送请求,请求地址:{},请求参数:{}".format(url, params))
            response = self.session.get(url=url,
                                        params=params,
                                        headers=headers,
                                        cookies=cookies)
            return response
        elif method == "put":
            logging.info("正在发送请求,请求地址:{},请求参数:{}".format(url, data))
            response = self.session.put(url=url,
                                        data=data,
                                        headers=headers,
                                        cookies=cookies)
            return response

    def close(self):
        self.session.close()
Exemple #7
0
    def downloadEp(self, ep_id: int, path: str):
        "下载一个章节"
        if not os.path.exists(path):
            os.mkdir(path)

        _s = Session()
        _list = self.getDownloadList(ep_id)
        for ii in range(len(_list)):
            try:
                with open(os.path.join(path, f'{ii+1:0>2}.jpg'), 'wb') as f:
                    f.write(_s.get(_list[ii]).content)
            except Exception as e:
                print(f'在{path}下写入{ii+1:0>2}.jpg时异常', repr(e))

        _s.close()
Exemple #8
0
class MySession:
    def __init__(self, cfg: DictConfig):
        self.cfg = cfg

    def __enter__(self) -> Session:
        auth = get_latest(self.cfg, ['token_type', 'access_token'])
        HEADER = {
            'Authorization': f'{auth["token_type"]} {auth["access_token"]}'
        }
        self.session = Session()
        self.session.headers.update(HEADER)
        return self.session

    def __exit__(self, exc_type, exc_val, exc_tb) -> None:
        self.session.close()
Exemple #9
0
class BdXhsApi(object):
    def __init__(self,
                 host=XHS_BASE_HOST,
                 prefix="fe_api/burdock/baidu/v2/",
                 scheme="https"):
        self._host = host
        self._prefix = prefix
        self._base_url = "{}://{}/{}".format(scheme, host, prefix)

        self._session = Session()
        ui = random.randint(0, len(USER_AGENTS) - 1)
        headers = {
            "User-Agent": USER_AGENTS[ui],
            "Host": self._host,
            "Connection": "close",
            "Content-Type": "application/json",
            "Accept-Language": "zh-cn"
        }
        self._session.headers.update(headers)
        self._session.keep_alive = False

    def _get(self, route, sign_code, retry=1):
        url = urljoin(self._base_url, route)
        headers = {"X-Sign": "X{}".format(sign_code)}
        try:
            ret = self._session.get(url, headers=headers, timeout=(2, 5))
            LOG.info("GET {} {}".format(ret.url, ret.status_code))
        except (requests.exceptions.ConnectTimeout,
                requests.exceptions.ConnectionError) as e:
            LOG.error(e)
            return None

        error = ret.text
        import pdb
        pdb.set_trace()
        if 200 <= ret.status_code < 300:
            data = ret.json()
            code = data.get("code")
            if code == 0:
                return data["data"]
        if retry:
            return self._get(route, sign_code, retry - 1)
        raise Exception('Error url:{} -{}'.format(url, error))

    def get_homefeed_categories(self):
        route = "homefeed/categories"
        sign_code = "144fc3e8f0039f6fdf80d42152805e2d"
        result = self._get(route, sign_code=sign_code)
        return result

    def get_search_tending(self):
        route = "search/trending"
        sign_code = "1d2bce3df0a71e0b906c0ef74a7637ab"
        result = self._get(route, sign_code=sign_code)
        return result

    def close(self):
        return self._session.close()
Exemple #10
0
def sxyprn_download(session: Session, logger: Logger):
    """
    This does the downloads
    :param session:
    :param logger:
    :return:
    """
    url_parsed = urllib.parse.urlparse(ConfigUrl.url)
    # noinspection PyProtectedMember
    base_url = url_parsed._replace(path="", params="", query="",
                                   fragment="").geturl()

    num_pages = None
    counter = 0
    urls = UrlSet()
    for url in url_generator(url=ConfigUrl.url):
        logger.info(f"loading [{url}]")
        response = session_get(session=session, url=url)
        response.raise_for_status()
        root = get_html_dom_content(response)
        if num_pages is None:
            num_pages = len(root.xpath("//div[contains(@class,'ctrl_el')]"))
            if num_pages == 0:
                num_pages = 1
        if ConfigDebugUrls.save:
            with tempfile.NamedTemporaryFile(delete=False) as f:
                logger.info(f"writing file [{f.name}]")
                f.write(get_element_as_bytes(root))
        elements = root.xpath("//a[contains(@class,'js-pop')]")
        for element in elements:
            href = element.attrib["href"]
            url = urllib.parse.urljoin(base_url, href)
            no_fluff = urllib.parse.urlparse(url)._replace(
                params="", query="", fragment="").geturl()
            urls.append(no_fluff)
        counter += 1
        if counter == num_pages:
            break
    session.close()
    logger.info(f"got total [{len(urls.urls_list)}] urls")
    logger.info(f"got [{urls.appended_twice}] appended twice urls")
    youtube_dl_download_urls(urls.urls_list)
Exemple #11
0
class PortalConnection(object):
    """
    Connection to HubSpot

    :param authentication_key: This can be either an :class:`APIKey` or an \
            :class:`OAuthKey` instance
    :param basestring change_source: The string passed to HubSpot as \
            ``auditId`` in the query string
    """
    _API_URL = 'https://api.hubapi.com'

    def __init__(self, authentication_key, change_source):
        super(PortalConnection, self).__init__()

        self._authentication_handler = \
            _QueryStringAuthenticationHandler(authentication_key)
        self._change_source = change_source

        self._session = Session()
        self._session.headers['User-Agent'] = _USER_AGENT

        http_adapter = HTTPAdapter(max_retries=_HTTP_CONNECTION_MAX_RETRIES)
        self._session.mount('', http_adapter)

    def send_get_request(self, url_path, query_string_args=None):
        """
        Send a GET request to HubSpot

        :param basestring url_path: The URL path to the endpoint
        :param dict query_string_args: The query string arguments

        :return: Decoded version of the ``JSON`` that HubSpot put in \
                the body of the response.

        """
        return self._send_request('GET', url_path, query_string_args)

    def send_post_request(self, url_path, body_deserialization):
        """
        Send a POST request to HubSpot

        :param basestring url_path: The URL path to the endpoint
        :param dict body_deserialization: The request's body message \
            deserialized

        :return: Decoded version of the ``JSON`` that HubSpot put in \
                the body of the response.
        """
        return self._send_request(
            'POST',
            url_path,
            body_deserialization=body_deserialization,
        )

    def send_put_request(self, url_path, body_deserialization):
        """
        Send a PUT request to HubSpot

        :param basestring url_path: The URL path to the endpoint
        :param body_deserialization: The request's body message deserialized

        :return: Decoded version of the ``JSON`` that HubSpot put in \
                the body of the response.
        """
        return self._send_request(
            'PUT',
            url_path,
            body_deserialization=body_deserialization,
        )

    def send_delete_request(self, url_path):
        """
        Send a DELETE request to HubSpot

        :param basestring url_path: The URL path to the endpoint

        :return: Decoded version of the ``JSON`` that HubSpot put in \
                the body of the response.
        """
        return self._send_request('DELETE', url_path)

    def _send_request(
        self,
        method,
        url_path,
        query_string_args=None,
        body_deserialization=None,
    ):
        url = self._API_URL + url_path

        query_string_args = query_string_args or {}
        query_string_args = dict(query_string_args,
                                 auditId=self._change_source)

        request_headers = \
            {'content-type': 'application/json'} if body_deserialization else {}

        if body_deserialization:
            request_body_serialization = json_serialize(body_deserialization)
        else:
            request_body_serialization = None

        response = self._session.request(
            method,
            url,
            params=query_string_args,
            auth=self._authentication_handler,
            data=request_body_serialization,
            headers=request_headers,
        )

        response_body_deserialization = \
            self._deserialize_response_body(response)
        return response_body_deserialization

    @classmethod
    def _deserialize_response_body(cls, response):
        cls._require_successful_response(response)

        if response.status_code == HTTP_STATUS_OK:
            cls._require_json_response(response)
            response_body_deserialization = response.json() or None
        elif response.status_code in _HTTP_STATUS_CODES_WITH_EMPTY_BODIES:
            response_body_deserialization = None
        else:
            exception_message = \
                'Unsupported response status {}'.format(response.status_code)
            raise HubspotUnsupportedResponseError(exception_message)

        return response_body_deserialization

    @staticmethod
    def _require_successful_response(response):
        if 400 <= response.status_code < 500:
            response_data = response.json()
            error_data = _HUBSPOT_ERROR_RESPONSE_SCHEMA(response_data)

            if response.status_code == HTTP_STATUS_UNAUTHORIZED:
                exception_class = HubspotAuthenticationError
            else:
                exception_class = HubspotClientError
            raise exception_class(
                error_data['message'],
                error_data['requestId'],
            )
        elif 500 <= response.status_code < 600:
            raise HubspotServerError(response.reason, response.status_code)

    @staticmethod
    def _require_json_response(response):
        content_type_header_value = response.headers.get('Content-Type')
        if not content_type_header_value:
            exception_message = 'Response does not specify a Content-Type'
            raise HubspotUnsupportedResponseError(exception_message)

        content_type = content_type_header_value.split(';')[0].lower()
        if content_type != 'application/json':
            exception_message = \
                'Unsupported response content type {}'.format(content_type)
            raise HubspotUnsupportedResponseError(exception_message)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        self._session.close()
class Client(object):
    def __init__(self, api_url='', sugar_auth=False, **kwargs):
        self.api_url = api_url
        self.params = kwargs
        self._sugar_auth = sugar_auth

        verify = True
        if client.no_check_certificate.value:
            verify = False
        elif client.certfile.value:
            verify = client.certfile.value

        headers = {'Accept-Language': ad.default_lang()}
        if self._sugar_auth:
            privkey_path = sugar.privkey_path()
            if not exists(privkey_path):
                _logger.warning('Sugar session was never started, '
                                'fallback to anonymous mode')
                self._sugar_auth = False
            else:
                uid = sugar.uid()
                headers['sugar_user'] = uid
                headers['sugar_user_signature'] = _sign(privkey_path, uid)

        self._session = Session(headers=headers, verify=verify, prefetch=False)

    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.close()

    def close(self):
        self._session.close()

    def exists(self, path):
        response = self.request('GET', path, allowed=[404])
        return response.status_code != 404

    def get(self, path_=None, **kwargs):
        response = self.request('GET', path_, params=kwargs)
        return self._decode_reply(response)

    def post(self, path_=None, data_=None, **kwargs):
        response = self.request('POST',
                                path_,
                                json.dumps(data_),
                                headers={'Content-Type': 'application/json'},
                                params=kwargs)
        return self._decode_reply(response)

    def put(self, path_=None, data_=None, **kwargs):
        response = self.request('PUT',
                                path_,
                                json.dumps(data_),
                                headers={'Content-Type': 'application/json'},
                                params=kwargs)
        return self._decode_reply(response)

    def delete(self, path_=None, **kwargs):
        response = self.request('DELETE', path_, params=kwargs)
        return self._decode_reply(response)

    def request(self,
                method,
                path=None,
                data=None,
                headers=None,
                allowed=None,
                params=None,
                **kwargs):
        if not path:
            path = ['']
        if not isinstance(path, basestring):
            path = '/'.join([i.strip('/') for i in [self.api_url] + path])

        if params is None:
            params = self.params
        else:
            params.update(self.params)

        while True:
            try:
                response = requests.request(method,
                                            path,
                                            data=data,
                                            headers=headers,
                                            session=self._session,
                                            params=params,
                                            **kwargs)
            except requests.exceptions.SSLError:
                _logger.warning('Use --no-check-certificate to avoid checks')
                raise

            if response.status_code != 200:
                if response.status_code == 401:
                    enforce(self._sugar_auth,
                            'Operation is not available in anonymous mode')
                    _logger.info('User is not registered on the server, '
                                 'registering')
                    self._register()
                    continue
                if allowed and response.status_code in allowed:
                    return response
                content = response.content
                try:
                    error = json.loads(content)
                except Exception:
                    _logger.debug('Got %s HTTP error for %r request:\n%s',
                                  response.status_code, path, content)
                    response.raise_for_status()
                else:
                    raise RuntimeError(error['error'])

            return response

    def call(self, request, response=None):
        params = request.copy()
        method = params.pop('method')
        document = params.pop('document') if 'document' in params else None
        guid = params.pop('guid') if 'guid' in params else None
        prop = params.pop('prop') if 'prop' in params else None

        path = []
        if document:
            path.append(document)
        if guid:
            path.append(guid)
        if prop:
            path.append(prop)

        if request.content_type == 'application/json':
            request.content = json.dumps(request.content)

        headers = None
        if request.content is not None:
            headers = {}
            headers['Content-Type'] = \
                    request.content_type or 'application/octet-stream'
            headers['Content-Length'] = str(len(request.content))
        elif request.content_stream is not None:
            headers = {}
            headers['Content-Type'] = \
                    request.content_type or 'application/octet-stream'
            # TODO Avoid reading the full content at once
            request.content = request.content_stream.read()
            headers['Content-Length'] = str(len(request.content))

        reply = self.request(method,
                             path,
                             data=request.content,
                             params=params,
                             headers=headers,
                             allowed=[303],
                             allow_redirects=request.allow_redirects)

        if reply.status_code == 303:
            raise Redirect(reply.headers['Location'])

        if response is not None:
            if 'Content-Disposition' in reply.headers:
                response['Content-Disposition'] = \
                        reply.headers['Content-Disposition']
            if 'Content-Type' in reply.headers:
                response.content_type = reply.headers['Content-Type']

        result = self._decode_reply(reply)
        if result is None:
            result = reply.raw
        return result

    def subscribe(self):
        return _Subscription(self, _RECONNECTION_NUMBER)

    def _register(self):
        self.post(
            ['user'], {
                'name': sugar.nickname() or '',
                'color': sugar.color() or '#000000,#000000',
                'machine_sn': sugar.machine_sn() or '',
                'machine_uuid': sugar.machine_uuid() or '',
                'pubkey': sugar.pubkey(),
            })

    def _decode_reply(self, response):
        if response.headers.get('Content-Type') == 'application/json':
            return json.loads(response.content)
        else:
            return response.content
Exemple #13
0
class Spider:
    # todo 针对每次请求不同的`header`来重新加载缓存
    # todo 增加字段`data`,存`post`字段
    # todo 增加字段`header`, 存header

    # 强制使用缓存
    FORCE_CACHE = 2
    # 运行使用缓存
    ENABLE_CACHE = 1
    # 不使用缓存
    DISABLE_CACHE = 0

    cache: CacheBase
    session: Session
    headers_generator: T_Headers_Generator
    sleeper: T_Sleeper
    request_middlewares: List[RequestMiddlewareBase]
    response_middlewares: List[ResponseMiddlewareBase]
    proxy_pool: Optional[ProxyPoolBase]
    __encoding: str

    cache_mode: Literal[0, 1, 2]
    timeout: Tuple[int, int]
    alive_time: int
    retry: int

    def __init__(
        self,
        cache: Optional[CacheBase] = None,
        session: Optional[Session] = None,
        headers_generator: Optional[T_Headers_Generator] = None,
        sleeper: Optional[T_Sleeper] = None,
        request_middlewares: Optional[List[RequestMiddlewareBase]] = None,
        response_middlewares: Optional[List[ResponseMiddlewareBase]] = None,
        proxy_pool: Optional[ProxyPoolBase] = None,
        __encoding: Optional[str] = None,
        cache_mode: Optional[Literal[0, 1, 2]] = None,
        timeout: Optional[Tuple[int, int]] = None,
        alive_time: Optional[int] = None,
        retry: Optional[int] = None,
    ):
        self.cache = cache or NoCache()
        if not session:
            self.session = Session()
        self.sleeper = sleeper or NoSleeper()
        self.request_middlewares = request_middlewares or []
        self.response_middlewares = response_middlewares or []
        self.proxy_pool = proxy_pool
        self.__encoding = __encoding
        # todo
        self.headers_generator = headers_generator or get_random_header

        self.cache_mode = cache_mode or Spider.DISABLE_CACHE
        self.timeout = timeout or (5, 5)
        self.alive_time = alive_time or 3
        self.retry = retry or 3

        self.update_headers()

    @classmethod
    def get_cache_spider(cls) -> 'Spider':
        spider = cls(SqliteCache())
        spider.cache_mode = Spider.ENABLE_CACHE
        return spider

    def set_sleeper(self, sleeper: T_Sleeper):
        if not isinstance(sleeper, Callable):
            raise RuntimeError('参数必须是Callable')
        self.sleeper = sleeper

    def set_random_sleeper(self, a=5, b=10):
        self.set_sleeper(RandomTimeSleeper(a, b))

    def set_sep_sleeper(self, sep_time=10):
        self.set_sleeper(SepTimeSleeper(sep_time))

    @property
    def encoding(self):
        return self.__encoding

    @encoding.setter
    def encoding(self, encoding):
        self.__encoding = encoding

    def set_cookie(self, cookie: str):
        """设置cookie

        :param cookie: 一个 `cookie` 字符串
        """
        cookie = {'Cookie': cookie}
        self.session.cookies = requests.sessions.cookiejar_from_dict(
            cookie, cookiejar=None, overwrite=True)

    def add_request_middlewares(
        self, request_middlewares: Union[RequestMiddlewareBase,
                                         List[RequestMiddlewareBase]]):
        if isinstance(request_middlewares, list):
            self.request_middlewares.extend(request_middlewares)
        else:
            self.request_middlewares.append(request_middlewares)

    def add_response_middlewares(
        self, response_middlewares: Union[ResponseMiddlewareBase,
                                          List[ResponseMiddlewareBase]]):
        if isinstance(response_middlewares, list):
            self.response_middlewares.extend(response_middlewares)
        else:
            self.response_middlewares.append(response_middlewares)

    def remove_request_middlewares(self, request_middlewares):
        del self.request_middlewares[request_middlewares]

    def remove_response_middlewares(self, response_middlewares):
        del self.response_middlewares[response_middlewares]

    def get_response(self,
                     req: PreparedRequest,
                     timeout=None,
                     allow_redirects=True,
                     cache_mode=None,
                     alive_time=None,
                     retry=None):
        """低级 api 发送请求, 在这里进行 request_middleware, response_middleware 的处理"""

        cache_mode = cache_mode or self.cache_mode
        alive_time = alive_time or self.alive_time
        timeout = timeout or self.timeout
        retry = retry or self.retry

        cache_signal = req.url

        if cache_mode == Spider.DISABLE_CACHE:
            # 如果禁用这个url的缓存, 则将之从缓存文件删除
            self.cache.clear_cache(cache_signal)

        # 如果 `is_force_cache` is True 则, 不论缓存是否过期, 都从缓存加载
        elif cache_mode == Spider.FORCE_CACHE and self.cache.is_cached(
                cache_signal, ignore_date=True):
            logger.debug('从缓存: {} <- {}', limit_text(req.url, 100), self.cache)
            response = self.cache.from_cache(cache_signal, force=True)
            if self.encoding:
                response.encoding = self.encoding
            return response

        elif cache_mode == Spider.ENABLE_CACHE and self.cache.is_cached(
                cache_signal, ignore_date=False):
            logger.debug('从缓存: {} <- {}', limit_text(cache_signal, 100),
                         self.cache)
            response = self.cache.from_cache(cache_signal, force=False)
            if self.encoding:
                response.encoding = self.encoding
            return response

        retry = retry
        while retry:
            try:
                # 间隔时间
                response = self.session.send(req,
                                             timeout=timeout or (5, 5),
                                             allow_redirects=allow_redirects)
                if self.encoding:
                    response.encoding = self.encoding
                response = Response(response)

                self.sleeper()

                if len(response.response.history) >= 1:
                    history = [each.url for each in response.response.history]
                    history.append(response.url)
                    logger.debug(
                        '页面重定向: {}',
                        '->'.join(['[{}]'.format(i) for i in history]))
                if response.response.ok:
                    if cache_mode == Spider.ENABLE_CACHE:
                        self.cache.cache(response.url, response, alive_time)
                else:
                    raise HTTPBadCodeError(f'坏HTTP响应', response)
                return response

            except requests.Timeout as e:
                if retry == 1:
                    raise e
                logger.debug('超时,重试---{}'.format(str(4 - retry)))
            except requests.RequestException as e:
                if retry == 1:
                    logger.error('取消重试---{}'.format(str(4 - retry)))
                    raise e
                logger.error('HTTP报错---{}'.format(str(4 - retry)))
                # todo 对于失败的`url`保存到另一个`log`文件
            except HTTPBadCodeError as e:
                if retry == 1:
                    logger.info('坏HTTP响应, 取消重试({})'.format(
                        e.args[1].status_code))
                    return e.args[1]
                logger.debug('坏HTTP响应({})---{}', e.args[1].status_code,
                             4 - retry)
            finally:
                retry -= 1

    def lunch(self,
              method,
              url,
              *,
              cache_mode=None,
              alive_time=None,
              timeout=None,
              retry=None,
              headers=None,
              data=None,
              params=None,
              cookies=None,
              hooks=None):
        """高级 api 发送请求, 处理网页缓存等功能"""
        # 发送请求
        req = requests.Request(
            method=method.upper(),
            url=url,
            headers=headers,
            files=None,
            data=data or {},
            json=None,
            params=params or {},
            auth=None,
            cookies=cookies,
            hooks=hooks,
        )
        req = self.session.prepare_request(req)
        for request_middleware in self.request_middlewares:
            req = request_middleware(self, req)

        resp = self.get_response(req,
                                 cache_mode=cache_mode,
                                 alive_time=alive_time,
                                 timeout=timeout,
                                 retry=retry)

        for response_middleware in self.response_middlewares:
            resp = response_middleware(self, resp)
        return resp

    def get(self, *args, **kwargs) -> [Response, requests.Response, object]:
        """获取网页

        :param args: (元组)`url`的各个路径:
        :param kwargs: 包含`requests`库所有选项
        :keyword alive_time: Union[datetime, int]缓存存活日期
        :keyword cache: 是否使用缓存
        :keyword sep_time: 间隔时间

        :return: Union[Response, requests.Response, object]
        """
        # 获取`alive_time`, `url`参数
        resp = self.lunch('get', *args, **kwargs)
        return resp

    def post(self, *args, **kwargs) -> Response:
        """获取网页

        :param args: (元组)`url`的各个路径:
        :param kwargs: 包含`requests`库所有选项
        :keyword alive_time: Union[datetime, int]缓存存活日期
        :keyword cache: 是否使用缓存
        :keyword sep_time: 间隔时间

        :return: Union[Response, requests.Response, object]
        """
        resp = self.lunch('post', *args, **kwargs)
        return resp

    def update_headers(self):
        """调用`self.headers_generator`来更新头"""
        self.session.headers.update(self.headers_generator())

    def close(self):
        self.session.close()
Exemple #14
0
class Porter:
    DEFAULTS_PATH = "default_settings/"

    def __init__(self, user="", password="", host="http://rocketchat:3000", destination="settings.json"):
        self.username = os.environ.get('API_USER', user)
        self.password = os.environ.get('API_PASS', password)
        self.host = os.environ.get('API_HOST', host)
        self.destination = os.environ.get('SETTINGS_PATH', destination)

        self.session = Session()

        self._wait_for_rocketchat()

    def _wait_for_rocketchat(self, rocket=None):
        self.rocket = rocket
        timeout = 60
        logger.info("starting to wait for rocketchat...")
        while timeout:
            time.sleep(1)
            try:
                if self.rocket is None:
                    self.rocket = RocketChat(self.username, self.password, server_url=self.host, session=self.session)
                ret = self.rocket.info().json()
                if ret.get('success'):
                    logger.info("rocketchat available!")
                    return
            except ConnectionError:
                pass
            except:
                pass
            timeout =- 1
        logger.error("Timeout while waiting for rocketchat!")
        

    def import_settings(self):
        with open(self.destination, 'r') as f:
            settings_to_import = json.load(f)

        logger.info(f"Importing {len(settings_to_import)} settings...")
        self._import(settings_to_import)
        logger.info("Finished importing settings!")

    def _import(self, settings):
        import_oauth = {}

        for _id, value in settings.items():
            if _id.startswith("Accounts_OAuth_Custom-"):
                custom_name = _id.split('-')
                if len(custom_name) == 2:
                    import_oauth[custom_name[1]] = True
                continue
            self.rocket.settings_update(_id, value)

        if import_oauth:
            # create all neccessary OAuth services
            for i, oauth_service_name in enumerate(import_oauth.keys()):
                logger.debug(f'create {oauth_service_name}')
                json_ = json.dumps({'msg': 'method', 'method': 'addOAuthService', 'params': [oauth_service_name], 'id': 1337+i})
                self.rocket.call_api_post("method.call/addOAuthService", message=json_)

            for _id, value in settings.items():
                if _id.startswith("Accounts_OAuth_Custom-"):
                    self.rocket.settings_update(_id, value)
         

    def _export(self):
        data = self.rocket.settings().json()
        settings = {sett_.get('_id'): sett_.get('value') for sett_ in data.get('settings', [])}
        if not settings:
            logger.error('Nothing returned from server, just "{}"!'.format(data))
            return {}

        api_default_count = settings.get('API_Default_Count', 50)

        # Get remaining
        for call in range(1, int(data.get('total', 1) / api_default_count)+1):
            data = self.rocket.settings(count=api_default_count, offset=call*api_default_count).json()
            for sett_ in data.get('settings', []):
                settings[sett_.get('_id')] =  sett_.get('value')

        return settings

    def export_changed(self):
        logger.info("Exporting all non-default settings...")
        version = self.rocket.info().json().get('info', {}).get('version', 0)
        if not version:
            logger.error('Could not get server version!')
            return

        try:
            with open(os.path.join(self.DEFAULTS_PATH, '{}.json'.format(version)), 'r') as f:
                settings_defaults = json.load(f)
        except FileNotFoundError:
            logger.error('No defaults for version {} found in the directory {}!'.format(version, self.DEFAULTS_PATH))
            return

        settings = self._export()

        settings_updated = {}
        for setting_id, setting_value in settings.items():
            if setting_id not in settings_defaults or setting_value != settings_defaults.get(setting_id):
                settings_updated[setting_id] = setting_value

        with open(self.destination, 'w') as f:
            json.dump(settings_updated, f)
        logger.info(f"Finished exporting {len(settings_updated)} updated settings")

    def export_all(self):
        logger.info("Exporting all settings...")
        settings = self._export()
        with open(self.destination, 'w') as f:
            json.dump(settings, f)
        logger.info(f"Finished exporting {len(settings)} settings")

    def close(self):
        self.session.close()
Exemple #15
0
class StrainRegistry:

    # Folder Collections
    FEATURED = "FEATURED"
    PERSONAL = "PERSONAL"
    SHARED = "SHARED"
    # don't care about SAMPLES, PENDING, or DRAFTS
    ALL_COLLECTIONS = (FEATURED, PERSONAL, SHARED)

    def __init__(self):
        self.auth = None
        self.session = None

    def __enter__(self):
        self.session = Session()
        self.session.auth = self.auth

    def __exit__(self, exc_type, exc_value, exc_traceback):
        self.session.close()
        self.session = None

    def build_entry_url(self, entry_id):
        return self._rest(f"parts/{entry_id}")

    def build_folder_url(self, folder_id):
        return self._rest(f"folders/{folder_id}")

    def create_folder(self, folder_name):
        self._check_session()
        try:
            response = self.session.post(
                self._rest("folders"),
                json={"folderName": folder_name},
            )
            response.raise_for_status()
            return Folder(self, response.json())
        except Exception as e:
            raise RegistryError("Could not create folder") from e

    def get_entry(self, entry_id):
        self._check_session()
        try:
            response = self.session.get(self.build_entry_url(entry_id))
            response.raise_for_status()
            return Entry(self, response.json())
        except Exception as e:
            raise RegistryError("Could not load Registry Entry") from e

    def get_folder(self, folder_id):
        self._check_session()
        try:
            response = self.session.get(self.build_folder_url(folder_id))
            response.raise_for_status()
            return Folder(self, response.json())
        except Exception as e:
            raise RegistryError("Could not load Registry Folder") from e

    def iter_entries(self, collection="available", **extra):
        self._check_session()

        def entries_api(start):
            response = self.session.get(
                self._rest(f"collections/{collection}/entries"),
                params={
                    "start": start,
                    **extra
                },
            )
            response.raise_for_status()
            raw_results = response.json()["data"]
            return [Entry(self, item) for item in raw_results]

        try:
            yield from self._yield_paged_records(entries_api)
        except Exception as e:
            raise RegistryError("Could not iterate Registry Entries") from e

    def list_entries(self, collection="available", **extra):
        self._check_session()
        try:
            response = self.session.get(
                self._rest(f"collections/{collection}/entries"),
                params=extra,
            )
            response.raise_for_status()
            return [Entry(self, item) for item in response.json()["data"]]
        except Exception as e:
            raise RegistryError("Could not list Registry Entries") from e

    def list_folders(self, collection="FEATURED"):
        self._check_session()
        try:
            # this endpoint does not support paging
            response = self.session.get(
                self._rest(f"collections/{collection}/folders"))
            response.raise_for_status()
            return [Folder(self, item) for item in response.json()]
        except Exception as e:
            raise RegistryError("Could not list Registry Folders") from e

    def login(self, user):
        if key_id := getattr(settings, "ICE_KEY_ID", None):
            self.auth = HmacAuth(key_id=key_id, username=user.email)
        return self
Exemple #16
0
def _remove_session(key: str, session: Session) -> None:
    session.close()
Exemple #17
0
class SessionState:
    def __init__(self, cache_file: Path, cache_key: str, redis: str, user_requested=False):
        self.user_requested = user_requested
        self._cache_file = cache_file
        self._cache_key = cache_key
        self._cache: Optional[SqliteDict] = None
        random.seed()
        self._session_key = random.randint(0, 999999)
        self._redis = Redis(host=redis)

        if not user_requested:
            self._open()
            if self._cache_key != self._cache.get("_cache_key_", None):
                self._cache.close()
                self._cache: Optional[SqliteDict] = None
                self._cache_file.unlink()
                self._open()
                self._cache["_cache_key_"] = self._cache_key

        self.session = Session()
        # noinspection PyTypeChecker
        self.session.mount(
            'https://',
            HTTPAdapter(max_retries=Retry(total=3, backoff_factor=0.1, status_forcelist=[500, 502, 503, 504])))
        self.sites = {}
        self.wikidata = Sparql()
        self.primary_site = self.get_site(primary_domain)

    def __enter__(self):
        return self

    def __exit__(self, typ, value, traceback):
        self.session.close()
        if self._cache is not None:
            self._cache.close()
            self._cache = None
            print(f'Closed SQL connection for {self._session_key} at {datetime.utcnow()}')

    def _open(self):
        if self._cache is None:
            print(f'Opening SQL connection for {self._session_key} at {datetime.utcnow()}')
            self._cache_file.parent.mkdir(parents=True, exist_ok=True)
            self._cache = SqliteDict(self._cache_file, autocommit=True)

    def get_site(self, domain: Domain) -> WikiSite:
        try:
            return self.sites[domain]
        except KeyError:
            # noinspection PyTypeChecker
            site = WikiSite(domain, self.session, domain == primary_domain)
            if self.user_requested:
                site.maxlag = None
            self.sites[domain] = site
            return site

    def delete_cached_items(self, prefix: str) -> None:
        self._open()
        for vv in {v for v in self._cache.keys() if v.startswith(prefix)}:
            del self._cache[vv]

    def del_obj(self, key: str) -> Any:
        self._redis.delete(self.redis_key(key))
        self._open()
        print(f"%% del {key}")
        return self._cache.pop(key, None)

    def load_obj(self, key: str, default: Any = None) -> Any:
        value = self._redis.get(self.redis_key(key))
        if value is not None:
            return loads(value)
        self._open()
        print(f"%% load {key}")
        value = self._cache.get(key, default)
        self._redis.set(self.redis_key(key), dumps(value))
        return value

    def save_obj(self, key: str, value: Any):
        self._open()
        print(f"%% save {key}")
        self._cache[key] = value
        self._redis.set(self.redis_key(key), dumps(value))

    def redis_key(self, key: str):
        return self._cache_key + key
Exemple #18
0
class WxXhsApi(object):
    def __init__(self, host=XHS_BASE_HOST, prefix="wx_mp_api/sns/v1/", scheme="https"):
        self._host = host
        self._prefix = prefix
        self._base_url = "{}://{}/{}".format(scheme, host, prefix)

        self._session = Session()
        ui = random.randint(0, len(USER_AGENTS) - 1)
        headers = {
            "User-Agent": USER_AGENTS[ui],
            "Host": self._host,
            "Connection": "close",
            "Accept-Encoding": "br, gzip, deflate",
            "Content-Type": "application/json",
            "Accept-Language": "zh-cn",
            "Device-Fingerprint":
                "WHJMrwNw1k/Gy/sC6Z1D0XzFNbmyE3cyfJCjTR5D+eJ4GPjHvuEU1skE1O3fkhMVWGWPZ3E6FqIOaBmFkRMqt6xFlRX"
                "tfTfVBdCW1tldyDzmauSxIJm5Txg==1487582755342",
            "Authorization": "ea521d9b-c1fb-4f91-8560-bfa160171e5a"
        }
        sid = "1572606846528931138054"
        self._sid = "session.{}".format(sid)
        self._session.headers.update(headers)
        self._session.keep_alive = False

    def _get(self, route, params=None, retry=1):
        url = urljoin(self._base_url, route)
        if params:
            params.update(sid=self._sid)

        try:
            ret = self._session.get(url, params=params, timeout=(5, 10))
            LOG.info("GET {} {}".format(ret.url, ret.status_code))
        except (requests.exceptions.ConnectTimeout, requests.exceptions.ConnectionError)as e:
            LOG.error(e)
            return None

        error = ret.text
        if 200 <= ret.status_code < 300:
            ret.encoding = 'utf-8'
            data = ret.json()
            success = data.get("success")
            if success:
                return data["data"]
            else:
                print("result:{}-{}".format(data.get("result"), data.get("msg")))
        if retry:
            return self._get(route, params, retry - 1)
        raise Exception('Error url:{} -{}'.format(url, error))

    # def get_homefeed_categories(self):
    #     route = "homefeed/categories"
    #     result = self._get(route)
    #     return result
    #
    # def get_search_tending(self):
    #     route = "search/trending"
    #     result = self._get(route)
    #     return result

    def search_notes(self, keyword, page=1, per_page=20, sort="general"):
        route = "search/notes"
        params = {
            "keyword": keyword,
            "page": page,
            "per_page": per_page,
            "sort": sort
        }
        result = self._get(route, params)
        return result

    def get_note_info_list(self, note_id):
        route = "note/{}/single_feed".format(note_id)
        result = self._get(route)
        return result

    def close(self):
        return self._session.close()
Exemple #19
0
class Client:
    def __init__(self, username, password, proxy):
        self.ses = Session()
        self.loggedIn = False
        self.username = username
        self.password = password
        self.proxy = proxy

    def Login(self):
        if self.loggedIn == True:
            return None

        loginData = {
            "password": self.password,
            "username": self.username,
            "queryParams": "{}"
        }
        homePageResponse = self.ses.get(
            "https://www.instagram.com/accounts/login/")
        loginHeaders = {
            "Accept": "*/*",
            "Accept-Encoding": "gzip,deflate,br",
            "Accept-Language": "en-US,en;q=0.5",
            "Connection": "keep-alive",
            "Content-Type": "application/x-www-form-urlencoded",
            "Host": "www.instagram.com",
            "Referer": "https://www.instagram.com/accounts/login/",
            "X-Requested-With": "XMLHttpRequest",
            "X-Instagram-AJAX": "1",
            "User-Agent": USER_AGENT,
            "X-CSRFToken": homePageResponse.cookies.get_dict()["csrftoken"],
        }
        loginCookies = {
            "rur": "PRN",
            "csrftoken": homePageResponse.cookies.get_dict()["csrftoken"],
            "mcd": homePageResponse.cookies.get_dict()["mcd"],
            "mid": homePageResponse.cookies.get_dict()["mid"]
        }
        self.ses.headers.update(loginHeaders)
        self.ses.cookies.update(loginCookies)

        loginPostResponse = self.ses.post(
            "https://www.instagram.com/accounts/login/ajax/", data=loginData)

        if loginPostResponse.status_code == 200 and loginPostResponse.json(
        )["authenticated"] == True:
            self.loggedIn = True
            mainPageResponse = self.ses.get("https://www.instagram.com/")
            self.ses.cookies.update(mainPageResponse.cookies)

    def Spam(self, username, userid):
        if self.loggedIn == False:
            return None

        link = "https://www.instagram.com/" + username + "/"
        profileGetResponse = self.ses.get(link)
        self.ses.cookies.update(profileGetResponse.cookies)
        spamHeaders = {
            "Accept": "*/*",
            "Accept-Encoding": "gzip,deflate,br",
            "Accept-Language": "en-US,en;q=0.5",
            "Connection": "keep-alive",
            "Content-Type": "application/x-www-form-urlencoded",
            "DNT": "1",
            "Host": "www.instagram.com",
            "X-Instagram-AJAX": "2",
            "X-Requested-With": "XMLHttpRequest",
            "Referer": link,
            "User-Agent": USER_AGENT,
            "X-CSRFToken": profileGetResponse.cookies.get_dict()["csrftoken"],
        }
        "Hichigo was here THT"
        spamData = {"reason_id": "1", "source_name": "profile"}

        self.ses.headers.update(spamHeaders)

        spamPostResponse = self.ses.post("https://www.instagram.com/users/" +
                                         userid + "/report/",
                                         data=spamData)
        if spamPostResponse.status_code == 200 and spamPostResponse.json(
        )["description"] == "Your reports help keep our community free of spam.":
            self.ses.close()
            return True
        else:
            return False
Exemple #20
0
class Api(object):
    session: Session
    job_type: JobType
    url: str

    def __init__(self,
                 job_type: JobType,
                 url: str,
                 api_key: str,
                 headers: Dict[str, str] = {}):
        self.session = Session()
        self.job_type = job_type
        self.url = self._normalize_url(url)

        self.session.headers.update({"X-Api-Key": api_key, **headers})

    def __enter__(self) -> Api:
        return self

    def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
        self.session.close()

    def _normalize_url(self, url: str) -> str:
        return url if url.endswith("/") else f"{url}/"

    def _response_json(self, response: Response, url: str) -> Any:
        if not response.ok:
            raise Exception(
                f"failed to check status for {url} got {response.status_code}")

        if not response.text:
            logger.error("%s response_text: %s", url, response.text)
            raise Exception(
                f"no response in status for {url}. Is the server set up correctly?"
            )

        return response.json()

    def get(self, url: str) -> Any:
        response = self.session.get(url=url)
        return self._response_json(response=response, url=url)

    def post(self, url: str, json: Dict[Any, Any]) -> Any:
        response = self.session.post(url=url, json=json)
        return self._response_json(response=response, url=url)

    def status(self) -> Status:
        full_url = routes.status(job_type=self.job_type, url=self.url)
        json = self.get(url=full_url)
        return Status.parse_obj(json)

    def profile(self) -> Profiles:
        full_url = routes.profile(job_type=self.job_type, url=self.url)
        json = self.get(url=full_url)
        return list(map(Profile.parse_obj, json))

    def tag(self) -> Tags:
        full_url = routes.tag(job_type=self.job_type, url=self.url)
        json = self.get(url=full_url)
        return list(map(Tag.parse_obj, json))

    def language(self) -> Languages:
        # Only Sonarr supports setting languageProfileId
        if self.job_type != JobType.Sonarr:
            return []

        full_url = routes.language(job_type=self.job_type, url=self.url)
        json = self.get(url=full_url)
        return list(map(Language.parse_obj, json))

    def metadata(self) -> Profiles:
        # Only Lidarr supports setting metadataProfileId
        if self.job_type != JobType.Lidarr:
            return []

        full_url = routes.metadata(job_type=self.job_type, url=self.url)
        json = self.get(url=full_url)
        return list(map(Profile.parse_obj, json))

    def content(self) -> ContentItems:
        full_url = routes.content(job_type=self.job_type, url=self.url)
        json = self.get(url=full_url)

        if self.job_type is JobType.Sonarr:
            return list(map(SonarrContent.parse_obj, json))
        elif self.job_type is JobType.Radarr:
            return list(map(RadarrContent.parse_obj, json))
        elif self.job_type is JobType.Lidarr:
            return list(map(LidarrContent.parse_obj, json))
        else:
            _assert_never(self.job_type)

    def save(self, content_item: ContentItem) -> Any:
        full_url = routes.content(job_type=self.job_type, url=self.url)
        return self.post(url=full_url, json=content_item.dict(by_alias=True))
Exemple #21
0
                ticketId, status, hardVersion, DeviceFac, Android, AppVersion,
                url_new, MobilePhone, picExist, Desc
            ]
            op_list = []
            for item in or_list:
                if "'" not in str(item):
                    op_list.append(str(item))
                    continue
                try:
                    op_list.append(re.search(":(.*)'", str(item)).group(1))
                except AttributeError:
                    op_list.append(re.search("'(.*)'", str(item)).group(1))

            # f.write(f"{url_new}\t{MobilePhone}\t{AppVersion}\t{Desc}\n")
            for i in range(op_list.__len__()):
                my_excel.w_data_origin(line, i + 1, op_list[i])

            line += 1
            end = datetime.datetime.now()
            print(ticketId, end - start)

my_session.close()
my_excel.close()
my_excel.save()

# #
# 前一位:
# ../div[@="class"]/preceding-sibling::div[1]
# 后一位:
# ../div[@="class"]/following-sibling::div[1]
Exemple #22
0
class Connection:

    _API_URL = 'https://www.2degreesnetwork.com/api'

    def __init__(self, auth, timeout=None, api_url=None):
        super(Connection, self).__init__()

        self._api_url = api_url or self._API_URL

        self._authentication_handler = auth

        self._session = Session()
        self._session.headers['User-Agent'] = _USER_AGENT

        self._timeout = timeout

        http_adapter = HTTPAdapter(max_retries=_HTTP_CONNECTION_MAX_RETRIES)
        self._session.mount('', http_adapter)

    def send_get_request(self, url, query_string_args=None):
        """
        Send a GET request

        :param str url: The URL or URL path to the endpoint
        :param dict query_string_args: The query string arguments

        :return: Decoded version of the ``JSON`` the remote put in \
                the body of the response.

        """
        return self._send_request('GET', url, query_string_args)

    def send_head_request(self, url, query_string_args=None):
        """
        Send a HEAD request

        :param str url: The URL or URL path to the endpoint
        :param dict query_string_args: The query string arguments

        """
        return self._send_request('HEAD', url, query_string_args)

    def send_post_request(self, url, body_deserialization=None):
        """
        Send a POST request

        :param str url: The URL or URL path to the endpoint
        :param dict body_deserialization: The request's body message \
            deserialized

        :return: Decoded version of the ``JSON`` the remote put in \
                the body of the response.
        """
        return self._send_request(
            'POST',
            url,
            body_deserialization=body_deserialization,
            )

    def send_put_request(self, url, body_deserialization):
        """
        Send a PUT request

        :param str url: The URL or URL path to the endpoint
        :param body_deserialization: The request's body message deserialized

        :return: Decoded version of the ``JSON`` the remote put in \
                the body of the response.
        """
        return self._send_request(
            'PUT',
            url,
            body_deserialization=body_deserialization,
            )

    def send_delete_request(self, url):
        """
        Send a DELETE request

        :param str url: The URL or URL path to the endpoint

        :return: Decoded version of the ``JSON`` the remote put in \
                the body of the response.
        """
        return self._send_request('DELETE', url)

    def _send_request(
        self,
        method,
        url,
        query_string_args=None,
        body_deserialization=None,
        ):
        if url.startswith(self._api_url):
            url = url
        else:
            url = self._api_url + url

        query_string_args = query_string_args or {}

        request_headers = \
            {'content-type': 'application/json'} if body_deserialization else {}

        if body_deserialization:
            request_body_serialization = json_serialize(body_deserialization)
        else:
            request_body_serialization = None

        response = self._session.request(
            method,
            url,
            params=query_string_args,
            auth=self._authentication_handler,
            data=request_body_serialization,
            headers=request_headers,
            timeout=self._timeout,
            )

        self._require_successful_response(response)
        self._require_deserializable_response_body(response)

        return response

    @staticmethod
    def _require_successful_response(response):
        if 400 <= response.status_code < 500:
            if response.status_code == HTTPStatus.UNAUTHORIZED:
                exception_class = AuthenticationError
            elif response.status_code == HTTPStatus.FORBIDDEN:
                exception_class = AccessDeniedError
            elif response.status_code == HTTPStatus.NOT_FOUND:
                exception_class = NotFoundError
            else:
                exception_class = ClientError
            raise exception_class()
        elif 500 <= response.status_code < 600:
            raise ServerError(response.reason, response.status_code)

    @classmethod
    def _require_deserializable_response_body(cls, response):
        if response.status_code in (HTTPStatus.OK, HTTPStatus.NO_CONTENT):
            if response.content:
                cls._require_json_response(response)
        else:
            exception_message = \
                'Unsupported response status {}'.format(response.status_code)
            raise UnsupportedResponseError(exception_message)

    @staticmethod
    def _require_json_response(response):
        content_type_header_value = response.headers.get('Content-Type')
        if not content_type_header_value:
            exception_message = 'Response does not specify a Content-Type'
            raise UnsupportedResponseError(exception_message)

        content_type = content_type_header_value.split(';')[0].lower()
        if content_type != 'application/json':
            exception_message = \
                'Unsupported response content type {}'.format(content_type)
            raise UnsupportedResponseError(exception_message)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        self._session.close()
class PortalConnection(object):
    """
    Connection to HubSpot

    :param authentication_key: This can be either an :class:`APIKey` or an \
            :class:`OAuthKey` instance
    :param basestring change_source: The string passed to HubSpot as \
            ``auditId`` in the query string
    """
    _API_URL = 'https://api.hubapi.com'

    def __init__(self, authentication_key, change_source):
        super(PortalConnection, self).__init__()

        self._authentication_handler = \
            _QueryStringAuthenticationHandler(authentication_key)
        self._change_source = change_source

        self._session = Session()
        self._session.headers['User-Agent'] = _USER_AGENT

        http_adapter = HTTPAdapter(max_retries=_HTTP_CONNECTION_MAX_RETRIES)
        self._session.mount('', http_adapter)

    def send_get_request(self, url_path, query_string_args=None):
        """
        Send a GET request to HubSpot

        :param basestring url_path: The URL path to the endpoint
        :param dict query_string_args: The query string arguments

        :return: Decoded version of the ``JSON`` that HubSpot put in \
                the body of the response.

        """
        return self._send_request('GET', url_path, query_string_args)

    def send_post_request(self, url_path, body_deserialization):
        """
        Send a POST request to HubSpot

        :param basestring url_path: The URL path to the endpoint
        :param dict body_deserialization: The request's body message \
            deserialized

        :return: Decoded version of the ``JSON`` that HubSpot put in \
                the body of the response.
        """
        return self._send_request(
            'POST',
            url_path,
            body_deserialization=body_deserialization,
            )

    def send_put_request(self, url_path, body_deserialization):
        """
        Send a PUT request to HubSpot

        :param basestring url_path: The URL path to the endpoint
        :param body_deserialization: The request's body message deserialized

        :return: Decoded version of the ``JSON`` that HubSpot put in \
                the body of the response.
        """
        return self._send_request(
            'PUT',
            url_path,
            body_deserialization=body_deserialization,
            )

    def send_delete_request(self, url_path):
        """
        Send a DELETE request to HubSpot

        :param basestring url_path: The URL path to the endpoint

        :return: Decoded version of the ``JSON`` that HubSpot put in \
                the body of the response.
        """
        return self._send_request('DELETE', url_path)

    def _send_request(
        self,
        method,
        url_path,
        query_string_args=None,
        body_deserialization=None,
        ):
        url = self._API_URL + url_path

        query_string_args = query_string_args or {}
        query_string_args = dict(query_string_args, auditId=self._change_source)

        request_headers = \
            {'content-type': 'application/json'} if body_deserialization else {}

        if body_deserialization:
            request_body_serialization = json_serialize(body_deserialization)
        else:
            request_body_serialization = None

        response = self._session.request(
            method,
            url,
            params=query_string_args,
            auth=self._authentication_handler,
            data=request_body_serialization,
            headers=request_headers,
            )

        response_body_deserialization = \
            self._deserialize_response_body(response)
        return response_body_deserialization

    @classmethod
    def _deserialize_response_body(cls, response):
        cls._require_successful_response(response)
        cls._require_json_response(response)

        if response.status_code == HTTP_STATUS_OK:
            response_body_deserialization = response.json()
        elif response.status_code in _HTTP_STATUS_CODES_WITH_EMPTY_BODIES:
            response_body_deserialization = None
        else:
            exception_message = \
                'Unsupported response status {}'.format(response.status_code)
            raise HubspotUnsupportedResponseError(exception_message)

        return response_body_deserialization

    @staticmethod
    def _require_successful_response(response):
        if 400 <= response.status_code < 500:
            response_data = response.json()
            error_data = _HUBSPOT_ERROR_RESPONSE_SCHEMA(response_data)

            if response.status_code == HTTP_STATUS_UNAUTHORIZED:
                exception_class = HubspotAuthenticationError
            else:
                exception_class = HubspotClientError
            raise exception_class(
                error_data['message'],
                error_data['requestId'],
                )
        elif 500 <= response.status_code < 600:
            raise HubspotServerError(response.reason, response.status_code)

    @staticmethod
    def _require_json_response(response):
        content_type_header_value = response.headers.get('Content-Type')
        if not content_type_header_value:
            exception_message = 'Response does not specify a Content-Type'
            raise HubspotUnsupportedResponseError(exception_message)

        content_type = content_type_header_value.split(';')[0].lower()
        if content_type != 'application/json':
            exception_message = \
                'Unsupported response content type {}'.format(content_type)
            raise HubspotUnsupportedResponseError(exception_message)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        self._session.close()
Exemple #24
0
class BiliApi:
    def __init__(self, headers: Optional[Dict[str, str]]):
        if not headers:
            headers = _default_headers
        self._session = Session()
        self._session.headers.update(headers)
        self._session.trust_env = True
        self._islogin = False
        self._show_name = None

    def login_by_cookie(self,
                        cookieData,
                        checkBanned=True,
                        strict=False) -> bool:
        '''
        登录并获取账户信息
        cookieData dict 账户cookie
        checkBanned bool 检查是否被封禁
        strict bool 是否严格限制cookie在.bilibili.com域名之下
        '''
        if strict:
            from yarl import URL
            self._session.cookies.update(cookieData,
                                         URL('https://.bilibili.com'))
        else:
            self._session.cookies.update(cookieData)

        self.refreshInfo()
        if not self._islogin:
            return False

        if 'bili_jct' in cookieData:
            self._bili_jct = cookieData["bili_jct"]
        else:
            self._bili_jct = ''

        self._isBanned = None
        if checkBanned:
            code = (self.likeCv(10743282))["code"]
            if code != 0 and code != 65006 and code != -404:
                self._isBanned = True
                import warnings
                warnings.warn(f'{self._name}:账号异常,请检查bili_jct参数是否有效或本账号是否被封禁')
            else:
                self._isBanned = False

        return True

    @property
    def banned(self):
        '''是否账号被异常封禁'''
        return self._isBanned

    @property
    def islogin(self):
        '''是否登录'''
        return self._islogin

    @property
    def myexp(self) -> int:
        '''获取登录的账户的经验'''
        return self._exp

    @property
    def mycoin(self) -> int:
        '''获取登录的账户的硬币数量'''
        return self._coin

    @property
    def vipType(self) -> int:
        '''获取登录的账户的vip类型'''
        return self._vip

    @property
    def name(self) -> str:
        '''获取用于显示的用户名'''
        return self._show_name

    @name.setter
    def name(self, name: str) -> None:
        '''设置用于显示的用户名'''
        self._show_name = name

    @property
    def username(self) -> str:
        '''获取登录的账户用户名'''
        return self._name

    @property
    def uid(self) -> int:
        '''获取登录的账户uid'''
        return self._uid

    @property
    def level(self) -> int:
        '''获取登录的账户等级'''
        return self._level

    def refreshInfo(self):
        '''刷新账户信息(需要先登录)'''
        ret = self.getWebNav()
        if ret["code"] != 0:
            self._islogin = False
            return

        self._islogin = True
        self._name = ret["data"]["uname"]
        self._uid = ret["data"]["mid"]
        self._vip = ret["data"]["vipType"]
        self._level = ret["data"]["level_info"]["current_level"]
        self._verified = ret["data"]["mobile_verified"]
        self._coin = ret["data"]["money"]
        self._exp = ret["data"]["level_info"]["current_exp"]
        if not self._show_name:
            self._show_name = self._name

    def xliveRoomInit(self, rid: int = 1):
        '''
        获取房间初始化信息(房间短id转长id)
        id int 直播间id
        '''
        url = f'https://api.live.bilibili.com/room/v1/Room/room_init?id={rid}'
        with self._session.get(url) as r:
            return r.json()

    def xliveMsgSend(
        self,
        roomid: int,
        msg: str,
        color: int = 16777215,
        fontsize: int = 25,
        mode: int = 1,
        bubble: int = 0,
    ):
        '''
        直播间发送消息
        roomid int 直播间id
        msg str 要发送的消息
        color int 字体颜色
        fontsize int 字体大小
        mode int 发送模式,应该是控制滚动,底部这些
        bubble int 未知
        '''
        url = 'https://api.live.bilibili.com/msg/send'
        post_data = {
            "color": color,
            "fontsize": fontsize,
            "mode": mode,
            "msg": msg,
            "rnd": int(time.time()),
            "roomid": roomid,
            "bubble": bubble,
            "csrf_token": self._bili_jct,
            "csrf": self._bili_jct
        }
        with self._session.post(url, data=post_data) as r:
            return r.json()

    def likeCv(self, cvid: int, type=1) -> Dict:
        '''
        点赞专栏
        cvid int 专栏id
        type int 类型
        '''
        url = 'https://api.bilibili.com/x/article/like'
        post_data = {"id": cvid, "type": type, "csrf": self._bili_jct}
        with self._session.post(url, data=post_data) as r:
            return r.json()

    def getWebNav(self) -> Dict[str, Any]:
        '''取导航信息'''
        url = "https://api.bilibili.com/x/web-interface/nav"
        with self._session.get(url) as r:
            ret = r.json()
        return ret

    def __enter__(self):
        return self

    def __exit__(self, *exc) -> None:
        self.close()

    def close(self) -> None:
        self._session.close()