├── chicago.py ├── course.txt ├── ethz.py ├── harvard.py └── readme.md /chicago.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from time import sleep 3 | from selenium import webdriver 4 | from selenium.webdriver.support.ui import Select 5 | from bs4 import BeautifulSoup as bs 6 | 7 | username = 'test@gmail.com' 8 | password = 'test' 9 | 10 | time_sleep = 0.05 11 | time_out = 5 12 | def wait_for_load(cond, driver): # wait for loading info 13 | cnt = time_out / time_sleep # max try 14 | while cond(driver) and cnt > 0: 15 | sleep(time_sleep) 16 | cnt -= 1 17 | 18 | def load_cond(driver): 19 | return len(bs(driver.page_source, 'html.parser').findAll(id='semester_m')) == 0 20 | 21 | if __name__ == "__main__": 22 | driver = webdriver.Chrome() 23 | # login 24 | driver.get("https://apply-psd.uchicago.edu/account/login?r=https%3a%2f%2fapply-psd.uchicago.edu%2fapply%2faca") 25 | driver.find_element_by_id("_pc_1").click() 26 | driver.find_element_by_id("email").send_keys(username) 27 | driver.find_element_by_id("password").send_keys(password) 28 | driver.find_element_by_xpath("(.//*[normalize-space(text()) and normalize-space(.)='Forgot Your Password?'])[1]/following::button[1]").click() 29 | driver.find_element_by_link_text("Education").click() 30 | driver.find_element_by_link_text("Add Course").click() 31 | # load courses 32 | raw = open('course.txt').read().split('\n')[:-1] 33 | for s in raw: 34 | print(s) 35 | c = s.split('\t') 36 | t = c[5].split('-') 37 | mm = {'Autumn': 'September', 'Summer': 'July', 'Spring': 'February'}[t[1]] 38 | sleep(2) 39 | wait_for_load(load_cond, driver) 40 | Select(driver.find_element_by_id("semester_m")).select_by_visible_text(mm) 41 | Select(driver.find_element_by_id("semester_y")).select_by_visible_text(t[0]) 42 | driver.find_element_by_id("name").send_keys(c[1]) 43 | driver.find_element_by_xpath("(.//*[normalize-space(text()) and normalize-space(.)='Save'])[1]/following::button[1]").click() 44 | -------------------------------------------------------------------------------- /course.txt: -------------------------------------------------------------------------------- 1 | 12090043 Military Theory and Skill Training 3 B+ 3.6 2016-Summer 0 8 40 3 2 | 01550013 Synthetical Practice of Electronics System Design 3 P N/A 2016-Autumn 1 0 5 8 3 | S1510041 Exploration to Scientific Research of Lab(3) 1 P N/A 2017-Spring 1 0 1 8 4 | -------------------------------------------------------------------------------- /ethz.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from selenium import webdriver 3 | from selenium.webdriver.support.ui import Select 4 | 5 | username = 'test@gmail.com' 6 | password = 'test' 7 | 8 | if __name__ == "__main__": 9 | driver = webdriver.Chrome() 10 | # login 11 | driver.get("https://www.lehrbetrieb.ethz.ch/eApply/ealogin.view?lang=en") 12 | driver.find_element_by_name("ea_mail").send_keys(username) 13 | driver.find_element_by_name("ea_password").send_keys(password) 14 | driver.find_element_by_xpath("(.//*[normalize-space(text()) and normalize-space(.)='Forgot your password?'])[1]/following::input[1]").click() 15 | driver.get("https://www.lehrbetrieb.ethz.ch/eApply/overview.view?indx=0") 16 | driver.find_element_by_link_text("Courses").click() 17 | # load courses 18 | raw = open('course.txt').read().split('\n')[:-1] 19 | for s in raw: 20 | print(s) 21 | c = s.split('\t') 22 | driver.find_element_by_id("add").click() 23 | Select(driver.find_element_by_id("subjectCategory")).select_by_visible_text("Course") 24 | driver.find_element_by_id("title").send_keys(c[1]) 25 | driver.find_element_by_id("academicYear").send_keys(c[5].split('-')[0]) 26 | driver.find_element_by_id("courseNumber").send_keys(c[0]) 27 | driver.find_element_by_id("weeks").send_keys(c[9]) 28 | driver.find_element_by_id("hoursTutorial").send_keys(c[6]) 29 | driver.find_element_by_id("hoursLectures").send_keys(c[7]) 30 | driver.find_element_by_id("hoursPracticalWork").send_keys(c[8]) 31 | driver.find_element_by_id("grade").send_keys(c[3]) 32 | driver.find_element_by_id("credits").send_keys(c[2]) 33 | driver.find_element_by_id("store").click() 34 | -------------------------------------------------------------------------------- /harvard.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from time import sleep 3 | from selenium import webdriver 4 | from selenium.webdriver.support.ui import Select 5 | from bs4 import BeautifulSoup as bs 6 | 7 | username = 'test@gmail.com' 8 | password = 'test' 9 | 10 | time_sleep = 0.05 11 | time_out = 5 12 | def wait_for_load(cond, driver): # wait for loading info 13 | cnt = time_out / time_sleep # max try 14 | while cond(driver) and cnt > 0: 15 | sleep(time_sleep) 16 | cnt -= 1 17 | 18 | def load_cond(driver): 19 | return len(bs(driver.page_source, 'html.parser').findAll(id='semester_m')) == 0 20 | 21 | math_courses = ''' 22 | Calculus A(1) 23 | Calculus A(2) 24 | Linear Algebra(1) 25 | Linear Algebra(2) 26 | Introduction to Complex Analysis 27 | Stochastic Mathematical Methods 28 | Numerical Analysis 29 | '''.split('\n')[:-1] 30 | 31 | english_courses = ''' 32 | Listening & Speaking for Academic Purposes (1) 33 | Listening & Speaking for Academic Purposes (2) 34 | Listening & Speaking for Academic Purposes (3) 35 | Listening & Speaking for Academic Purposes (4) 36 | Foreign Language Application 37 | Reading & Writing for Argumentative Essays 38 | Art English(1) 39 | Art English(2) 40 | '''.split('\n')[:-1] 41 | 42 | if __name__ == "__main__": 43 | driver = webdriver.Chrome() 44 | # login 45 | driver.get("https://apply.gsas.harvard.edu/account/login") 46 | driver.find_element_by_id("email").send_keys(username) 47 | driver.find_element_by_id("password").send_keys(password) 48 | driver.find_element_by_xpath("(.//*[normalize-space(text()) and normalize-space(.)='Forgot Your Password?'])[1]/following::button[1]").click() 49 | driver.get('https://apply.gsas.harvard.edu/apply/aca') 50 | driver.find_element_by_link_text("Add Course").click() 51 | # load courses 52 | raw = open('course.txt').read().split('\n')[:-1] 53 | for s in raw: 54 | print(s) 55 | c = s.split('\t') 56 | t = c[5].split('-') 57 | mm = {'Autumn': 'September', 'Summer': 'July', 'Spring': 'February'}[t[1]] 58 | sleep(2) 59 | wait_for_load(load_cond, driver) 60 | Select(driver.find_element_by_id("semester_m")).select_by_visible_text(mm) 61 | Select(driver.find_element_by_id("semester_y")).select_by_visible_text(t[0]) 62 | driver.find_element_by_id("name").send_keys(c[1]) 63 | Select(driver.find_element_by_id("level")).select_by_visible_text("Undergraduate") 64 | driver.find_element_by_id("number").send_keys(c[0]) 65 | driver.find_element_by_id("grade").send_keys(c[3]) 66 | Select(driver.find_element_by_id("courses_foreign_language")).select_by_visible_text("Yes" if c[1] in english_courses else "No") 67 | Select(driver.find_element_by_id("courses_mathematics")).select_by_visible_text("Yes" if c[1] in math_courses else "No") 68 | driver.find_element_by_xpath("(.//*[normalize-space(text()) and normalize-space(.)='Save'])[1]/following::button[1]").click() 69 | 70 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # ETHz/Chicago/Harvard courses auto upload 2 | 3 | n+e 4 | 5 | ## Dependency 6 | 7 | Python3, selenium, bs4 8 | 9 | For installing selenium, you can refer to [here](https://morvanzhou.github.io/tutorials/data-manipulation/scraping/5-01-selenium/). 10 | 11 | For installing Beautiful soup: `pip3 install bs4 --user`. 12 | 13 | ps. I test the script in Chrome driver. If you use Firefox, please replace the `Chrome` in script. 14 | 15 | ## Usage 16 | 17 | 1. Replace your username and password in `ethz.py` or `chicago.py` or `harvard.py`; 18 | 19 | 2. Add your courses into `course.txt`. For Tsinghua students, it can directly copy the courses from English transcript page in [info](http://zhjw.cic.tsinghua.edu.cn/cj.cjCjbAll.do?m=bks_cjdcx&cjdlx=yw); 20 | 21 | 3. (Only for ETHz application) You should add the last 4 terms in `course.txt`; 22 | 23 | (Only for Harvard application) You should complete `math_courses` and `english_courses` in `harvard.py`; 24 | 25 | 4. `python3 ethz.py` or `python3 chicago.py` or `python3 harvard.py`; 26 | 27 | 5. Have a cup of tea. 28 | 29 | ## Format 30 | 31 | The **full** format in `course.txt` is as follows (in a single line, separated by Tab): 32 | 33 | - Course ID (12090043) 34 | - Course Name (Military Theory and Skill Training) 35 | - Credit (3) 36 | - Grade (B+) 37 | - Points (3.6) 38 | - Semester (2016-Summer) 39 | - hours Tutorial (0) (only for ETHz) 40 | - hours Lectures (8) (only for ETHz) 41 | - hours Practical Work (40) (only for ETHz) 42 | - Weeks (3) (only for ETHz) 43 | 44 | which results in: `12090043 Military Theory and Skill Training 3 B+ 3.6 2016-Summer 0 8 40 3` 45 | 46 | ## What does it look like? 47 | 48 | [Demo](http://ml.cs.tsinghua.edu.cn/~jiayi/video/IMG_7360.mov) --------------------------------------------------------------------------------