일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 그리디
- jpa
- 컴퓨터 구조
- Cloud Pub/Sub
- 생활코딩
- 데이터 분석
- 수학
- 다익스트라
- 삼성 SW 역량테스트
- CI/CD
- 우선순위 큐
- Cloud Run
- REACT
- 삼성SW역량테스트
- BFS
- JavaScript
- 펜윅 트리
- ICPC
- 종만북
- 고속 푸리에 변환
- Air Table
- dp
- 시뮬레이션
- Bit
- 다이나믹 프로그래밍
- r
- LCS
- 접미사 배열
- 이분탐색
- 백준 1753번
- Today
- Total
코딩스토리
크롤링 연습 - 백준 채점 현황으로 출석 체크 하기 본문
산학 프로젝트 관련 준비로 크롤링을 공부하려고 구글링을 해봤다.
일단 Youtube에는 대부분 파이썬으로 크롤링을 하는데 우리는 JavaScript를 사용할 예정이므로 더 찾아보니
크롤링을 하려면 Ajax, Axios, Cheerio... 등등 공부할게 너무 많았다.
지금 공부한 게 0, 말 그대로 바닥이어서 일단은 가장 많이 들어보고 언젠간 반드시 해야 할 것 같았던 Ajax를 공부하기 시작했다.
생코 강의를 열심히 듣다가 밥 먹고 잠깐 침대에 누워서 Yotube를 켰는데 무슨 알고리즘인지 추천 영상에 Open Api를 활용하는 영상이 있었다.
그 영상을 보니 Javascript, JQuery, Ajax를 사용하여 Api를 사용하는 방법을 대충? 알게 되었다.
갑자기 소학뽕에 취해 Api를 가져와서 코딩해볼까 하고 앉았는데.. 지금 그게 중요한 게 아니었다..
어쨌든 지금은 크롤링을 어떻게 하는지 감을 찾는 게 중요하므로 간단한 주제로 시도해보려고 한다.
주제 : 백준 채점 현황 기록을 가져와서 해당 문제를 풀었는지 안 풀었는지 확인하기
일단 백준의 채점 현황에 들어가서 어떤 식으로 html이 이루어져 있는지 확인해봤다.
잘 보면 정말 다행히도 해당 페이지에는 tbody 태그가 하나밖에 없고, 이 tbody 태그 안에 내가 원하는 정보들이 들어있었다.
일단은 가장 중요한 건 이 html을 받아오는 거여서 그것부터 해보자 생각하고 해 봤는데... 왜 안됨?
에이.. 설마..???
(이 간격이 3시간임)
와... 3시간 만에 해결함
const axios = require('axios');
const cheerio = require('cheerio');
const url = 'https://www.acmicpc.net/status?user_id=kimtaehyun98';
axios.get(url)
.then(adata => {console.log(adata);})
.catch(err => {console.log(err);});
이 코드를 cmd에서 실행시키는데 계속 안됨.
구글링 2시간 + 혼자 속으로 욕하기 1시간 후
stack overflow에서 node-modules 삭제해보란 글을 보고 삭제 후
node index.js로 실행시켜 보니
axios 모듈이 없다고 나와서 다시 npm install axios 한 후 실행시켜보니
후.. 겨우 겨우 어찌 저지 가져오긴 했다.
이제부터 시작인듯하다.... (진짜 울고 싶다.. 이 길은 내 길이 아닌 거 같아..)
이제부터는 구글링 스킬이 중요하다.
일단 내가 원하는 정보는 문제 번호와 맞았는지 틀렸는지이다.
문제 번호부터 가져와보자. (코드는 아래에 첨부할게요)
앞의 '/problem/'은 필요 없기 때문에 substr로 제거해줬다.
이제 다음으로 맞았는지 틀렸는지를 확인해야 한다.
처음에 html을 분석하다가 착각한 부분이 있었다.
내가 원한 건 정확히 "맞았습니다!!"라는 text인데 이게 이상하게 불러와지지가 않았다.
(아직도 잘 모르겠음..ㅠ)
그래서 혹시나 해서 다시 html을 째려보고 있었는데 뭔가 해결책이 보였다.
잘 보면 "맞았습니다!!"를 받은 문제의 클래스 이름은 "result-ac"로 되어있고 틀렸으면 "result-wa"로 되어있었다.
이 방법으로 하면 오히려 더 좋다.
처음 방법대로 "맞았습니다!!"를 불러오면 "100점" 같이 서브 태스크가 있는 문제들을 판별해낼 수가 없었다.
오히려 좋아!!
일단 가져왔으니 이쁘게 바꿔보자.
어차피 필요한 건 "ac" 또는 "wa" 이므로 이번에도 substr을 사용했다.
후.. 거의 다 됐다.
이제부터는 단순 알고리즘이다.
내가 생각한 알고리즘은 다음과 같다.
- 미리 문제 번호 지정 (3문제)
- 각 문제 번호마다 지정된 문제 번호와 일치하는지 확인한다.
- 일치한다면 'ac' 인지 'wa'인지 확인한다.
굉장히 단순하면서 간단한 알고리즘이다.
(설명하기에는 너무 귀찮고 더러워서.. 코드로 남길게요)
이렇게 해서 실행시켜보면!!
정상적으로 출력이 된다!
전체 코드는 다음과 같다.
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
|
const axios = require('axios');
const cheerio = require('cheerio');
const url = 'https://www.acmicpc.net/status?user_id=kimtaehyun98';
let problem_num = [];
let YesorYes = [];
axios.get(url)
.then(all_data => {
// 성공적으로 data(html)를 받아왔다면
console.log("Success!!");
// cheerio 모듈을 사용하여 data를 저장하고
var $ = cheerio.load(all_data.data);
// 해당 html중 <tbody> 태그의 <tr> 태그의 3번째 <td> 태그의 <a> 태그의 href 를 가져오면 된다.
$('tbody>tr>td:nth-child(3)>a').each((index, item) => { // 여기서 each는 반복문이라 생각하면 됨!
problem_num.push(item.attribs.href.substr(9)) // 문제 번호를 저장하기
});
// 해당 html중 <tbody> 태그의 <tr> 태그의 4번째 <td> 태그의 <span> 태그의 <span>의 클래스 이름을 가져오면 된다.
$('tbody>tr>td:nth-child(4)>span>span').each((index, item) => { // 여기서 each는 반복문이라 생각하면 됨!
var name = item.attribs.class;
YesorYes.push(name.substr(7,2));
});
let today_problem = ['11559', '1477', '9370'];
let doit = [false, false, false];
for(let i = 0; i < problem_num.length; i++){
let numb_index = today_problem.indexOf(problem_num[i]); // 제출한 문제가 오늘 풀어야 하는 문제에 해당하는지 확인
if(numb_index != -1) { // 오늘 풀어야 했던 문제라면
if(YesorYes[i] === 'ac'){ // ac를 받았다면
doit[numb_index] = true; // true로 변경 = 풀었다!
}
}
}
// 출력을 위해 푼 문제 번호 저장한 배열 생성
var print_arr = [];
for(let i = 0; i < 3; i++){
if(doit[i] === true) print_arr.push(today_problem[i]); // true라면 푼 문제로 추가
}
var check = '결석';
if(today_problem.length === print_arr.length) check = '출석';
// 몇 문제 풀었는지, 다 풀었는지 안풀었는지, 말 그대로 출석부 출력
console.log(
`********************************************************
id : kimtaehyun98
오늘 풀어야 하는 문제 번호 : ${today_problem}
푼 문제 번호 : ${print_arr}
출석 : ${check}
********************************************************`
)
})
.catch(err => {console.log(err);});
|
cs |
어찌 저찌 크롤링에 입문하긴 했지만 아직은.. 많이 어렵다 ㅎ
이번 크롤링의 한계점
1. 원하는 id를 미리 저장해야 함 (url을 미리 저장해놓았음)
-> 이건 바꾸는 건 어렵지 않을 것 같다. 사용자에게 입력받고 그걸 url로 만들어서 주면 될 듯?
2. 문제 번호 고정 (미리 저장해 놓음)
-> 이것의 해결방법도 1번과 비슷할 듯
3. 서브 태스크 있는 문제 판별 불가
-> 해결!
4. web을 화면으로 어떻게 띄워야 하는지 모르겠음
-> 공부 예정
'Web > JavaScript' 카테고리의 다른 글
HTTP 프로토콜 (1) | 2021.04.11 |
---|---|
ES6 공부 (0) | 2021.02.25 |
5. 실행 컨텍스트와 클로저 (0) | 2021.01.19 |
4. 함수와 프로토타입 체이닝 - 2 (0) | 2021.01.15 |
4. 함수와 프로토타입 체이닝 - 1 (3) | 2021.01.11 |