├── vue.config.js ├── babel.config.js ├── public ├── favicon.ico └── index.html ├── src ├── assets │ ├── background.jpg │ ├── fonts │ │ └── IRANSans │ │ │ ├── IRANSansMedium │ │ │ └── IRANSansMedium.ttf │ │ │ ├── IRANSans Regular │ │ │ └── IRANSans Regular.ttf │ │ │ ├── IRANSans UltraLight │ │ │ └── IRANSans UltraLight.ttf │ │ │ └── readme.html │ └── css │ │ └── font.css ├── plugins │ └── vuetify.js ├── main.js ├── store │ ├── index.js │ └── modules │ │ └── home.js ├── helpers │ ├── english_to_persian.js │ ├── persianNumber_To_English.js │ ├── placeSearch.js │ ├── teacherName.js │ ├── timeCalculator.js │ ├── arabic_to_persian.js │ ├── time_and_place.js │ └── timeInterference.js ├── router │ └── index.js ├── App.vue └── views │ └── Home.vue ├── server.js ├── .gitignore ├── README.md ├── package.json └── sessCrawler └── crawler.py /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | transpileDependencies: [ 3 | 'vuetify' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmirHosein-Gharaati/sess-semester/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/assets/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmirHosein-Gharaati/sess-semester/HEAD/src/assets/background.jpg -------------------------------------------------------------------------------- /src/assets/fonts/IRANSans/IRANSansMedium/IRANSansMedium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmirHosein-Gharaati/sess-semester/HEAD/src/assets/fonts/IRANSans/IRANSansMedium/IRANSansMedium.ttf -------------------------------------------------------------------------------- /src/plugins/vuetify.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuetify from 'vuetify/lib/framework'; 3 | 4 | Vue.use(Vuetify); 5 | 6 | export default new Vuetify({ 7 | rtl: true 8 | }); 9 | -------------------------------------------------------------------------------- /src/assets/fonts/IRANSans/IRANSans Regular/IRANSans Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmirHosein-Gharaati/sess-semester/HEAD/src/assets/fonts/IRANSans/IRANSans Regular/IRANSans Regular.ttf -------------------------------------------------------------------------------- /src/assets/css/font.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "IRANSans"; 3 | src: local("IRANSans"), 4 | url("../fonts/IRANSans/IRANSans Regular/IRANSans Regular.ttf") format("truetype"); 5 | } -------------------------------------------------------------------------------- /src/assets/fonts/IRANSans/IRANSans UltraLight/IRANSans UltraLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmirHosein-Gharaati/sess-semester/HEAD/src/assets/fonts/IRANSans/IRANSans UltraLight/IRANSans UltraLight.ttf -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const serveStatic = require("serve-static") 3 | const path = require('path'); 4 | app = express(); 5 | app.use(serveStatic(path.join(__dirname, 'dist'))); 6 | const port = process.env.PORT || 3000; 7 | app.listen(port); -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | import store from './store' 5 | import vuetify from './plugins/vuetify'; 6 | 7 | Vue.config.productionTip = false 8 | 9 | new Vue({ 10 | router, 11 | store, 12 | vuetify, 13 | render: h => h(App) 14 | }).$mount('#app') 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import Vuex from "vuex"; 3 | import home from "./modules/home"; 4 | import createPersistedState from "vuex-persistedstate"; 5 | 6 | Vue.use(Vuex); 7 | 8 | export default new Vuex.Store({ 9 | modules: { 10 | home, 11 | }, 12 | plugins: [createPersistedState({ 13 | paths: [''] 14 | })], 15 | }); 16 | -------------------------------------------------------------------------------- /src/helpers/english_to_persian.js: -------------------------------------------------------------------------------- 1 | function toFarsiNumber(n) { 2 | const farsiDigits = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹']; 3 | 4 | return n 5 | .toString() 6 | .split('') 7 | .map(x => { 8 | if (x >= '0' && x <= '9') 9 | return farsiDigits[x]; 10 | else 11 | return x; 12 | }) 13 | .join(''); 14 | } 15 | 16 | export {toFarsiNumber}; -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueRouter from 'vue-router' 3 | import Home from '../views/Home.vue' 4 | 5 | Vue.use(VueRouter) 6 | 7 | const routes = [ 8 | { 9 | path: '/', 10 | name: 'Home', 11 | component: Home 12 | }, 13 | ] 14 | 15 | const router = new VueRouter({ 16 | mode: 'history', 17 | base: process.env.BASE_URL, 18 | routes 19 | }) 20 | 21 | export default router 22 | -------------------------------------------------------------------------------- /src/helpers/persianNumber_To_English.js: -------------------------------------------------------------------------------- 1 | function convertPersianNumToEng(number){ 2 | const persianNumDifference = "۱".charCodeAt()-"1".charCodeAt(); 3 | let res=0 4 | for(let i=0; i256? number[i].charCodeAt()- persianNumDifference:number[i].charCodeAt())-"0".charCodeAt()); 7 | } 8 | return res; 9 | } 10 | 11 | export { convertPersianNumToEng }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sess-semester 2 | 3 | [Online Deploy link](https://sess-semester.herokuapp.com/) 4 | 5 | ## Project setup 6 | ``` 7 | npm install 8 | ``` 9 | 10 | ### Compiles and hot-reloads for development 11 | ``` 12 | npm run serve 13 | ``` 14 | 15 | ### Compiles and minifies for production 16 | ``` 17 | npm run build 18 | ``` 19 | 20 | ### Lints and fixes files 21 | ``` 22 | npm run lint 23 | ``` 24 | 25 | ### Customize configuration 26 | See [Configuration Reference](https://cli.vuejs.org/config/). 27 | -------------------------------------------------------------------------------- /src/helpers/placeSearch.js: -------------------------------------------------------------------------------- 1 | function placeSearchHelper(places, course) { 2 | let timeAndPlace = course['seperated_time_and_place']; 3 | let arr = []; 4 | for(let index in timeAndPlace){ 5 | let temp = timeAndPlace[index]; 6 | temp = temp.place; 7 | arr.push(temp); 8 | } 9 | for(let index in arr){ 10 | let place = arr[index]; 11 | if (places.includes(place)) 12 | return true; 13 | } 14 | return false; 15 | } 16 | 17 | export {placeSearchHelper}; -------------------------------------------------------------------------------- /src/helpers/teacherName.js: -------------------------------------------------------------------------------- 1 | function teacherNameDivider(string){ 2 | 3 | string = string.split('*'); 4 | let result = [] 5 | for(let i=0 ; i < string.length ; i+=3){ 6 | result.push([string[i+1], string[i]].join(" ")); 7 | } 8 | 9 | if(result.length > 1){ 10 | result = result.join(' | '); 11 | result = result.substr(0, result.length-3); 12 | return result; 13 | } 14 | 15 | else return result[0]; 16 | } 17 | 18 | function teacherSearch(string, listOfOptions) { 19 | for(let i = 0 ; i < listOfOptions.length ; i++){ 20 | if(string.includes(listOfOptions[i])) return true; 21 | } 22 | return false; 23 | } 24 | 25 | export { teacherNameDivider, teacherSearch }; 26 | -------------------------------------------------------------------------------- /src/helpers/timeCalculator.js: -------------------------------------------------------------------------------- 1 | function isTimeInBetween(startTime, endTime, obj) { 2 | 3 | let isInBetween = false; 4 | 5 | let start = new Date(2000, 0, 1, startTime.split(":")[0], startTime.split(":")[1]); 6 | let end = new Date(2000, 0, 1, endTime.split(":")[0], endTime.split(":")[1]); 7 | 8 | 9 | for (let i = 0; i < obj.length; i++){ 10 | 11 | let startCourse = new Date(2000, 0, 1, obj[i].startHour, obj[i].startMinute); 12 | let endCourse = new Date(2000, 0, 1, obj[i].endHour, obj[i].endMinute); 13 | 14 | if (start <= startCourse && endCourse <= end) { 15 | isInBetween = true; 16 | break; 17 | } 18 | } 19 | 20 | 21 | 22 | return isInBetween; 23 | } 24 | 25 | export { isTimeInBetween }; -------------------------------------------------------------------------------- /src/helpers/arabic_to_persian.js: -------------------------------------------------------------------------------- 1 | String.prototype.replaceAll = function(search, replacement) { 2 | var target = this; 3 | return target.replace(new RegExp(search, 'g'), replacement); 4 | }; 5 | 6 | export default String.prototype.ArabicToPersianCharacter = function () { 7 | var string = this; 8 | var obj = { 9 | 'ك' :'ک', 10 | 'دِ': 'د', 11 | 'بِ': 'ب', 12 | 'زِ': 'ز', 13 | 'ذِ': 'ذ', 14 | 'شِ': 'ش', 15 | 'سِ': 'س', 16 | 'ى' :'ی', 17 | 'ي' :'ی', 18 | '١' :'۱', 19 | '٢' :'۲', 20 | '٣' :'۳', 21 | '٤' :'۴', 22 | '٥' :'۵', 23 | '٦' :'۶', 24 | '٧' :'۷', 25 | '٨' :'۸', 26 | '٩' :'۹', 27 | '٠' :'۰', 28 | }; 29 | 30 | Object.keys(obj).forEach(function(key) { 31 | string = string.replaceAll(key, obj[key]); 32 | }); 33 | return string 34 | }; -------------------------------------------------------------------------------- /src/helpers/time_and_place.js: -------------------------------------------------------------------------------- 1 | function timeAndPlaceDivider(string){ 2 | let stringLength = string.length; 3 | let index = 0; 4 | let lastIndex = 0; 5 | let result = []; 6 | 7 | while(index < stringLength){ 8 | let arr = []; 9 | 10 | while(string[index] != '(') 11 | index++; 12 | arr.push(string.substring(lastIndex, index)); 13 | index++; 14 | while(string[index] == ' ') index++; 15 | lastIndex = index; 16 | 17 | while(string[index] != ')') 18 | index++; 19 | arr.push(string.substring(lastIndex, index)); 20 | index++; 21 | while(string[index] == ' ') index++; 22 | lastIndex = index; 23 | 24 | result.push(arr); 25 | } 26 | 27 | return result; 28 | } 29 | 30 | function timeAndPlaceCorrector(string){ 31 | string = string.replace(')', ")\n"); 32 | return string; 33 | } 34 | 35 | export { timeAndPlaceDivider, timeAndPlaceCorrector }; -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 12 | 13 | 14 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/store/modules/home.js: -------------------------------------------------------------------------------- 1 | import { getField, updateField } from "vuex-map-fields"; 2 | 3 | const state = { 4 | results: [], 5 | 6 | filters: { 7 | semester: "", 8 | unit: [], 9 | course: [], 10 | teacherName: [], 11 | time: [], 12 | place: [], 13 | gender: [], 14 | }, 15 | 16 | filtersItems: { 17 | semesters: ["1402-1"], 18 | units: [], 19 | course: [], 20 | teachersName: [], 21 | times: [], 22 | places: [], 23 | genders: [], 24 | }, 25 | 26 | json: null, 27 | }; 28 | 29 | const getters = { 30 | getField, 31 | getFilterItems: (state) => state.filtersItems, 32 | getSemesters: (state) => state.filtersItems.semesters, 33 | getUnits: (state) => state.filtersItems.units, 34 | getCourses: (state) => state.filtersItems.course, 35 | getTeachers: (state) => state.filtersItems.teachersName, 36 | getPlaces: (state) => state.filtersItems.places, 37 | getGenders: (state) => state.filtersItems.genders, 38 | getJson: (state) => state.json, 39 | }; 40 | 41 | const mutations = { 42 | updateField, 43 | }; 44 | 45 | const actions = {}; 46 | 47 | export default { 48 | state, 49 | getters, 50 | mutations, 51 | actions, 52 | }; 53 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sess-semester", 3 | "version": "0.1.5", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint", 9 | "postinstall": "npm run build", 10 | "start": "node server.js" 11 | }, 12 | "dependencies": { 13 | "core-js": "^3.6.5", 14 | "express": "^4.17.1", 15 | "serve-static": "^1.14.1", 16 | "vue": "^2.6.11", 17 | "vue-router": "^3.2.0", 18 | "vuetify": "^2.4.0", 19 | "vuex": "^3.4.0", 20 | "vuex-map-fields": "^1.4.1", 21 | "vuex-persistedstate": "^4.0.0-beta.3" 22 | }, 23 | "devDependencies": { 24 | "@vue/cli-plugin-babel": "~4.5.0", 25 | "@vue/cli-plugin-eslint": "~4.5.0", 26 | "@vue/cli-plugin-router": "~4.5.0", 27 | "@vue/cli-plugin-vuex": "~4.5.0", 28 | "@vue/cli-service": "~4.5.0", 29 | "babel-eslint": "^10.1.0", 30 | "eslint": "^6.7.2", 31 | "eslint-plugin-vue": "^6.2.2", 32 | "sass": "^1.32.0", 33 | "sass-loader": "^10.0.0", 34 | "vue-cli-plugin-vuetify": "~2.1.0", 35 | "vue-template-compiler": "^2.6.11", 36 | "vuetify-loader": "^1.7.0" 37 | }, 38 | "eslintConfig": { 39 | "root": true, 40 | "env": { 41 | "node": true 42 | }, 43 | "extends": [ 44 | "plugin:vue/essential", 45 | "eslint:recommended" 46 | ], 47 | "parserOptions": { 48 | "parser": "babel-eslint" 49 | }, 50 | "rules": {} 51 | }, 52 | "browserslist": [ 53 | "> 1%", 54 | "last 2 versions", 55 | "not dead" 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /src/helpers/timeInterference.js: -------------------------------------------------------------------------------- 1 | function checkClassTimeInterference(course1, course2){ 2 | const convertDayName =[ 3 | "یکشنبه", 4 | "دوشنبه", 5 | "سهشنبه", 6 | "چهارشنبه", 7 | "پنجشنبه", 8 | "جمعه", 9 | "شنبه", 10 | ] 11 | 12 | let c1Time = course1['seperated_time_and_place']; 13 | let c2Time = course2['seperated_time_and_place']; 14 | 15 | for(let k=0 ; k < c1Time.length ; k++){ 16 | for(let l=0 ; l < c2Time.length ; l++){ 17 | let course1Day = c1Time[k]['day'].replace(/\s/g, ''); 18 | let course2Day = c2Time[l]['day'].replace(/\s/g, ''); 19 | if(convertDayName.indexOf(course1Day) !== convertDayName.indexOf(course2Day)){ 20 | continue; 21 | } 22 | 23 | 24 | let course1StartTime = new Date(2000, 1, 0, c1Time[k]['startHour'], c1Time[k]['startMinute']); 25 | let course2StartTime = new Date(2000, 1, 0, c2Time[l]['startHour'], c2Time[l]['startMinute']); 26 | 27 | let course1EndTime = new Date(2000, 1, 0, c1Time[k]['endHour'], c1Time[k]['endMinute']); 28 | let course2EndTime = new Date(2000, 1, 0, c2Time[l]['endHour'], c2Time[l]['endMinute']); 29 | 30 | if((course1StartTime > course2StartTime && course1StartTime < course2EndTime) || 31 | (course1EndTime < course2EndTime && course1EndTime > course2StartTime) || 32 | (course1StartTime <= course2StartTime && course1EndTime >= course2EndTime) 33 | ){ 34 | return true; 35 | } 36 | 37 | } 38 | } 39 | return false; 40 | } 41 | 42 | function checkFinalTimeInterference(course1, course2){ 43 | 44 | let course1DateTime = course1['final_date_split']; 45 | let course2DateTime = course2['final_date_split']; 46 | 47 | let course1ClockTime = course1['final_time_split']; 48 | let course2ClockTime = course2['final_time_split']; 49 | 50 | // ------- 51 | let course1DayTime = new Date(course1DateTime['y'], course1DateTime['m'], course1DateTime['d']); 52 | let course2DayTime = new Date(course2DateTime['y'], course2DateTime['m'], course2DateTime['d']); 53 | 54 | if(course1DayTime.getTime() !== course2DayTime.getTime()) 55 | return false; 56 | 57 | let course1StartTime = new Date(course1DateTime['y'], course1DateTime['m'], course1DateTime['d'], course1ClockTime['start_hour'], course1ClockTime['start_minute']); 58 | let course2StartTime = new Date(course2DateTime['y'], course2DateTime['m'], course2DateTime['d'], course2ClockTime['start_hour'], course2ClockTime['start_minute']); 59 | 60 | let course1EndTime = new Date(course1DateTime['y'], course1DateTime['m'], course1DateTime['d'], course1ClockTime['end_hour'], course1ClockTime['end_minute']); 61 | let course2EndTime = new Date(course2DateTime['y'], course2DateTime['m'], course2DateTime['d'], course2ClockTime['end_hour'], course2ClockTime['end_minute']); 62 | 63 | if( 64 | (course1StartTime.getHours() === 0 && course1StartTime.getMinutes() === 0 && course1EndTime.getHours() === 0 && course1EndTime.getMinutes() === 0) || 65 | (course2StartTime.getHours() === 0 && course2StartTime.getMinutes() === 0 && course2EndTime.getHours() === 0 && course2EndTime.getMinutes() === 0) 66 | ) return false; 67 | 68 | 69 | if( 70 | (course1StartTime > course2StartTime && course1StartTime < course2EndTime) || 71 | (course1EndTime < course2EndTime && course1EndTime > course2StartTime) || 72 | (course1StartTime <= course2StartTime && course1EndTime >= course2EndTime) 73 | ) return true; 74 | 75 | return false; 76 | } 77 | 78 | export {checkClassTimeInterference, checkFinalTimeInterference}; -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 71 | 72 | 160 | -------------------------------------------------------------------------------- /src/assets/fonts/IRANSans/readme.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | IRANSansFontsgeek 8 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 182 | 183 | 184 |
165 | 166 | 167 |
168 | 169 | 170 | 176 | 177 |
171 |

