Had to recreate project
This commit is contained in:
commit
c395a1ef32
169
RequestCrawler.py
Normal file
169
RequestCrawler.py
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
import sys
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
import requests
|
||||||
|
from requests.auth import HTTPBasicAuth
|
||||||
|
import io
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
from twitter import *
|
||||||
|
import tweepy
|
||||||
|
import difflib
|
||||||
|
# This imports from a file called 'constants'. This is at the moment, the file called 'constants_template'
|
||||||
|
import constants
|
||||||
|
import mail_handler
|
||||||
|
|
||||||
|
# Open a session for requests, which will be used throughout
|
||||||
|
session = requests.session()
|
||||||
|
|
||||||
|
# The config for being able to utilize twitter
|
||||||
|
cfg = {
|
||||||
|
"consumer_key" : constants.cons_key,
|
||||||
|
"consumer_secret" : constants.cons_secret,
|
||||||
|
"access_token" : constants.access_token,
|
||||||
|
"access_token_secret" : constants.access_token_secret
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Setting the Twitter connection up
|
||||||
|
def get_api(cfg):
|
||||||
|
auth = tweepy.OAuthHandler(cfg['consumer_key'], cfg['consumer_secret'])
|
||||||
|
auth.set_access_token(cfg['access_token'], cfg['access_token_secret'])
|
||||||
|
return tweepy.API(auth)
|
||||||
|
|
||||||
|
api = get_api(cfg)
|
||||||
|
|
||||||
|
|
||||||
|
# The main method for scraping Stads
|
||||||
|
def findGrades():
|
||||||
|
|
||||||
|
# Calling the first get to Stads, such that I can get the correct link to follow
|
||||||
|
stads = session.get('https://sbstads.au.dk/sb_STAP/sb/resultater/studresultater.jsp')
|
||||||
|
|
||||||
|
# Getting the response with a meta tag, that I can then follow
|
||||||
|
soup = BeautifulSoup(stads.text, 'html5lib')
|
||||||
|
|
||||||
|
# Finding said meta tag
|
||||||
|
meta_tag_redirect = session.get(soup.find('meta')['content'][6:])
|
||||||
|
|
||||||
|
# This should return 200, since I hopefully found the correct meta tag
|
||||||
|
print(meta_tag_redirect.status_code)
|
||||||
|
|
||||||
|
# Getting the url of the meta tag
|
||||||
|
meta_tag_url = meta_tag_redirect.url
|
||||||
|
|
||||||
|
# Trying to log in to WAYF
|
||||||
|
wayf_login = session.post(meta_tag_url, data={'username':constants.USERNAME,'password':constants.PASSWORD})
|
||||||
|
|
||||||
|
# Should return 200
|
||||||
|
print(wayf_login.status_code)
|
||||||
|
|
||||||
|
soup = BeautifulSoup(wayf_login.text, 'html5lib')
|
||||||
|
|
||||||
|
|
||||||
|
# Finding SAMLResponse, such that I can parse it as a parameter, so WAYF will like me
|
||||||
|
SAMLResponse = soup.find('input', {'name':'SAMLResponse'})['value']
|
||||||
|
|
||||||
|
# Hopefully WAYF does in fact like me
|
||||||
|
wayf = session.post('https://wayf.wayf.dk/module.php/saml/sp/saml2-acs.php/wayf.wayf.dk', data={'SAMLResponse':SAMLResponse})
|
||||||
|
|
||||||
|
# If this returns 200, it does \o/
|
||||||
|
print(wayf.status_code)
|
||||||
|
|
||||||
|
# After concluding that WAYF liked me, we look at the response of WAYF
|
||||||
|
soup = BeautifulSoup(wayf.text, 'html5lib')
|
||||||
|
|
||||||
|
# We then find the new SAMLResponse as well as a string 'RelayState'
|
||||||
|
SAMLResponse = soup.find('input', {'name':'SAMLResponse'})['value']
|
||||||
|
RelayState = soup.find('input', {'name':'RelayState'})['value']
|
||||||
|
|
||||||
|
# We then do the last post, and after this, hopefully we can 'get' Stads
|
||||||
|
SAMLAssertion = session.post('https://sbstads.au.dk/sb_STAP/saml/SAMLAssertionConsumer', data={'SAMLResponse':SAMLResponse,'RelayState':RelayState})
|
||||||
|
|
||||||
|
# If this returns 200, it's go time!
|
||||||
|
print(SAMLAssertion.status_code)
|
||||||
|
|
||||||
|
# Given that the previous print returned 200, we can now get the source code of Stads
|
||||||
|
resultater = session.get('https://sbstads.au.dk/sb_STAP/sb/resultater/studresultater.jsp')
|
||||||
|
|
||||||
|
# Just to check that it returns 200, so we have access
|
||||||
|
print(resultater.status_code)
|
||||||
|
|
||||||
|
# Given that it returned 200, we can now get the source code and thus continue in our adventure to find the grades
|
||||||
|
soup = BeautifulSoup(resultater.text, 'html5lib')
|
||||||
|
|
||||||
|
return soup
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def createGradeFile():
|
||||||
|
soup = findGrades()
|
||||||
|
|
||||||
|
newest_grades = soup.find_all('tr', {'class':'DataSelect'})
|
||||||
|
|
||||||
|
if os.path.isfile('./temp_new_grades.log'):
|
||||||
|
grade_file = open('temp_new_grades.log', 'r+')
|
||||||
|
else:
|
||||||
|
grade_file = open('temp_new_grades.log', 'w+')
|
||||||
|
|
||||||
|
|
||||||
|
for grade in newest_grades:
|
||||||
|
grade_file.truncate()
|
||||||
|
grade_file.write('%s \n' %str.strip(grade.find_all('td')[0].getText()))
|
||||||
|
|
||||||
|
grade_file.close()
|
||||||
|
|
||||||
|
def diffGradeLists():
|
||||||
|
|
||||||
|
createGradeFile()
|
||||||
|
|
||||||
|
new_grade_file = open('./temp_new_grades.log', 'r+')
|
||||||
|
old_grade_file = open('./old_grades.log', 'r+')
|
||||||
|
|
||||||
|
diff = difflib.unified_diff(old_grade_file.readlines(), new_grade_file.readlines(), fromfile='file1', tofile='file2', lineterm="\n", n=0)
|
||||||
|
lines = list(diff)[2:]
|
||||||
|
added = [line[1:] for line in lines if line[0] == '+']
|
||||||
|
removed = [line[1:] for line in lines if line[0] == '-']
|
||||||
|
|
||||||
|
new_courses = []
|
||||||
|
|
||||||
|
for line in added:
|
||||||
|
if line not in removed:
|
||||||
|
new_courses.append(line)
|
||||||
|
|
||||||
|
new_grade_file.close()
|
||||||
|
old_grade_file.close()
|
||||||
|
return new_courses
|
||||||
|
|
||||||
|
def checker():
|
||||||
|
|
||||||
|
new_grades = diffGradeLists()
|
||||||
|
new_grade_file = open('./temp_new_grades.log', 'r+')
|
||||||
|
old_grade_file = open('./old_grades.log', 'r+')
|
||||||
|
|
||||||
|
grades_string = "New grade(s) in the following course(s):\n"
|
||||||
|
|
||||||
|
if not new_grades:
|
||||||
|
print('There are no new grades')
|
||||||
|
else:
|
||||||
|
with new_grade_file:
|
||||||
|
with old_grade_file:
|
||||||
|
for line in new_grade_file:
|
||||||
|
old_grade_file.write(line)
|
||||||
|
for i in range (0, len(new_grades)):
|
||||||
|
grades_string += (new_grades[i])
|
||||||
|
print(grades_string)
|
||||||
|
mail_handler.handle(grades_string)
|
||||||
|
tweeter(grades_string)
|
||||||
|
|
||||||
|
new_grade_file.close()
|
||||||
|
old_grade_file.close()
|
||||||
|
|
||||||
|
def tweeter(grades):
|
||||||
|
tweet = '{:s}'.format(grades)
|
||||||
|
api.update_status(status=tweet)
|
||||||
|
|
||||||
|
|
||||||
|
checker()
|
||||||
|
|
||||||
|
|
42
Web/WebSubscription.py
Normal file
42
Web/WebSubscription.py
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#!/bin/python3
|
||||||
|
import sqlite3
|
||||||
|
from flask import Flask, session, redirect, url_for, escape, request
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
conn = sqlite3.connect('../mailing_list')
|
||||||
|
c = conn.cursor()
|
||||||
|
|
||||||
|
@app.route('/subscribe')
|
||||||
|
def login():
|
||||||
|
return '''
|
||||||
|
<form action="/added_email" method="POST">
|
||||||
|
<p> Enter information and click submit, in order to subscribe to the mailing list </p>
|
||||||
|
<input type="text" name="email" placeholder="Enter Email Address" style="width:10%"></input>
|
||||||
|
<br>
|
||||||
|
<p> Pick study</p>
|
||||||
|
<select name="studie" style="width:10%">
|
||||||
|
<option value=""></option>
|
||||||
|
<option value="Datalogi">Datalogi</option>
|
||||||
|
</select>
|
||||||
|
<br><br>
|
||||||
|
<input type="submit" value="Submit">
|
||||||
|
</form>
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/added_email', methods=['POST'])
|
||||||
|
def hello():
|
||||||
|
|
||||||
|
email = request.form['email']
|
||||||
|
studie = request.form['studie']
|
||||||
|
|
||||||
|
query = "insert into mails (email, studie) values (?, ?)"
|
||||||
|
c.execute(query, (email, studie))
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return 'I inserted: %s and %s, into the database' % (email, studie)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(port=2047)
|
19
constants_template.py
Normal file
19
constants_template.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
# Username for STADS
|
||||||
|
USERNAME = 'username'
|
||||||
|
|
||||||
|
# Password for STADS
|
||||||
|
PASSWORD = 'password'
|
||||||
|
|
||||||
|
# Consumer Key (API Key)
|
||||||
|
cons_key = 'insert consumer key here'
|
||||||
|
# Consumer Secret (API Secret)
|
||||||
|
cons_secret = 'insert consumer secret here'
|
||||||
|
# Access Token
|
||||||
|
access_token = 'insert access token here'
|
||||||
|
# Access Token Secret
|
||||||
|
access_token_secret = 'insert access token secret here'
|
||||||
|
|
||||||
|
EMAIL_USERNAME = 'username'
|
||||||
|
EMAIL_PASSWORD = 'password'
|
28
mail_handler.py
Normal file
28
mail_handler.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#!/bin/python3
|
||||||
|
import sqlite3
|
||||||
|
import smtplib
|
||||||
|
import constants
|
||||||
|
|
||||||
|
username = constants.EMAIL_USERNAME
|
||||||
|
password = constants.EMAIL_PASSWORD
|
||||||
|
|
||||||
|
conn = sqlite3.connect('mailing_list')
|
||||||
|
cursor = conn.cursor();
|
||||||
|
|
||||||
|
mails = cursor.execute('SELECT email FROM mails')
|
||||||
|
|
||||||
|
def handle(new_grades):
|
||||||
|
fromaddr = username
|
||||||
|
server = smtplib.SMTP('smtp.gmail.com:587')
|
||||||
|
server.starttls()
|
||||||
|
server.login(username, password)
|
||||||
|
msg = new_grades
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for email in mails:
|
||||||
|
toaddr = email
|
||||||
|
server.sendmail(fromaddr, toaddr, msg)
|
||||||
|
|
||||||
|
server.quit()
|
||||||
|
conn.close()
|
Loading…
Reference in New Issue
Block a user