이전 포스팅에서 로그인 성공 후 응답으로 돌아온 토큰을 로컬스토리지에 저장하는 것까지 성공했다.
이후 로그인이 된 상태를 유지해야 하고 로그인 여부에 따라 다른 UI를 보여줘야 한다.
많은 페이지의 UI를 다르게 띄워줘야하는데 페이지마다 로컬 스토리지의 토큰을 get 해와서 처리하는 것은 번거로울 것 같았다.
그래서 생각해낸 방법은 useContext를 사용해서 전역으로 로그인 상태를 관리하는 것이었다.
로그인 된 상태 true / 로그인 하지 않은 상태 false 로 처리해서 전역변수 처리를 한 다음
다른 UI를 띄워줘야할 때 true/false 값을 활용해 간단하게 처리할 수 있는 것이다.
해야할 것은 1. LoginContext.jsx 생성하여 전역 변수로 선언해주기 2. 로그인하면 isLoggedIn 값을 true로 변경 3. 로그아웃하면 isLoggedIn 값을 false로 변경 4. 다른 컴포넌트에서 isLoggedIn 값 활용하여 다른 UI 띄우기 !
로그인 시도(/login)를 했을 때 - 동아리원O, 동의O -> 로그인 성공(200) -> 메인으로 이동 - 동아리원O, 동의X -> 401 에러 -> 동의 항목 페이지로 이동 -> 동의하기(/agree) -> 로그인 재시도(/login) -> 로그인 성공(200) - 동아리원X -> 400 에러 -> 로그인 불가능
// 로그인
const handleLogin = async () => {
try {
console.log(studentInfo)
const result = await API().post('/login', studentInfo); // 로그인 성공
console.log(result);
navigate('/user'); // 사용자 메인으로 이동
} catch (error) {
if (error.response) {
const statusCode = error.response.status;
if (statusCode === 400) { // 400 : 학번 or 이름 틀렸을 경우
setFailModalOpen(!failModalOpen);
setStudentInfo({
studentId: '',
name: ''
});
} else { // 401 : 개인정보 동의하지 않았을 경우
setModalOpen(!modalOpen);
}
}
}
};
로그인을 성공했을 때는 navigate로 페이지를 이동 시켜주고
실패했을 때는 에러 코드에 따라 다른 처리를 해주었다.
에러코드 === 400 > 동아리 소속이 아닌사람 (동아리원X)
해당 창이 뜨면서 로그인 실패
에러코드 === 401 > 동아리 소속이지만 동의항목을 거치지 않은 사람(동아리원O, 동의X)
개인정보 수집이용 동의 모달창을 띄워준다.
이후 모달창에서 동의를 누르면 서버(/agree)로 동아리원 정보가 전달되고 서버에서 전달받은 동아리원의 isAgree 항목을 true로 변경함.
// 동의했을 때
const handleAgree = async () => {
try {
await API().post('/agree', studentInfo); // 성공적으로 처리되면
handleLogin(studentInfo); // 다시 로그인 함수 호출
} catch (error) {
console.log(error)
}
}
이후 다시 로그인 재시도(/login)를 하면 동아리원O, 동의O 이므로 로그인 성공(200) !
로그인 성공시 돌아온 토큰 저장
const result = await API().post('/login', studentInfo); // 로그인 성공
navigate('/user'); // 사용자 메인으로 이동
localStorage.clear()
localStorage.setItem('Token', result.data.accessToken)
로그인을 성공하게 되면 서버에서 토큰을 발행해주는데 이 토큰을 어딘가에 저장해두어야 한다.
행, 열에 들어갈 데이터 추가한 후 wb.save('저장할 경로') 로 저장하면 해당 폴더에 엑셀 시트가 만들어지는 것을 볼 수 있다.
이 코드를 데이터 크롤링하는 코드와 합쳐보면
# 가져온 데이터 엑셀파일로 저장
import requests
from bs4 import BeautifulSoup
import openpyxl
fpath = r'C:\Users\tmdgm\Desktop\pyex\주거정책_data.xlsx'
wb = openpyxl.load_workbook(fpath)
ws = wb.active # 현재 활성화된 시트 선택 - 기본시트 선택
row = 2
for i in range(1, 5):
response = requests.get(f'https://youth.incheon.go.kr/youthpolicy/youthPolicyInfoList.do?menudiv=dwelling&pgno={i}')
html = response.text
soup = BeautifulSoup(html, 'html.parser')
titles = soup.select(".boardList .con-box .tit") # 정책 title
links = soup.select(".boardList .btn-box .btn:first-child") # 정책 url
# for link in links:
# url = link.attrs['href']
# print(f'https://youth.incheon.go.kr{url}')
for title in titles:
print(title.text.strip())
ws[f'B{row}'] = title.text
row += 1
wb.save(fpath)
# 크롤링 기본
import requests
from bs4 import BeautifulSoup
# 크롤링하고 싶은 url get해오기
response = requests.get("https://youth.incheon.go.kr/youthpolicy/youthPolicyInfoList.do?")
html = response.text # html 전체 코드 들어있음.
soup = BeautifulSoup(html, 'html.parser') # html 번역기
# soup.select > 여러개 / soup.select_one > 한 개 선택
titles = soup.select(".tit")
for title in titles:
print(title.text.strip())
설치한 라이브러리들을 import 해준다.
requests.get("URL")로 내가 크롤링하고 싶은 주소를 넣는다.
성공적으로 가져와졌다면 response 출력시 <Response [200]> 이 뜰 것이다.
이후 html번역기인 html.parser를 활용
soup.select() < css 선택자를 활용하여 가져오고 싶은 태그 선택
select > 한 개 선택
select_one > 여러 개 선택
.tit가 여러 개라면 리스트 형태로 titles에 들어온다.
반복문으로 title를 출력
성공 나이쓰 !
3. 링크 가져오기
import requests
from bs4 import BeautifulSoup
response = requests.get("https://youth.incheon.go.kr/youthpolicy/youthPolicyInfoList.do?menudiv=dwelling")
html = response.text
soup = BeautifulSoup(html, 'html.parser')
titles = soup.select(".boardList .con-box .tit") # 정책 title
links = soup.select(".boardList .btn-box .btn:first-child") # 해당 정책 URL 접근
for link in links:
url = link.attrs['href']
print(f'https://youth.incheon.go.kr{url}')
위와 비슷한 코드이다.
다른 은 a태그 href 속성을 활용하여 url을 가져온 것
link에는 a 태그가 들어가 있다.
link.attrs['href'] : 해당 링크의 url을 가져올 수 있다.
위의 '~ 인천시 청년월세 지원사업' 들의 해당 정책 상세보기 링크에 접근할 수 있는 것!
4. 여러 페이지 가져오기
정책들이 여러 페이지로 이루어져 있을 것이다.
페이지를 이동할 때마다 변경되는 url을 보고 활용하면 된다.
페이지가 이동될 때 pgno= 1, 2로 변경되는 것을 볼 수 있다.
# 여러 페이지 가져오기
import requests
from bs4 import BeautifulSoup
pageNum = 1
for i in range(1, 10):
print(f'{pageNum}페이지입니다.')
response = requests.get(f'https://youth.incheon.go.kr/youthpolicy/youthPolicyInfoList.do?menudiv=dwelling&pgno={i}')
html = response.text
soup = BeautifulSoup(html, 'html.parser')
titles = soup.select(".boardList .con-box .tit") # 정책 title
for title in titles:
print(title.text.strip())
pageNum += 1