-학기 시간표 종합- 19.11.29 ~ 19.12.10

crawl_table.py

from bs4 import BeautifulSoup as bs
from selenium import webdriver
from selenium.webdriver.support.ui import Select
import time
from webdriver_manager.chrome import ChromeDriverManager

from Class_Define import Department, Class

class Crwal_Table:
    def __init__(self):
        self.options = webdriver.ChromeOptions()
        # self.options.add_argument('headless')
        self.options.add_argument("user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) "
                             "Chrome/61.0.3163.100 Safari/537.36")

        self.browser = None
        self.year = None
        self.semester = None
        self.dept_list = []
        self.semester_trans = {'1' : '1', '2' : '3', '여름' : '2', '겨울' : '4'}
        self.dept_eles = None

    def get_year_obj(self, rq_year):
        year = self.browser.find_element_by_name('ag_ledg_year')
        self.year = Select(year)
        self.year.select_by_value('20' + rq_year)

    def get_semester_obj(self, rq_semester):
        semester = self.browser.find_element_by_name('ag_ledg_sessn')
        self.semester = Select(semester)
        self.semester.select_by_value(self.semester_trans[rq_semester])

    def lecture_home(self, year, semester):
        if self.browser.current_url != "https://wis.hufs.ac.kr/src08/jsp/lecture/LECTURE2020L.jsp":
            self.browser.get("https://wis.hufs.ac.kr/src08/jsp/lecture/LECTURE2020L.jsp")

        if not self.year:
            self.get_year_obj(year)
            time.sleep(0.3)
            self.get_semester_obj(semester)

        dept_eles = self.browser.find_element_by_name('ag_crs_strct_cd')
        if len(self.dept_list) == 0:
            for i in dept_eles.find_elements_by_tag_name('option'):
                self.dept_list.append(i.text.strip()[6:].split('(')[0].strip())

        self.dept_eles = Select(dept_eles)
        return self.dept_eles

    def make_timetable(self, major, rq_year, rq_semester):

        if major == None:
            return None

        try:
            with open(rq_year + '-' + rq_semester + ' ' + major + '.txt', 'r', encoding="UTF-8") as file:
                class_list = file.readlines()
                depart = Department(major)
                print(depart.name, '데이터 수집 중')
                for i in class_list:
                    i = i.split(" # ")
                    area, year, subject, syllabus, required, online, foreign, team_teaching, prof, credit, class_time, restrict_num, note, stars = i
                    depart.insert_class(Class(area, year, subject, syllabus, required, online, foreign,
                                              team_teaching, prof, credit, class_time, restrict_num, note, stars))
            print("데이터 수집 완료")
            return depart

        except:
            if not self.browser:
                self.browser = webdriver.Chrome(ChromeDriverManager().install(), options=self.options)
            dept_eles = self.lecture_home(rq_year, rq_semester)

            major_index = None
            for i in range(len(self.dept_list)):
                if major.lower() in self.dept_list[i].lower():
                    major_index = i
                    break
            print(self.dept_list[major_index], '데이터 수집 중')

            if major_index == None:
                raise Exception("학과를 정확히 입력해주세요!")

            # major_index = self.dept_list.index(major)
            depart = Department(self.dept_list[major_index])
            dept_eles.select_by_index(major_index)

            time.sleep(0.5)
            html = bs(self.browser.page_source, 'html.parser')

            tbody = html.findAll('tbody')
            trs = tbody[-1].findAll('tr')[1:]

            for i in trs:
                tds = i.findAll('td')
                area = tds[1].get_text().strip()
                year = tds[2].get_text().strip()
                subject = tds[4].get_text().strip().splitlines()
                subject = " / ".join(subject)
                try:
                    syllabus = tds[5].find('a')['href'].split('\'')
                    ag_1 = syllabus[1]
                    ag_2 = syllabus[3]
                    ag_3 = syllabus[5]
                    ag_4 = syllabus[7]
                    syllabus = "https://wis.hufs.ac.kr/src08/jsp/lecture/syllabus.jsp?mode=print&ledg_year=" \
                               +str(ag_1)+"&ledg_sessn="+str(ag_2)+"&org_sect="+str(ag_3)+"&lssn_cd="+str(ag_4)
                except:
                    syllabus = 'None'

                required = tds[6]
                if required.find('img'):
                    required = 'O'
                else:
                    required = required.get_text()

                online = tds[7]
                if online.find('img'):
                    online = 'O'
                else:
                    online = online.get_text()

                foreign = tds[9]
                if foreign.find('img'):
                    foreign = 'O'
                else:
                    foreign = foreign.get_text()

                team_teaching = tds[10]
                if team_teaching.find('img'):
                    team_teaching = 'O'
                else:
                    team_teaching = team_teaching.get_text()

                prof = tds[11].get_text().strip().split('(')[0].strip()
                credit = tds[12].get_text().strip()
                class_time = tds[14].get_text().strip()
                restrict_num = tds[15].get_text().strip()
                note = tds[16].get_text().strip()

                if len(note) == 0:
                    depart.insert_class(Class(area, year, subject, syllabus, required, online, foreign,
                                              team_teaching, prof, credit, class_time, restrict_num))
                else:
                    depart.insert_class(Class(area, year, subject, syllabus, required, online, foreign,
                                              team_teaching, prof, credit, class_time, restrict_num, note))

            self.all_courses(depart, rq_year, rq_semester)
        print("데이터 수집 완료")
        return depart

    def get_avg_stars(self, dept_obj1, dept_obj2, grade):
        if not self.browser:
            self.browser = webdriver.Chrome(ChromeDriverManager().install(), options=self.options)
        browser = self.browser
        browser.get("https://everytime.kr/lecture")
        try:
            print('로그인 시도')
            id = browser.find_element_by_name("userid")
            id_input = input('아이디 입력 : ')
            id.send_keys(id_input)

            pw = browser.find_element_by_name("password")
            pw_input = input('비밀번호 입력 : ')
            pw.send_keys(pw_input)

            login = browser.find_element_by_class_name('submit')
            login.click()
            print('에브리타임 로그인 성공')
        except:
            print('로그인 실패')
            return

        fst_class_list = dept_obj1.classes
        scd_class_list = None
        if dept_obj2 != None:
            scd_class_list = dept_obj2.classes

        def course_insert(class_list):
            for course in class_list:

                if course.year not in grade or len(course.prof) == 0:
                    continue
                else:
                    if (fst_class_list == class_list and '이중' in course.area) \
                            or (scd_class_list == class_list and '1전공자 전용' in course.note):
                        continue

                while True:
                    try:
                        input_box = browser.find_element_by_name('keyword')
                        submit_btn = browser.find_element_by_class_name('submit')
                        input_box.send_keys(' ')
                        input_box.send_keys(course.subject.split(' / ')[0])
                        browser.execute_script("arguments[0].click();", submit_btn)
                        time.sleep(0.5)
                        if course.prof in browser.page_source:
                            profs= browser.find_element_by_xpath("//*[contains(text(), '" + course.prof + "')]")
                        else:
                            course.stars = '-'
                            browser.back()
                            break
                        browser.execute_script("arguments[0].click();", profs)
                        time.sleep(0.5)
                        stars = browser.find_element_by_class_name('value').text
                        if stars == '0':
                            stars = '-'
                        course.stars = stars
                        browser.back()
                        browser.back()
                        break

                    except:
                        pass
                    try:
                        popup = browser.find_element_by_class_name('close')
                        browser.execute_script("arguments[0].click();", popup)
                    except:
                        continue
        print('강의평 가져오는중...')
        course_insert(fst_class_list)
        print('1전공 완료')
        if scd_class_list:
            course_insert(scd_class_list)
            print('2전공 완료')
        # browser.close()

    def all_courses(self, dept_obj, year, semester):
        with open(year + '-' + semester + ' ' + dept_obj.name + '.txt', 'w', encoding="UTF-8") as file:
            for course in dept_obj.classes:
                file.write(" # ".join(course()) + "\n")

