def __init__(self, task_driver: WebDriver):
        """
        TASK_ARTICLE_VIDEO(task_driver: WebDriver)
        初始化

        :param task_driver: 驱动
        """
        self.__driver = task_driver
        self.__network = NETWORK()
Exemple #2
0
    def __init__(self, task_driver: WebDriver):
        """
        LOGIN()
        初始化,

        """
        self.__driver = task_driver
        self.__network = NETWORK()
        self.__wait = WebDriverWait(self.__driver, 10)
Exemple #3
0
    def __init__(self, driver: WebDriver):
        """
        TASK_ANSWER(driver: WebDriver)
        初始化

        :param driver: 驱动
        """
        self.__driver = driver
        self.__network = NETWORK()
        self.__wait = WebDriverWait(self.__driver, 10)
class TASK_ARTICLE_VIDEO(metaclass=SINGLETON):
    def __init__(self, task_driver: WebDriver):
        """
        TASK_ARTICLE_VIDEO(task_driver: WebDriver)
        初始化

        :param task_driver: 驱动
        """
        self.__driver = task_driver
        self.__network = NETWORK()

    def __Check(self, item: str, tq: int) -> None:
        """
        __Check(item: str, tq: int) -> None
        监测任务的完成

        :param item: 任务编号
        :param tq: 等待程度
        :return: None
        """
        bar = tqdm(desc=item, total=tq, unit='it', leave=False, ncols=70)
        count = 0
        start = time.time()
        while True:
            js = "document.documentElement.scrollTop={speed}"
            self.__driver.execute_script(script=js.format(
                speed=RANDOM.Int(a=1, b=10)))
            temp = self.__network.Get()
            if API().Task_Check.geturl() in temp.keys() or \
                    time.time() - start >= 35:
                count += 1
                bar.update(n=1)
                start = time.time()
            if count >= tq:
                break
            time.sleep(0.1)
        bar.close()

    def Do(self, task: Union[ARTICLE, VIDEO], tq: int) -> None:
        """
        Do(task: Union[ARTICLE, VIDEO]) -> None
        进行一次文章或视频任务

        :param task: 任务
        :param tq: 等待程度
        :return: None
        """
        self.__network.Clear()
        self.__driver.get(task.Link)
        self.__Check(item=task.Item, tq=tq)
Exemple #5
0
def Quit() -> None:
    """
    Quit() -> None
    有序退出程序

    :return: None
    """
    NETWORK().Quit()
    temp = DRIVER_MANAGE().Task_Quit
    DB_MANAGE().Quit()
    MITMDUMP().Close()
    del temp
Exemple #6
0
# @Software : Pycharm
# @Version  : Python 3.8.5
# @File     : main.py
# @Function : 入口
import os

from inside.Config.System import SYSTEM
from inside.Driver.Driver_Manage import DRIVER_MANAGE
from inside.Login.Login import LOGIN
from inside.Options.Options_Manage import OPTIONS_MANAGE
from inside.Task.Mitmdump.Mitmdump import MITMDUMP
from inside.Task.Task_Manage import TASK_MANAGE
from inside.Tools.Network import NETWORK
from inside.Tools.Output import OUTPUT

if __name__ == '__main__':
    SYSTEM().Check_Chrome()
    os.system(command=SYSTEM().Clear)
    OPTIONS_MANAGE.Init_Options()
    MITMDUMP().Open()
    driver = DRIVER_MANAGE()
    network = NETWORK()
    network.Init(driver=driver.Task)
    if LOGIN(task_driver=driver.Task).Login():
        while True:
            OUTPUT.Info()
            OPTIONS_MANAGE.Task_Options()
            task = TASK_MANAGE(driver=driver.Task)
            task.Task()

