-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCrawler.py
277 lines (239 loc) · 8.98 KB
/
Crawler.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
import os
import csv
import datetime
import requests
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
os.system("clear")
GMAIL = "https://accounts.google.com/signin/v2/identifier?continue=https%3A%2F%2Fmail.google.com%2Fmail%2F&service=mail&sacu=1&rip=1&flowName=GlifWebSignIn&flowEntry=ServiceLogin"
EMAIL_ADDRESS = ""
PASSWORD = ""
CHROME_DRIVER = "/Users/jun/Downloads/chromedriver"
GET_EMAIL_URL = "https://challenges.nomadcoders.co/users/login"
LOGIN_URL = ""
# 파이썬 챌린지 : 5
# JS 챌린지 : 4
CHALLENGE = 5
# 처음 참가자 수
# 파이썬 챌린지 : 598
# JS 챌린지 : 784
MAX = 598
# 챌린지 시작 날짜
# 파이썬 챌린지 : 2020년 4월 13일 6시
# JS 챌린지 : 2020년 4월 20일 6시
DATE = datetime.datetime(2020, 4, 13, 6)
# 현재 참가자 수
participants=0
# 크롤링데이터
data = []
# 과제 제출 실패 데이터
fail = []
# 로그인 성공 여부
session_Login = False
# 크롬드라이버 선언
driver = webdriver.chrome.webdriver.WebDriver
def setChallenge():
global CHALLENGE
global MAX
global DATE
while True:
print("JS : 4 / Python : 5")
mode = input("Challenge : ")
if( mode == '4'):
CHALLENGE = 4
MAX = 784
DATE = datetime.datetime(2020, 4, 20, 6)
break
elif( mode == '5'):
CHALLENGE = 5
MAX = 598
DATE = datetime.datetime(2020, 4, 13, 6)
break
else:
continue
# 로그인을 위한 데이터 입력
def SetLogin():
print("\t< Gmail Login >")
global EMAIL_ADDRESS
global PASSWORD
EMAIL_ADDRESS = input("email or ID : ")
if (EMAIL_ADDRESS.find("@")== -1):
EMAIL_ADDRESS = EMAIL_ADDRESS + "@gmail.com"
PASSWORD = input("password : ")
# 크롬드라이버 실행
def excuteDriver():
global driver
driver = webdriver.Chrome(CHROME_DRIVER)
# 크롤링 데이터 받아오기
def getData():
# 정상적으로 실행될때 까지 반복
while len(data)==0:
try:
html = linkToPage(CHALLENGE)
addToList(html)
except:
continue
# 노마드코더 로그인 이메일 보내기
def sendEmail():
global driver
driver.implicitly_wait(3) # 로딩 최대 3초 기다리기
# 이메일 받기 위한 작업
driver.get(GET_EMAIL_URL) # 노마드코더 로그인
driver.find_element_by_name('email').send_keys(EMAIL_ADDRESS) # 주소 입력
driver.find_element_by_xpath('/html/body/main/main/div/form/button').click() # 이메일 보내기
# 노마드코더 로그인 이메일 받기
def getEmail():
global LOGIN_URL
global driver
driver.implicitly_wait(3) # 로딩 최대 3초 기다리기
#LOGIN_URL이 존재할때 까지 반복
while True:
# 로그인 성공한 세션이 있을 경우 바로 메일함으로 이동
global session_Login
if(session_Login == False):
global PASSWORD
driver.get(GMAIL) # Gmail 이동
driver.find_element_by_name('identifier').send_keys(EMAIL_ADDRESS) # 주소 입력
driver.find_element_by_id('identifierNext').click() # 다음버튼
WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.NAME, "password"))) # 비밀번호 입력 대기
driver.find_element_by_name('password').send_keys(PASSWORD) # 비밀번호 입력
driver.find_element_by_id('passwordNext').click() # 다음버튼
# 받은편지함 나올때 까지 대기. 실패할경우 로그인 재시도.
try:
WebDriverWait(driver, 5).until(EC.title_contains(('받은편지함'))) # 받은 편지함 로딩 대기
except:
print("Login failed. Retrying...") # 로그인 실패
PASSWORD = input("password : ") # 비밀번호 재입력
continue
session_Login = True # 로그인 성공 세션 저장
else:
driver.get(GMAIL) # 메일함 이동
WebDriverWait(driver, 5).until(EC.title_contains(('받은편지함'))) # 받은 편지함 로딩 대기
# 메일함 목록에 메일이 없을 때 예외처리
try:
print("모든 이메일 확인중")
emails = driver.find_elements_by_class_name("xT") # 모든 이메일 확인
for email in emails: # 노마드코더에서 온 가장 최근의 로그인 이메일 리스트 열기
if(email.find_element_by_class_name("y6").text=="Log in Nomad Challenges"):
email.click()
break
except: # 이메일 존재 유무 예외처리
print("이메일 아예 없어용")
continue
# 로그인 이메일 리스트 로딩 대기
try:
print("이메일 로딩 기다려욤")
WebDriverWait(driver, 3).until(EC.title_contains(('Log in Nomad Challenges')))
except:
print("에러 : 메일 없음 or [로딩 3초 초과]")
continue
# 이메일 크롤링
print("이메일 크롤링해욤")
text_source = driver.page_source
email_soup = BeautifulSoup(text_source,"html.parser")
emails = email_soup.find("div",{"role":"list"}).find_all("div",{"role":"listitem"})
for email in emails:
body = email.text
url = body.rfind('this:')+6
LOGIN_URL = body[url:url+79]
if(LOGIN_URL!=""):
break
print(LOGIN_URL)
return LOGIN_URL
def linkToPage(Challenge):
# 이메일에서 로그인 URL을 받아와서 이동
global driver
driver.get(getEmail())
#Progress Report 접속
driver.get(f"https://challenges.nomadcoders.co/challenges/{Challenge}/report")
html = driver.page_source
return html
def addToList(html):
url_soup = BeautifulSoup(html,"html.parser")
progress = url_soup.find_all("div",{"class":"report__row"})
global participants
for person in progress[1:]:
participants+=1
fail = person.find_all("span",{"class":"report__fail"})
if(len(fail)>=2):
continue
reports = person.find_all("div",{"class":"report__cell"})
items = []
for report in reports:
link = report.find("a", href=True)
if link is None:
item = report.find("span")
items.append(item.get_text())
continue
items.append(link['href'])
data.append(items)
def printList():
global fail
fail = [0] * (len(data[0])-1)
for i in range(len(data)):
print(f"# {i} \t{data[i][0]} :",end="")
for j in range(1,len(data[i])):
print(" ",end="")
if(data[i][j].find("io")!=-1):
print("O",end="")
else:
if(data[i][j]=="X"):
fail[j-1] = fail[j-1] + 1
print(f"{data[i][j]}",end="")
print("\n")
print(f"Total : {MAX}")
print(f"Survivors : {len(data)}")
print(f"Total 🔪💨 : {MAX-len(data)}")
print(f"Total Survivors Rate : {round(len(data)/MAX*100)}%\n")
print(f"People in List : {participants}")
print(f"List's 🔪💨 : {participants-len(data)}")
print(f"List's Survivors Rate : {round(len(data)/participants*100)}%\n")
print(f"Failure in Assignment (from only Survivors) [First Absent]- ")
for i in range(len(fail)):
print(f"\tAssignment {i+1} : {fail[i]} \tFailure Rate (Failure/Survivors) : {round(fail[i]/len(data)*100)}%")
def cvsPrint():
#time = datetime.datetime.now()
#days = (time-DATE).days+1
# csv 파일 출력
try:
f = open(f"result{CHALLENGE}.csv",'r')
day = int(f.readlines()[-1][0])
f.close()
except:
f = open(f"result{CHALLENGE}.csv",'w', newline='')
wr = csv.writer(f)
wr.writerow(['challenge','date','max_participants'])
wr.writerow([CHALLENGE,DATE,MAX])
wr.writerow(['day','num','name','assignment'])
# 이전 데이터 추출
for j in range(1,len(data[0])-1):
for i in range(len(data)):
wr.writerow([j,i+1,data[i][0],data[i][j]])
day = j
f.close()
if( len(data[0]) - 1 > day ):
# 오늘자 데이터 추출
f = open(f"result{CHALLENGE}.csv",'a', newline='')
wr = csv.writer(f)
for i in range(len(data)):
wr.writerow([len(data[i])-1,i+1,data[i][0],data[i][len(data[i])-1]])
f.close()
def checkList():
id=input("\nInput ID : ")
for i in range(len(data)):
if(data[i][0]==id):
print(f"\n{data[i][0]}님 Progress -")
for j in range(1,len(data[i])):
print(f"\tAssignment {j} : {data[i][j]}")
print()
setChallenge()
SetLogin()
excuteDriver()
sendEmail()
getData()
printList()
cvsPrint()
checkList()