class_define.py

class Department:
    def __init__(self, name):
        self.name = name
        self.classes = []

    def __str__(self):
        return self.name

    def insert_class(self, class_obj):
        self.classes.append(class_obj)

class Class:
    def __init__(self, area, year, subject, syllabus, required, online, foreign, team_teaching, prof,
                 credit, class_time, restrict_num, note = '-', avg_stars = ' - '):
        self.area = area
        self.year = year
        self.subject = subject
        self.syllabus = syllabus
        self.required = required
        self.online = online
        self.foreign = foreign
        self.team_teaching = team_teaching
        self.prof = prof
        self.credit = credit
        self.class_time = class_time
        self.restrict_num = restrict_num
        self.stars = avg_stars
        self.note = note

    def __str__(self):
        return self.subject

    def __call__(self):
        return (self.area, self.year, self.subject, self.syllabus, self.required, self.online, self.foreign,
                self.team_teaching, self.prof, self.credit, self.class_time, self.restrict_num, self.note, self.stars)

class User:
    def __init__(self, course_evl, grade, first_major, second_major = None):
        self.first_major = first_major
        self.second_major = second_major
        self.grade = grade
        self.courses = []
        self.course_evl = course_evl

class User_Table(User):
    def __init__(self, course_evl, grade, first_major, second_major = None):
        self.credits = 0
        self.longest = 0
        self.time_table = None
        super().__init__(course_evl, grade, first_major, second_major)

    def insert_course(self, course_obj):
        self.courses.append(course_obj)
        class_time = course_obj.class_time.split('(')[0].strip()
        try:
            class_time = int(class_time.split()[-1])
            if class_time > self.longest:
                self.longest = class_time
        except:
            pass
        self.credits += int(course_obj.credit)

    def make_txt(self, fst_obj, sec_obj):
        first_major_obj = fst_obj
        for course in first_major_obj.classes:
            if (self.course_evl and ' - ' in course.stars) or not course.year in self.grade or '이중' in course.area:
                continue
            self.insert_course(course)

        print('1전공 조건 추출 완료')

        if sec_obj:
            second_major_obj = sec_obj
            for course in second_major_obj.classes:
                if (self.course_evl == True and ' - ' in course.stars) or not course.year in self.grade or '1전공자 전용' in course.note:
                    continue
                self.insert_course(course)
            print('2전공 조건 추출 완료')

        self.time_table = {
            'Mon': [[] for i in range(self.longest)],
            'Tue': [[] for i in range(self.longest)],
            'Wed': [[] for i in range(self.longest)],
            'Thu': [[] for i in range(self.longest)],
            'Fri': [[] for i in range(self.longest)],
        }
        return self.credits

    def make_time_dict(self):
        print('시간표 만드는 중입니다.')
        course_list = self.courses
        for i in course_list:
            s = Stack()
            if len(i.class_time) > 3:
                time = i.class_time.split('(')[2].strip().split()
            else:
                continue
            for j in time:
                if not j.isdigit():
                    if not s.isEmpty():
                        s.pop()
                    s.push(j)
                else:
                    subject_information = {'sub': i.subject, 'syllabus': i.syllabus, 'prof': i.prof, 'stars': i.stars, 'credit' :  i.credit}
                    self.time_table[s.peek()][int(j) - 1].append(subject_information)
            while not s.isEmpty:
                s.pop()

        return self.time_table