Exemple #7
0
class TASK_ANSWER(metaclass=SINGLETON):
    """答题任务类"""

    def __init__(self, driver: WebDriver):
        """
        TASK_ANSWER(driver: WebDriver)
        初始化

        :param driver: 驱动
        """
        self.__driver = driver
        self.__network = NETWORK()
        self.__wait = WebDriverWait(self.__driver, 10)

    def Topic_Type(self) -> str:
        """
        Topic_Type() -> str
        题目类型

        :return: str
        """
        topic_type_ec = EC.presence_of_element_located(
            (
                By.CLASS_NAME, 'q-header'
            )
        )
        topic_type: WebElement = self.__wait.until(topic_type_ec)
        return topic_type.text.strip()

    def Topic_Seq(self) -> str:
        """
        Topic_Seq() -> str
        题目序号,返回'x/x'

        :return: str
        """
        topic_seq_ec = EC.presence_of_element_located(
            (
                By.CLASS_NAME, 'pager'
            )
        )
        topic_seq: WebElement = self.__wait.until(topic_seq_ec)
        return topic_seq.text.strip()

    def Topic_Input(self) -> List[WebElement]:
        """
        Topic_Input() -> WebElement
        填空题输入框

        :return: WebElement
        """
        topic_input_ec = EC.presence_of_all_elements_located(
            (
                By.TAG_NAME, 'input'
            )
        )
        return self.__wait.until(topic_input_ec)

    def Topic_Options(self) -> List[WebElement]:
        """
        Topic_Options() -> List[WebElement]
        选择题选项

        :return: List[WebElement]
        """
        topic_options_ec = EC.presence_of_element_located(
            (
                By.CLASS_NAME, 'q-answers'
            )
        )
        topic_options: WebElement = self.__wait.until(topic_options_ec)
        return topic_options.find_elements_by_tag_name(name='div')

    def Topic_Submit(self) -> WebElement:
        """
        Topic_Submit() -> WebElement
        题目提交按钮

        :return: WebElement
        """
        topic_submits_ec = EC.presence_of_element_located(
            (
                By.CLASS_NAME, 'action-row'
            )
        )
        topic_submits: WebElement = self.__wait.until(topic_submits_ec)
        submits = topic_submits.find_elements_by_tag_name(name='button')
        for submit in submits:
            if submit.is_enabled():
                return submit

    def __Accomplish(self) -> bool:
        """
        __Accomplish() -> bool
        检测答题是否完成

        :return: bool
        """
        while True:
            for key, value in self.__network.Get().items():
                if re.match(
                    pattern=API().Answer_Accomplish.geturl(),
                    string=key
                ):
                    return True

    def __Error(self) -> bool:
        """
        __Error() -> bool
        检测是否有弹窗

        :return: bool
        """
        try:
            time.sleep(1)
            self.__driver.find_element_by_class_name(
                name='ant-modal-content')
            return True
        except NoSuchElementException:
            return False

    def __Alert(self) -> None:
        """
        __Alert() -> None
        检测弹窗,并点击确认

        :return: None
        """
        try:
            self.__driver.switch_to.alert.accept()
        except NoAlertPresentException:
            pass

    def __Do(self) -> None:
        """
        __Do() -> None
        做一个题目

        :return: None
        """
        topic_type = self.Topic_Type()
        if '填空题' in topic_type:
            for answer in self.Topic_Input():
                answer.send_keys('1')
        elif [x for x in ('单选题', '多选题') if x in topic_type]:
            for answer in self.Topic_Options():
                while answer.get_attribute(name='class') == 'q-answer choosable':
                    answer.click()
        time.sleep(0.1)
        topic_seq = self.Topic_Seq()
        while self.Topic_Seq() == topic_seq:
            topic_submit = self.Topic_Submit()
            topic_submit.click()
            if self.__Error():
                raise TASK_EXCEPTION('失败')

    def Do(self, link: str) -> None:
        """
        Do(link: str) -> None
        答题

        :param link: 题目链接
        :return: None
        """
        self.__network.Clear()
        self.__driver.get(url=link)
        self.__Alert()
        seq = int(self.Topic_Seq().split('/')[-1])
        bar = tqdm(
            desc='答题',
            total=seq,
            unit='题',
            leave=False,
            ncols=70
        )
        while True:
            try:
                self.__Do()
                bar.update(n=1)
            except (StaleElementReferenceException,
                    ElementClickInterceptedException,
                    TimeoutException):
                self.__Accomplish()
                bar.update(n=1)
                time.sleep(0.1)
                break
        bar.close()
