controller/
입력 받은 Login Data를 토대로 크롤링을 하고 로데이터를 정제하는 Controller 부분입니다.
/controller
/__init__.py
/__init__.py
__init__은 특정 클래스나 폴더 혹은 모듈이 호출될떄 함께 호출되고 실행되며, 패키지로 인식하게 해준다.
python3.3 버전부터는 __init__
.
py
파일이 없어도 패키지로 인식한다(PEP 420). 하지만 하위 버전 호환을 위해 __init__.py
파일을 생성하는 것이 안전한 방법이다.
/login_check.py
/login_check.py
lms_id와 lms_pw를 통해 기존에 알아둔 id, pw양식에 맞는지 확인을 하고, 1차 양식이 통과하면 실제 lms에 로그인이 되는지 처리하는 부분입니다.
from bs4 import BeautifulSoup
import requests
"""
lms_login_check
"""
def login_check_and_get_session(lms_id, lms_pw):
fail_login_value = "로그인 정보가 일치하지 않습니다."
if lms_id.isdigit() != True and len(lms_id) != 9:
return False
# elif len(lms_pw) != 6 and not (10 <= len(lms_pw) <= 16):
# return False
else:
session = requests.Session()
session_url = "https://lms.pknu.ac.kr/ilos/lo/login.acl" # 세션을 얻을 url
data = {"usr_id": lms_id, "usr_pwd": lms_pw} # LMS 아이디 # LMS 비밀번호
request = session.post(session_url, data=data, verify=False)
confirm_login = BeautifulSoup(request.text, "html.parser")
if fail_login_value in str(confirm_login):
session.close()
print("세션이 닫혔습니다.")
return False
else:
return True
/selecter.py
/selecter.py
lmsid 와 lmspw 를 토대로 lms의 세션을 통해 크롤링으로 "수업", "과제", "시험"의 로데이터를 얻고, 설계한 API에 맞는 데이터로 정제하는 부분입니다.
# -*- coding: utf-8 -*-
from bs4 import BeautifulSoup
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def get_session(lms_id, lms_pw):
session = requests.Session()
session_url = "https://lms.pknu.ac.kr/ilos/lo/login.acl" # 세션을 얻을 url
data = {"usr_id": lms_id, "usr_pwd": lms_pw} # LMS 아이디 # LMS 비밀번호
request = session.post(session_url, data=data, verify=False)
confirm_login_soup = BeautifulSoup(request.text, "html.parser")
# login_checker 에서 시행했음.
# if "로그인 정보가 일치하지 않습니다." in confirm_login_soup.text:
# session.close() # 세션 닫기
# return False
return session
def Sub_subject_craw_module(session):
subject_craw_url = (
"https://lms.pknu.ac.kr/ilos/main/main_form.acl" # 학수번호와 과목 명을 크롤링함
)
request = session.post(subject_craw_url, verify=False)
sub_num_soup = BeautifulSoup(request.text, "html.parser") # main에 요청보내서 학수번호 알아내기
subject_list = sub_num_soup.findAll("em", {"sub", "sub_open"})
return_subject_list = []
for index in range(len(subject_list)):
return_subject_list.append(
[
"".join(subject_list[index].text.replace(" ", "").split()),
subject_list[index]["kj"],
]
)
return return_subject_list
def Sub_detail_sub_info(KJKEY, session):
# global session
craw_url = "https://lms.pknu.ac.kr/ilos/st/course/eclass_room2.acl"
sub_main = "https://lms.pknu.ac.kr/ilos/st/course/submain_form.acl"
data = {
"KJKEY": KJKEY, # n번째 과목의 학수번호
"returnData": "json",
"returnURI": "",
"encoding": "utf-8",
}
request = session.post(craw_url, data=data, verify=False) # 해당 과목에 대한 session을 얻는다.
soup = BeautifulSoup(request.text, "html.parser")
res = session.get(sub_main, verify=False) # 해당 과목의 세션을 얻었을 때 url을 가져와야함
soup = BeautifulSoup(res.text, "html.parser")
right_banner = soup.find("div", {"class", "submain-rightarea"}) # 오른쪽 배너를 부르고
detail_sub_info = right_banner.findAll("a", {"class", "site-link"}) # 부른 것에서 추출
subject_url_list = []
exam_url_list = []
assignment_url = "https://lms.pknu.ac.kr" # + "/ilos/st/course/report_view_form.acl?RT_SEQ=4057037" 과제는 그냥 get 때리면 됨, SEQ뒤에 과제 일렬번호 써줘야함
# 오른쪽 부분을 이용해서 "과제와 시험기간이 현재 범위 인것만 긁는다."
for i in range(len(detail_sub_info)):
if "[과제]" in detail_sub_info[i].text.strip():
subject_url_list.append(assignment_url + detail_sub_info[i]["href"])
if "[시험]" in detail_sub_info[i].text.strip():
exam_url_list.append(assignment_url + detail_sub_info[i]["href"])
return subject_url_list, exam_url_list
def Sub_class_info(ky, session):
online_list = "https://lms.pknu.ac.kr/ilos/st/course/online_list.acl" # 수업
data = {"ud": "", "ky": ky, "WEEK_NO": "", "encoding": "utf-8"}
res = session.post(online_list, verify=False)
soup = BeautifulSoup(res.text, "html.parser")
temp_temp = soup.findAll("div", {"class", "lecture-box"})
return temp_temp
def Sub_subject(craw_url, session):
res = session.post(craw_url, verify=False)
soup = BeautifulSoup(res.text, "html.parser")
temp_temp = soup.find("table", {"class": "bbsview"})
temp_temp2 = soup.find("table", {"class": "bbswrite"})
return temp_temp, temp_temp2
def Sub_exam(craw_url, session):
res = session.post(craw_url, verify=False)
soup = BeautifulSoup(res.text, "html.parser")
contents = soup.find("div", {"id": "contents"})
return contents
def get_subject_information(lms_id, lms_pw):
"""
세션 얻기
"""
session = get_session(lms_id, lms_pw)
"""
학수번호와 과목명을 크롤링
"""
subject_list = Sub_subject_craw_module(session)
"""
미완료 항목 크롤링
"""
sub_percent = "100%" # 100% 안들으면 미완료
return_dic = {"status": 200, "subject": [], "lms_data": []}
calender_form = {
"subject_name": "",
"class": "",
"context": "",
"date_deadline": "",
}
for index in range(len(subject_list)):
return_dic["subject"].append(subject_list[index][0]) # json 추가부분
# 수업 처리 부분
temp_li_ = Sub_class_info(subject_list[index][1], session)
for i in range(len(temp_li_)):
temp_list_find = temp_li_[i].text.split()
if sub_percent not in temp_list_find:
index_ha = temp_list_find.index("학습인정기간")
if "아닙니다." not in temp_list_find[:index_ha]:
# 이유를 모르겠음 .... 왜 -1 하면 되는 것인가 ?
calender_form["subject_name"] = subject_list[index - 1][0]
print("into calender_form ", subject_list[index][0], index)
calender_form["class"] = "수업"
calender_form["context"] = " ".join(temp_list_find[:index_ha])
calender_form["date_deadline"] = " ".join(
temp_list_find[index_ha + 6 : index_ha + 9]
)
return_dic["lms_data"].append(
dict(calender_form)
) # dict해서 넣어야 이전값들이 안바뀜
# 과제 및 시험 처리 부분
# 과제 처리 부분
temp_list, temp_list2 = Sub_detail_sub_info(subject_list[index][1], session)
for i in range(len(temp_list)):
temp_temp, temp_temp2 = Sub_subject(temp_list[i], session)
sub = temp_temp.text.split()
find_index = sub.index("마감일")
find_index2 = sub.index("제출방식")
if "제출일시" not in temp_temp2.text.split(): # 과제 제출 안함
calender_form["subject_name"] = subject_list[index][0]
calender_form["class"] = "과제"
calender_form["context"] = " ".join(sub[4:find_index2])
calender_form["date_deadline"] = " ".join(
sub[find_index + 1 : find_index + 4]
)
return_dic["lms_data"].append(dict(calender_form))
# 시험 처리 부분
for i in range(len(temp_list2)):
h = Sub_exam(temp_list2[i], session)
if "응시정보" in h.text:
continue
else:
h = h.findAll("td")
li = []
for j in range(len(h)):
li.append(h[j].text)
calender_form["subject_name"] = subject_list[index][0]
calender_form["class"] = "시험"
calender_form["context"] = li[0]
calender_form["date_deadline"] = ", ".join(li[4:6])
return_dic["lms_data"].append(dict(calender_form))
session.close()
return return_dic
# return_json = get_subject_information("202013245", "125734")
# print("return_json :: ", return_json)
Last updated