1. 스프링부트 + 몽고DB 연결
2. 크롤링 (뉴스 데이터)
3. 몽고 저장 - 배치프로그램 (1분마다)
4. API 컨트롤러 구축
5. Flask 서버 만들어서 API 호출해서 시각화
1) application.yml 설정
application.properties → 파일명 'yml'로 변경
spring mongodb host → port → database 입력
spring:
data:
mongodb:
host: localhost
port: 27017
database: greendb
2) test 파일 만들어서 JUnit test
public class NaverCrawTest {
int aid = 1;
@Test
public void test1() {
String aidStr = String.format("%010d",aid);
String url = "https://news.naver.com/main/read.naver?mode=LSD&mid=shm&sid1=102&oid=022&aid=" + aidStr;
RestTemplate rt = new RestTemplate();
//html
String html = rt.getForObject(url, String.class);
System.out.println(html);
}
}
* exchange
requestEntity : post, put 사용
responseType : json data를 지정 타입으로 변환해서 받는다.
3) html 분석
* title id 찾기 : #articletitle
* company class 찾기 : .press_log img → 속성값 title 사용
* createdAt class 찾기 : .t11
4) pom.xml jsoup 라이브러리 dependency 추가
- NaverCrawTest 추가
String html = rt.getForObject(url, String.class);
Document doc = Jsoup.parse(html);
Element companyElement = doc.selectFirst(".press_logo img");
String compnayAttr = companyElement.attr("title"); // title 또는 alt
Element titleElement = doc.selectFirst("#articleTitle");
Element createdAtElement = doc.selectFirst(".t11");
String company = compnayAttr;
String title = titleElement.text();
String createdAt = createdAtElement.text();
5) Batch package 생성 후 NaverNewsCrawsBatch 생성
① NewsappApplication
@EnableScheduling
@SpringBootApplication
public class NewsappApplication {
public static void main(String[] args) {
SpringApplication.run(NewsappApplication.class, args);
}
② NaverNewsCrawBatch
- 생성자 사용 시 자동 생성되는 _id를 넣을 수 없으므로 Builder 사용
@RequiredArgsConstructor
@Component
public class NaverNewsCrawsBatch {
private int aid = 1;
private final NaverNewsRepository naverNewsRepository;
@Scheduled(fixedDelay = 1000*60*1)
public void newsCraw() {
List<NaverNews> newsList = new ArrayList<>();
for(int i = 1; i<6; i++) {
String aidStr = String.format("%010d",aid);
String url = "https://news.naver.com/main/read.naver?mode=LSD&mid=shm&sid1=102&oid=022&aid=" +aidStr;
RestTemplate rt = new RestTemplate();
try {
// {"username":"ssar" , "password":"1234"}
String html = rt.getForObject(url, String.class);
Document doc = Jsoup.parse(html);
Element companyElement = doc.selectFirst(".press_logo img");
String compnayAttr = companyElement.attr("title"); // title 또는 alt
Element titleElement = doc.selectFirst("#articleTitle");
Element createdAtElement = doc.selectFirst(".t11");
String company = compnayAttr;
String title = titleElement.text();
String createdAt = createdAtElement.text();
NaverNews nn = NaverNews.builder()
.company(company)
.title(title)
.cratedAt(createdAt)
.build();
newsList.add(nn);
} catch (Exception e) {
System.out.println("통신 오류");
}
aid++;
}
naverNewsRepository.saveAll(newsList);
}
}
③ Domain package 생성
- NaverNews
@Builder
@AllArgsConstructor
@Data
@Document(collection = "naver_news") // 몽고DB 컬렉션 이름 지정
public class NaverNews {
@Id
private String _id;
private String company;
private String title;
private String cratedAt; // 날짜 몽고DB save() 하면 무조건 미국 시간(+9시간)으로 들어감
}
- NaverNewsRepository
public interface NaverNewsRepository extends MongoRepository<NaverNews, String>{
@Query(value="{title: ?0, company: ?1}")
LIst<NaverNews> mFindByTitleAndCompany(String title, String company);
}
④ web package 생성 - controller 생성
@RequiredArgsConstructor
@RestController
public class NaverNewsController {
private final NaverNewsRepository naverNewsRepository;
@GetMapping
public CMRespDto<?> findAll(){
List<NaverNews> naverNewsList = naverNewsRepository.findAll();
return new CMRespDto<>(1,"성공",naverNewsList);
}
}
⑤ web package 내부 dto package 생성 - CMResDto 생성
@AllArgsConstructor
@NoArgsConstructor
@Data
public class CMRespDto<T> {
private int code;
private String msg;
private T data;
}
파이썬 사용해서 Flask로 뿌리기
1. flask, request 설치
# pip install requests
# pip install flask
2. router.py
from flask import Flask, render_template
import requests
app = Flask(__name__)
@app.route('/naverNews')
def naverNews():
response = requests.get("http://localhost:8080/naverNews")
cmRespDto = response.json();
if cmRespDto["code"]==1:
return render_template("index.html", naverNewsList=cmRespDto["data"])
else:
return "데이터를 가져올 수 없습니다"
if __name__ == '__main__':
app.run(debug=True)
3. index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>네이버뉴스 리스트</title>
</head>
<body>
<table border="1">
<tr>
<th>신문사</th>
<th>기사제목</th>
<th>기사발행일</th>
</tr>
{% for naverNews in naverNewsList%}
<tr>
<td>{{naverNews.company}}</td>
<td>{{naverNews.title}}</td>
<td>{{naverNews.createdAt}}</td>
</tr>
{% endfor %}
</table>
</body>
</html>
4. setinterval javascript 추가 ( index.html 에 추가)
<script>
setInterval(function(){
location.reload();
}, 1000*60*1
)
</script>
'Study > 연습' 카테고리의 다른 글
여기어때 홈페이지 크롤링 연습 (1) | 2021.11.15 |
---|---|
빅데이터시스템개발 - test, train Data target/Shuffle/저장 (0) | 2021.10.26 |
Python - 공공API 테스트 (0) | 2021.10.25 |