Exemple #8
0
class LOGIN(object):
    """登录类"""

    def __init__(self, task_driver: WebDriver):
        """
        LOGIN()
        初始化,

        """
        self.__driver = task_driver
        self.__network = NETWORK()
        self.__wait = WebDriverWait(self.__driver, 10)

    def __QR_Iframe(self) -> WebElement:
        """
        __QR_Iframe() -> WebElement
        获取二维码iframe

        :return: WebElement
        """
        iframe_Ec = EC.presence_of_element_located(
            (
                By.ID, "ddlogin-iframe"
            )
        )
        return self.__wait.until(iframe_Ec)

    def __QR_Base64(self) -> str:
        """
        __QR_Base64() -> str
        二维码base64,格式为:data:image/png;base64,xxx==

        :return: str
        """
        qr_code_Ec = EC.presence_of_element_located(
            (By.CLASS_NAME, "login_qrcode_content")
        )
        qr_code: WebElement = self.__wait.until(qr_code_Ec)
        qr = qr_code.find_element_by_tag_name(name='img')
        return qr.get_attribute(name='src')

    def __Get_QR(self) -> str:
        """
        __Get_QR() -> str
        获取二维码,格式为:data:image/png;base64,xxx==

        :return: str
        """
        qr_iframe = self.__QR_Iframe()
        self.__driver.switch_to.frame(frame_reference=qr_iframe)
        temp = self.__QR_Base64()
        self.__driver.switch_to.default_content()
        return temp

    def __Get_QR_ID(self, key: str, value: str) -> str:
        """
        __Get_QR_ID(key: str, value: str) -> str
        获取二维码ID,格式为:qr:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

        :param key: url
        :param value: requestId
        :return: str
        """
        if API().Login_Generate.geturl() == key:
            response = self.__network.GetResponseBody(requestId=value)[
                'body']
            response = json.loads(response)
            return response['result']
        return ''

    def __Get_QR_Status_Network(self, key: str, value: str) -> int:
        """
        __Get_QR_Status_Network(key: str, value: str) -> int
        获取二维码状态码(Network中获取)

        :param key: url
        :param value: requestId
        :return: int
            -1: 还未请求
            1: 成功
            11021: 未登录
            11019: 二维码失效
        """
        if API().Login_QR_Status.geturl() == key:
            while True:
                try:
                    response = self.__network.GetResponseBody(requestId=value)
                    response = json.loads(response['body'])
                    if response['success']:
                        return 1
                    else:
                        return int(response['code'])
                except WebDriverException:
                    continue
        return -1

    def __Get_QR_Status_Requests(self, qr_data: Dict, qr_state: str):
        """
        __Get_QR_Status_Requests(qr_data: Dict) -> int
        获取二维码状态码(requests请求)

        :param qr_data: 带有二维码编号的data
        :param qr_state: 二维码的state
        :return: int
            1: 成功
            11021: 未登录
            11019: 二维码失效
        """
        html = REQUESTS.Post(
            url=API().Login_QR_Status.geturl(),
            data=qr_data
        )
        status = html.json()
        if status['success']:
            self.__Change_Driver_Cookie(key=status['data'], state=qr_state)
            return 1
        else:
            return int(status['code'])

    def __Change_Driver_Cookie(self, key: str, state: str) -> None:
        """
        __Change_Driver_Cookie(key: str, state: str) -> None
        此处是应对network中还未查询二维码状态时,所做的措施,用处是加快登录过程,而不需要浏览器
            自主添加cookie

        :param key: 最后一次查询二维码状态的api会返回code(只会允许查询一次,随后就是过期)
        :param state: iframe链接中提取
        :return: None
        """
        url = parse.urlparse(url=key)
        code = parse.parse_qs(qs=url.query)['loginTmpCode'][0]
        html = REQUESTS.Get(
            url=API().Login_Token.geturl().format(code=code, state=state)
        )
        token = html.cookies.get(name='token')
        cookie = {'domain': '.xuexi.cn',
                  'name': 'token',
                  'value': token}
        self.__driver.add_cookie(cookie_dict=cookie)
        self.__driver.refresh()

    def __Get_QR_State(self, key: str) -> str:
        """
        __Get_QR_State(key: str) -> str
        获取二维码的state,在iframe链接中提取

        :param key: iframe链接
        :return: str
        """
        temp = re.match(
            pattern=API().Login_QR_Iframe.geturl(),
            string=key
        )
        if temp:
            url = parse.urlparse(url=key)
            return parse.parse_qs(qs=url.query)['state'][0]
        return ''

    def __QR_Refresh(self) -> None:
        """
        __QR_Refresh() -> None
        刷新二维码

        :return: None
        """
        qr_refresh_Ec = EC.presence_of_element_located(
            (
                By.CLASS_NAME, "refresh"
            )
        )
        qr_refresh: WebElement = self.__wait.until(qr_refresh_Ec)
        qr_refresh.click()

    def __Check_Status(self) -> bool:
        """
        __Check_Status() -> bool
        检测二维码状态, 此处略微复杂了一点
        具体流程:
            1、初始化state、iid、status、req为空
                state:二维码的state值,用于处理浏览器未触发状态检测的空窗期登录问题
                iid:二维码的id值,作用同上
                status:二维码的状态值
                req:检测浏览器是否处于空窗期
            2、开启循环
            3、从日志中取值
            4、为state、iid、status、req赋值
            5、如果日志中没有了、且初值都赋值完毕,且浏览器处于空窗期,就进行自主查询
            6、判断查询的状态

        :return: bool
            True:成功
            False:过期
        """
        state = iid = status = None
        req = False
        while True:
            network = self.__network.Get()
            for key, value in network.items():
                key = parse.unquote(string=key)
                temp = self.__Get_QR_State(key=key)
                if temp:
                    state = temp
                    break
                temp = self.__Get_QR_ID(key=key, value=value)
                if temp:
                    iid = temp
                    break
                status = self.__Get_QR_Status_Network(key=key, value=value)
                req = True if status == -1 else False
            if not network and state and iid and status and req:
                qr_data = {
                    'qrCode': iid,
                    'goto': 'https://oa.xuexi.cn',
                    'pdmToken': ''
                }
                status = self.__Get_QR_Status_Requests(
                    qr_data=qr_data,
                    qr_state=state
                )
            if status == 1:
                return True
            elif status == 11021:
                continue
            elif status == 11019:
                return False

    def _Login(self) -> bool:
        """
        _Login() -> Bool
        进行登录;
        具体流程:
            1、开启循环检测二维码状态
                1、获取二维码图片
                2、显示二维码
                3、二维码状态检测
                4、根据3的返回值决定:
                    1、刷新二维码,中断本次循环,再来一次
                    2、提取Token值,根据选项(持久化)决定是否保持token,关闭二维码容器
        :return: Bool,返回值只有True,如未登录则会一直循环
        """
        self.__network.Clear()
        self.__driver.get(url=API().Login.geturl())
        while True:
            qr = self.__Get_QR()
            QR_VESSEL().Show_QR(qr=qr)
            status = self.__Check_Status()
            if not status:
                self.__QR_Refresh()
                continue
            else:
                while self.__driver.current_url != API().Master.geturl():
                    continue
                cookies = self.__driver.get_cookies()
                token = [{cookie['name']: cookie['value']} for cookie in
                         cookies if cookie['name'] == 'token']
                if token:
                    INFO_MANAGE().Init(token=token[0]['token'])
                    if OPTIONS().Token:
                        cookie = token[0]
                        html = REQUESTS().Get(
                            url=API().Aggregate_Score.geturl(),
                            cookies=cookie
                        )
                        data = html.json()
                        user_id = data['data']['userId']
                        user = USER(user_id=user_id, token=token[0]['token'])
                        if DB_MANAGE().User.Exist_User(user=user):
                            DB_MANAGE().User.Update(user=user)
                        else:
                            DB_MANAGE().User.Insert(user=user)
                            DB_MANAGE().Article.Update_All()
                            DB_MANAGE().Video.Update_All()
                QR_VESSEL().QR_QUIT()
                return status

    def Login(self) -> bool:
        """
        Login() -> bool
        登录,如果user表不为空会检测令牌是否有效,有效则直接登录

        :return: bool
        """
        if DB_MANAGE().User.Exist():
            user = DB_MANAGE().User.Query()
            if CHECK_TOKEN.Check_Token(token=user.Token):
                INFO_MANAGE().Init(token=user.Token)
                self.__driver.get(url=API().Master.geturl())
                self.__driver.add_cookie(cookie_dict=user.Token_Driver)
                self.__driver.refresh()
                return True
        return self._Login()