class Stack:
    def __init__(self):
        self.item = []
        self.size = 0

    def push(self, value):
        self.item.append(value)
        self.size += 1

    def pop(self):
        if self.size != 0:
            self.size -= 1
            return self.item.pop()
        return print("Stack is Empty")

    def peek(self):
        if self.size != 0:
            return self.item[-1]
        return print("Stack is Empty")

    def __len__(self):
        return len(self.item)

    def isEmpty(self):
        return self.__len__() == 0

quick_sort.py

def quick_sort_by_stars(list, p, r):
    if p < r:
        q = partition_by_stars(list, p, r)
        quick_sort_by_stars(list, p, q - 1)
        quick_sort_by_stars(list, q + 1, r)

def partition_by_stars(list, p, r):
    x = list[r].stars
    i = p - 1
    for j in range(p, r):
        if list[j].stars > x:
            i += 1

            list[j], list[i] = list[i], list[j]

    list[i + 1], list[r] = list[r], list[i + 1]

    return i + 1

def quick_sort_by_time(list, p, r):
    if p < r:
        q = partition_by_time(list, p, r)
        quick_sort_by_time(list, p, q - 1)
        quick_sort_by_time(list, q + 1, r)

def partition_by_time(list, p, r):
    refer = {
        '월' : 10,
        '화' : 30,
        '수' : 50,
        '목' : 70,
        '금' : 90,
        'x' : 120
    }
    x = list[r].class_time.split()
    if len(x) > 1:
        x = refer[x[0]] + int(x[1])
    else:
        x = refer['x']
    i = p - 1
    for j in range(p, r):
        value = list[j].class_time.split()
        if len(value) > 1:
            value = refer[value[0]] + int(value[1])
        else:
            value = refer['x']

        if value < x:
            i += 1

            list[j], list[i] = list[i], list[j]

    list[i + 1], list[r] = list[r], list[i + 1]

    return i + 1

html_making.py