반응형

# Naver Search API 활용 (Excel파일 읽기)

## 준비물

  • https://mvnrepository.com/ 에서 필요한 API 다운로드
  • Apache POI API : 마이크로소프트에서 만든 파일의 데이터를 핸들링 할 수 있는 API.
  • commons-codec API, commons-collections API

poi-4.0.1.jar
2.59MB
commons-codec-1.15.jar
0.34MB
commons-collections4-4.4.jar
0.72MB

  • Excel 파일 생성 (title, author, company, isbn, imageUrl 항목으로 데이터 입력)

## 작업소스

  • ExcelVO
package kr.inflearn;

public class ExcelVO {
	String title;
	String author;
	String company;
	String isbn;
	String imageUrl;
	public ExcelVO() {}
	public ExcelVO(String title, String author, String company, String isbn, String imageUrl) {
		super();
		this.title = title;
		this.author = author;
		this.company = company;
		this.isbn = isbn;
		this.imageUrl = imageUrl;
	}
	public ExcelVO(String title, String author, String company) {
		super();
		this.title = title;
		this.author = author;
		this.company = company;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getAuthor() {
		return author;
	}
	public void setAuthor(String author) {
		this.author = author;
	}
	public String getCompany() {
		return company;
	}
	public void setCompany(String company) {
		this.company = company;
	}
	public String getIsbn() {
		return isbn;
	}
	public void setIsbn(String isbn) {
		this.isbn = isbn;
	}
	public String getImageUrl() {
		return imageUrl;
	}
	public void setImageUrl(String imageUrl) {
		this.imageUrl = imageUrl;
	}
	@Override
	public String toString() {
		return "ExcelVO [title=" + title + ", author=" + author + ", company=" + company + ", isbn=" + isbn
				+ ", imageUrl=" + imageUrl + "]";
	}
}
  • Project03_A
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;

import kr.inflearn.ExcelVO;

public class Project03_A {
	public static void main(String[] args) {
		String filename = "bookList.xls";
		
		List<ExcelVO> data = new ArrayList<ExcelVO>();
		
		try (FileInputStream fis = new FileInputStream(filename)) {
			HSSFWorkbook workbook = new HSSFWorkbook(fis);	// bookList.xls 파일을 가리킴.
			HSSFSheet sheet = workbook.getSheetAt(0);		// Excel 파일 첫번째 시트.
			Iterator<Row> rows = sheet.rowIterator();		// Excel 파일 첫번째 시트 내 row.
			rows.next();									// 두번째 row부터 시작되도록 함.
			
			String[] imsi = new String[5];
			
			while (rows.hasNext()) {
				HSSFRow row = (HSSFRow) rows.next();
				Iterator<Cell> cells = row.cellIterator();
				
				int i = 0;
				while (cells.hasNext()) {
					HSSFCell cell = (HSSFCell) cells.next();
					imsi[i] = cell.toString();
					i++;
				}
				
				// 데이터 저장 시 : 묶음(VO) -> 담기(List)
				ExcelVO vo = new ExcelVO(imsi[0], imsi[1], imsi[2], imsi[3], imsi[4]);
				data.add(vo);
			}
			showExcelData(data);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void showExcelData(List<ExcelVO> data) {
		for (ExcelVO vo : data) {
			System.out.println(vo);
		}
	}
}
  • 실행 시 아래와 같이 출력

반응형
반응형

# Jsoup API 활용 (Jsoup API 이용한 크롤링(GUI 버전))

  • 년월입 선택하여 특정 사이트에서 데이터 가져와서 보여주기.
  • 응용해서 다양하게 활용할 수 있을것 같다.

  • 작업소스
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import org.jsoup.Jsoup;
import org.jsoup.nodes.*;
import org.jsoup.select.Elements;
public class Project02_F extends JFrame implements ActionListener, ItemListener{
	private Choice chyear, chmonth;
	private JLabel yLabel, mLabel;
	private JTextArea area;
	GregorianCalendar gc;
	private int year, month;
	private JLabel[] dayLabel = new JLabel[7];
	private String[] day={"일","월","화","수","목","금","토"};
	private JButton[] days = new JButton[42];	// 7일이 6주이므로 42개의 버튼필요
	private JPanel selectPanel = new JPanel();
	private GridLayout grid = new GridLayout(7, 7, 5, 5);	// 행,열,수평갭,수직갭
	private Calendar ca = Calendar.getInstance();
	private Dimension dimen, dimen1;
	private int xpos, ypos;
	
	public static void main(String[] args) {
		new Project02_F();
	}
	
	public Project02_F(){
		setTitle("웹 페이지 크롤링 GUI : " + ca.get(Calendar.YEAR) + "년" + (ca.get(Calendar.MONTH)+1) + "월" + ca.get(Calendar.DATE) + "일");
		setSize(900,600);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		dimen	= Toolkit.getDefaultToolkit().getScreenSize();
		dimen1	= this.getSize();
		xpos	= (int) (dimen.getWidth()/2 - dimen1.getWidth()/2);
		ypos	= (int) (dimen.getHeight()/2 - dimen1.getHeight()/2);
		
		setLocation(xpos, ypos);	// 화면 가운데 출력.
		setResizable(false);
		setVisible(true);
		
		chyear	= new Choice(); 
		chmonth	= new Choice();
		yLabel	= new JLabel("년"); 
		mLabel	= new JLabel("월");
		
		init();
	}
	
	public void init(){
		select();
		calendar();
	}	
	
	@Override
	public void actionPerformed(ActionEvent arg0) {
		area.setText("");
		String year		= chyear.getSelectedItem();
		String month	= chmonth.getSelectedItem();
		JButton btn		= (JButton) arg0.getSource();
		String day		= btn.getText();
		String bible	= year + "-" + month + "-" + day;
		
		// Jsoup API : HTML파싱
		String url="https://sum.su.or.kr:8888/bible/today/Ajax/Bible/BodyMatter?qt_ty=QT1&Base_de="+bible+"&bibleType=1";
	    
		try {
			Document doc = Jsoup.connect(url).post();

			Element bible_text=doc.select(".bible_text").first();			
			Element bibleinfo_box=doc.select("#bibleinfo_box").first();
			
			// dailybible_info
			Element dailybible_info=doc.select("#dailybible_info").first();
			area.append(dailybible_info.text()+"\n");
			area.append(bible_text.text()+"\n");
			area.append(bibleinfo_box.text()+"\n");
			
			Elements liList=doc.select(".body_list > li");
			
			for (Element  li : liList) {				
				String line=li.select(".info").first().text();
				 
				if (line.length() > 65) {
			 	  line	= line.substring(0,36) 
			 			  + "\n" + line.substring(36,66) 
			 			  + "\n" + line.substring(66) + "\n";	
	 			  area.append(li.select(".num").first().text() + ":" + line);
				} else if (line.length() > 35) {
				  line	= line.substring(0,36) 
						  + "\n" + line.substring(36) + "\n";	
 				  area.append(li.select(".num").first().text() + ":" + line);	
				} else {
				  area.append(li.select(".num").first().text() + ":" + li.select(".info").first().text() + "\n");
				}
			}
		 } catch (Exception e) {
			e.printStackTrace();
		 }		
	}
	
	public void select() {
		JPanel panel = new JPanel(grid);	// 7행 7열의 그리드레이아웃
		
		for (int i = 2022; i >= 2000; i--) {
			chyear.add(String.valueOf(i));
		}
		
		for (int i=1; i <= 12; i++) {
			chmonth.add(String.valueOf(i));
		}
		
		// 레이블에 요일 이름 출력
		for (int i = 0; i < day.length; i++) {
			dayLabel[i] = new JLabel(day[i], JLabel.CENTER);
			panel.add(dayLabel[i]);
		}
		
		dayLabel[6].setForeground(Color.BLUE);	// 토요일 색상
		dayLabel[0].setForeground(Color.RED);	// 일요일 색상
		
		for (int i = 0; i < 42; i++) {	// 버튼 생성 (42개)
			days[i] = new JButton("");	// 제목 없는 버튼 생성
			
			if (i % 7 == 0) {
				days[i].setForeground(Color.RED);	// 일요일 버튼 색
			} else if (i % 7 == 6) {
				days[i].setForeground(Color.BLUE);	// 토요일 버튼 색
			} else {
				days[i].setForeground(Color.BLACK);
			}
			
			days[i].addActionListener(this);
			panel.add(days[i]);
		}
		
		selectPanel.add(chyear);
		selectPanel.add(yLabel);
		selectPanel.add(chmonth);
		selectPanel.add(mLabel);
		
		area=new JTextArea(60, 40);
		area.setCaretPosition(area.getDocument().getLength());
		JScrollPane scrollPane = new JScrollPane(area);  
        
		this.add(selectPanel,	"North");	// 연도와 월을 선택할 수 있는 화면 상단에 출력
		this.add(panel,			"Center");
		this.add(scrollPane,	"East");
		
		String m = (ca.get(Calendar.MONTH) + 1) + "";
		String y = ca.get(Calendar.YEAR) + "";
		
		chyear.select(y);
		chmonth.select(m);
		chyear.addItemListener(this);
		chmonth.addItemListener(this);
	}
	
	public void calendar() {
		year		= Integer.parseInt(chyear.getSelectedItem());
		month		= Integer.parseInt(chmonth.getSelectedItem());
		gc			= new GregorianCalendar(year, month-1, 1);
		int max		= gc.getActualMaximum(gc.DAY_OF_MONTH);	// 해당 달의 최대 일 수
		int week	= gc.get(gc.DAY_OF_WEEK);	//해당 달의 시작 요일

		String today		= Integer.toString(ca.get(Calendar.DATE));	// 오늘 날짜
		String today_month	= Integer.toString(ca.get(Calendar.MONTH) + 1);	// 현재 달

		for (int i = 0; i < days.length; i++) {
			days[i].setEnabled(true);
		}
		
		// 시작일 이전 버튼 비 활성화
		for (int i = 0; i < week-1; i++) {
			days[i].setEnabled(false);
		}
		
		for (int i = week; i < max+week; i++) {
			days[i-1].setText((String.valueOf(i-week+1)));
			days[i-1].setBackground(Color.WHITE);
			
			// 오늘이 속한 달과 같은 달인 경우
			if (today_month.equals(String.valueOf(month))) {
				//버튼의 날짜와 오늘날짜가 일치하는 경우
				if (today.equals(days[i-1].getText())) {
					days[i-1].setBackground(Color.CYAN);	// 버튼의 배경색 지정
				}
			}
		}
		
		// 날짜 없는 버튼 비활성화
		for (int i = (max+week-1); i < days.length; i++) {
			days[i].setEnabled(false);
		}
	}
	
	@Override
	public void itemStateChanged(ItemEvent arg0) {
		Color color = this.getBackground();
		
		if (arg0.getStateChange() == ItemEvent.SELECTED) {
			// 년 or 월 선택 시 기존 달력을 지우고 새로 작성.
			for (int i = 0; i < 42; i++) {
				if (!days[i].getText().equals("")) {
					days[i].setText("");	// 기존 날짜 지움
					days[i].setBackground(color);	// 달력의 배경색과 동일한 색으로 버튼의 배경색 설정
				}
			}
			
			calendar();
		}
	}
}

 

반응형
반응형

# Jsoup API 활용 (Jsoup API 이용한 크롤링(리소스 다운로드))

  • 웹 페이지에 존재하는 리소스의 종류는 다양함 (파일, 영상, 이미지 등)
  • 스레드 생성하여 다운로드 받을 수 있도록 진행.
  • 리소스 크롤링의 경우 저작권 등 주의.
  • 동영상, 이미지 크롤링 구현 로직
import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.jsoup.Jsoup;
import org.jsoup.select.Elements;

import kr.inflearn.DownloadBroker;

import org.jsoup.nodes.*;

public class Project02_C {
	public static void main(String[] args) {
		String url1 = "사이트 주소 입력";
		String url2 = "http://ncov.mohw.go.kr/";
		
		try {			
			Document doc1 = Jsoup.connect(url1).post();
			Document doc2 = Jsoup.connect(url2).post();

			// 리소스 다운로드.
			// 1. mp3
			Element source1 = doc1.select("tr .list").first();
			System.out.println(source1);
			String audio = source1.attr("src").trim();
			System.out.println(audio);
			String fileName1 = audio.substring(audio.lastIndexOf("/")+1);		
			Runnable r1 = new DownloadBroker(audio, fileName1);
			Thread dLoad1 = new Thread(r1);
			dLoad1.start();

			// 2. image
			Element source2 = doc2.select("img").first();
			String imgUrl = "http://ncov.mohw.go.kr/" + source2.attr("src").trim();
			System.out.println(imgUrl);
			String fileName2 = imgUrl.substring(imgUrl.lastIndexOf("/")+1);
			Runnable r2 = new DownloadBroker(imgUrl, fileName2);
			Thread dLoad2 = new Thread(r2);
			dLoad2.start();
			
			for (int i = 0; i < 10; i++) {
				try {
					Thread.sleep(1000);	// 1초 = 1000
				} catch (Exception e) {
					e.printStackTrace();
				}
				System.out.println(" " + (i+1));
			}
			System.out.println();
			System.out.println("================================");
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
}
package kr.inflearn;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;

public class DownloadBroker implements Runnable {
	private String address;
	private String fileName;
	
	public DownloadBroker(String address) {
		this.address = address;
	}
	
	public DownloadBroker(String address, String fileName) {
		this.address = address;
		this.fileName = fileName;
	}
	
	@Override
	public void run() {
		try {
			FileOutputStream fos = new FileOutputStream(fileName);
			BufferedOutputStream bos = new BufferedOutputStream(fos);
			URL url = new URL(address);
			InputStream is = url.openStream();
			BufferedInputStream input = new BufferedInputStream(is);
			
			int data;
			while ((data = input.read()) != -1) {
				bos.write(data);
			}
			bos.close();
			input.close();
			System.out.println("다운로드 완료...");
			System.out.println(fileName);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
반응형
반응형

# Jsoup API 활용 (Jsoup API 이용한 웹 페이지 크롤링2)

## 웹 페이지 클롤링 하기 (HTML Parsing)

 

실시간 속보 : 네이버 금융

관심종목의 실시간 주가를 가장 빠르게 확인하는 곳

finance.naver.com

  • 위 홈페이지에서 실시간 속보 가져오기.
  • 구현 로직
import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.jsoup.Jsoup;
import org.jsoup.select.Elements;
import org.jsoup.nodes.*;

public class Project02_B {
	public static void main(String[] args) {
		
		String url = "https://finance.naver.com/news/news_list.naver?mode=LSS2D&section_id=101";
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		try {
			System.out.println("[입력 : 숫자 입력] : ");
			String sectionId = br.readLine();		
			url += url + "&section_id2=" + sectionId;
			
			System.out.println("================================");
			Document doc = Jsoup.connect(url).post();
			Element subTitle =  doc.select(".sub_tlt").first();
			System.out.println(subTitle.text());
			
			System.out.println("================================");
			Elements newsList =  doc.select(".newsList .articleSubject");
			for (Element dd : newsList) {
				System.out.println(dd.text());
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		
	}
}
  • 출력 결과
[입력 : 숫자 입력] : 
258
================================
실시간 속보
================================
메디콕스, 호주 그린파머스와 대마 원료 수입독점계약 체결
[속보] 코스피, 2400선 재차 붕괴
삼성증권, 2년만에 '전국 동시 투자설명회' 재개
[ET라씨로] '누리호 발사 D-1'…AP 위성 등 관련주 강세
코스피, 장중 2400선 붕괴…19개월 만에 최저치
코스피·코스닥 또 연저점 경신
[fn마켓워치] 바이와알이 韓신임 대표에 배양호 前한국수력원자력 재생에너지처장 선임
마지노선 무너진 비트·이더…큰손들도 “추가적인 고통 대비”
개장 직후 하락 전환한 코스피, 원/달러 환율은 상승
개장 직후 하락 전환한 코스피·코스닥지수, 원/달러 환율은 상승
[시그널] E&F PE, 폐기물 처리업계 강자로 '우뚝'
[속보] 코스피 장중 2400선 재차 붕괴…2391선
KB證, 서울옥션과 하반기 투자전략·미술투자 세미나
[특징주] 바이오플러스, 미국·중국 필러 시장 진출 기대감… 4%↑
경기 침체 우려에 코스피 연중 최저치 '뚝'…2391.27
[장중시황] 코스피, 하루 만에 2400선 다시 붕괴…외인 '팔자' 낙폭 커져
[속보] 코스피, 장중 2400선 붕괴
[증시신상품] 신한자산운용, S&P500 월배당 ETF
와이즈에이아이, 일본 기업과 'AI 플랫폼' 수출 협약
[속보] 코스피, 장중 2400선 재차 붕괴
반응형

+ Recent posts