IRANSans

172 |

This font was downloaded from fontsgeek.com . You can visit fontsgeek.com for thousands of free fonts.

173 |

View Character Map and other information Browse other free fonts

174 |

You will be shortly redirected to FontsGeek website.

175 |
178 |
179 | 180 | 181 |
185 | 186 | 187 | 188 | 189 | -------------------------------------------------------------------------------- /sessCrawler/crawler.py: -------------------------------------------------------------------------------- 1 | from selenium import webdriver 2 | from selenium.webdriver.support.select import Select 3 | from selenium.webdriver.common.by import By 4 | import json 5 | import re 6 | 7 | 8 | def arabicToPersian(text): 9 | obj = {"ك":"ک","دِ":"د","بِ":"ب","زِ":"ز","ذِ":"ذ","شِ":"ش","سِ":"س","ى":"ی","ي":"ی","١":"۱","٢":"۲","٣":"۳","٤":"۴","٥":"۵","٦":"۶","٧":"۷","٨":"۸","٩":"۹","٠":"۰","1":"۱","3":"۲","3":"۳","4":"۴","5":"۵","6":"۶","7":"۷","8":"۸","9":"۹","0":"۰"} 10 | regex = re.compile('|'.join(map(re.escape, obj))) 11 | return regex.sub(lambda match: obj[match.group(0)], text) 12 | 13 | def convertIfPersianToEng(numberInString): 14 | difference = ord("۱")- ord("1") 15 | result = 0 16 | for i in numberInString: 17 | result*=10 18 | if(ord(i)<256): 19 | result+=int(i) 20 | pass 21 | else: 22 | result += int(chr(ord(i)-difference)) 23 | return result 24 | 25 | def seperateTimeAndPlace(timeAndDate): 26 | # timeAndDate 27 | justDateAndTime = timeAndDate.replace("\n","") 28 | places = re.findall(r'\(.*?\)',justDateAndTime) 29 | justDateAndTime = justDateAndTime.replace(" ","") 30 | justDateAndTime = re.sub(r'\(.*?\)', " ", justDateAndTime).split(" ")[:-1] 31 | 32 | thsCourseDaysAndPlace = [] 33 | for i in range(len(justDateAndTime)): 34 | dictOneOfCourseDays ={} 35 | dictOneOfCourseDays["place"] = places[i].replace("(","").replace(")","") 36 | seperated = justDateAndTime[i].split("-") 37 | dictOneOfCourseDays["day"]= seperated[0] 38 | seperatedTimes = seperated[1].split(":") 39 | dictOneOfCourseDays["startHour"] = convertIfPersianToEng(seperatedTimes[0]) 40 | dictOneOfCourseDays["startMinute"] = convertIfPersianToEng(seperatedTimes[1]) 41 | dictOneOfCourseDays["endHour"] = convertIfPersianToEng(seperatedTimes[2]) 42 | dictOneOfCourseDays["endMinute"] = convertIfPersianToEng(seperatedTimes[3]) 43 | thsCourseDaysAndPlace.append(dictOneOfCourseDays) 44 | 45 | return thsCourseDaysAndPlace 46 | 47 | def get_course_details(): 48 | global Driver 49 | data = dict() 50 | 51 | data['title'] = arabicToPersian(Driver.find_element(By.ID, 'edName').text) 52 | data['vahed'] = Driver.find_element(By.ID, 'edTotalUnit').text 53 | data['group'] = Driver.find_element(By.ID, 'edGroup').text 54 | data['teacher'] = arabicToPersian(Driver.find_element(By.ID, 'edTch').text) 55 | data['gender'] = arabicToPersian(Driver.find_element(By.ID, 'edSex').text) 56 | data['unit'] = arabicToPersian(Driver.find_element(By.ID, 'edUnit').text) 57 | data['time_in_week'] = arabicToPersian(Driver.find_element(By.ID, 'edTimeInWeek').text) 58 | data['time_room'] = arabicToPersian(Driver.find_element(By.ID, 'edTimeRoom').text) 59 | data['midterm_date'] = Driver.find_element(By.ID, 'edMidDate').text 60 | data['midterm_time'] = Driver.find_element(By.ID, 'edMidTime').text 61 | data['capacity'] = arabicToPersian(Driver.find_element(By.ID, 'edCapacity').text) 62 | data['id'] = Driver.find_element(By.ID, 'edSrl').text + '^' + data['group'] 63 | data['final_time'] = Driver.find_element(By.ID, 'edFinalTime').text 64 | data['final_date'] = Driver.find_element(By.ID, 'edFinalDate').text 65 | 66 | try: 67 | splitedTime = Driver.find_element(By.ID, 'edFinalTime').text.replace(" ","").split("-") 68 | splitedTimeStart = splitedTime[0].split(":") 69 | splitedTimeEnd = splitedTime[1].split(":") 70 | data['final_time_split'] = {"start_hour":convertIfPersianToEng(splitedTimeStart[0]),"start_minute":convertIfPersianToEng(splitedTimeStart[1]), "end_hour":convertIfPersianToEng(splitedTimeEnd[0]),"end_minute":convertIfPersianToEng(splitedTimeEnd[1])} 71 | except: 72 | data['final_time_split'] = {"start_hour":0,"start_minute":0, "end_hour":0,"end_minute":0} 73 | 74 | try: 75 | splitedDate = Driver.find_element(By.ID, 'edFinalDate').text.split("/") 76 | data['final_date_split'] = {"d":convertIfPersianToEng(splitedDate[2]),"m":convertIfPersianToEng(splitedDate[1]),"y":convertIfPersianToEng(splitedDate[0])} 77 | except: 78 | data['final_date_split'] = {"d":0,"m":0,"y":0} 79 | 80 | try: 81 | data['seperated_time_and_place']=seperateTimeAndPlace(arabicToPersian(data['time_room'])) 82 | except: 83 | data['seperated_time_and_place']={} 84 | return [data['id'], data] 85 | 86 | 87 | PATH = r'/home/amirhosein/chromedriver' 88 | 89 | Driver = webdriver.Chrome(PATH) 90 | 91 | all_data = {} 92 | 93 | Driver.get(r'http://sess.shirazu.ac.ir/') 94 | 95 | input('Navigate to semester schedule page and press enter to continue ') 96 | 97 | select_element = Driver.find_element(By.ID, 'edDepartment') 98 | select_object = Select(select_element) 99 | 100 | all_obj_name = [arabicToPersian(string.text) for string in select_object.options[1:]] 101 | # select units 102 | 103 | toCrawlIndexes = [1,9,10,12,18,41,74,77,78,91] 104 | 105 | for j in toCrawlIndexes: 106 | datas = dict() 107 | select_element = Driver.find_element(By.ID, 'edDepartment') 108 | select_object = Select(select_element) 109 | select_object.select_by_index(j) 110 | Driver.find_element(By.ID, 'edDisplay').click() 111 | print("crawling ",select_element, " ...") 112 | 113 | 114 | listOdd = 'listOdd' 115 | listEven = 'listEven' 116 | lengthOdd = len(Driver.find_elements_by_class_name(listOdd)) 117 | 118 | for i in range(lengthOdd): 119 | # Odd list 120 | coursesOdd = Driver.find_elements_by_class_name(listOdd) 121 | 122 | coursesOdd[i].click() 123 | serial, data = get_course_details() 124 | datas[serial] = data 125 | Driver.back() 126 | 127 | # Even list 128 | coursesEven = Driver.find_elements_by_class_name(listEven) 129 | 130 | try: 131 | coursesEven[i].click() 132 | serial, data = get_course_details() 133 | datas[serial] = data 134 | Driver.back() 135 | except Exception as e: 136 | pass 137 | 138 | all_data[all_obj_name[j-1]] = datas 139 | Driver.back() 140 | 141 | with open('data.json', 'w',encoding="utf-8") as f: 142 | json.dump(all_data, f, ensure_ascii=False) 143 | -------------------------------------------------------------------------------- /src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 772 | 773 | 1154 | 1155 | 1253 | --------------------------------------------------------------------------------