반응형

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

## Jsoup API

  • Java HTML Parser.
  • 사용법이 간단하고 인기 많은 파서. ( 자바에서 html 을 파싱할 수 있도록 도와주는 라이브러리 )
  • HTML 에 포함된 특정 단어를 분리하기 위해 사용하는 자바 라이브러리로 데이터 추출, 가공 등에 효율적. (CSS, DOM 객체 등 핸들링에도 사용, 제이쿼리와 유사한 성질의 API)
  • https://jsoup.org 
 

jsoup: Java HTML parser, built for HTML editing, cleaning, scraping, and XSS safety

jsoup: Java HTML Parser jsoup is a Java library for working with real-world HTML. It provides a very convenient API for fetching URLs and extracting and manipulating data, using the best of HTML5 DOM methods and CSS selectors. jsoup implements the WHATWG H

jsoup.org

 

Maven Repository: jsoup

jsoup is a Java library for working with real-world HTML. It provides a very convenient API for fetching URLs and extracting and manipulating data, using the best of HTML5 DOM methods and CSS selectors. jsoup implements the WHATWG HTML5 specification, and

mvnrepository.com

## Jsoup 의 주요 요소

  1. Document (Document Object Model) : Jsoup 얻어온 결과 HTML 전체 문서 
  2. Element (=Node) : Document 의 HTML 요소
  3. Elements : Element 가 모인 자료형으로 반복문 사용 가능. (for, while 등)
  4. Connection : Jsoup 의 connect 혹은 설정 메소드들을 이용하여 만들어지는 객체로 연결을 하기 위한 정보를 담고 있다.
  5. Response : Jsoup 가 URL 에 접속해 얻어온 결과로 Document 와 다르게 status 코드, status 메시지, charset 등 헤더 메시지와 쿠키 등을 갖고 있다.

## Jsoup API 이용한 크롤링

  • Jsoup 이용하여 네이버 스포츠 크롤링.
  • 크롬 등 에서 개발자 도구를 이용하여 해당 HTML 의 트리구조 확인. (원하는 부분의 데이터를 가져오기 위해 확인 필요)
  • 구현 로직.
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class Project02_A {
	public static void main(String[] args) {
		
		// 크롤링 할 사이트 주소.
		String url = "https://sports.news.naver.com/wfootball/index.nhn";
		
		Document doc = null;
		
		try {
			doc = Jsoup.connect(url).get();
		} catch (Exception e) {
			System.out.println(e);
		}
		
		// 1. 주요 뉴스로 나오는 태그 찾아서 가져옴.
		Elements element = doc.select("div.home_news");
		
		// 2. 헤더 제목 가져오기.
		String title = element.select("h2").text().substring(0, 4);
		
		System.out.println("====================================");
		System.out.println("헤더 제목 : " + title);
		System.out.println("====================================");
		
		// 3. for문 이용 하위 뉴스 기사들 출력
		for (Element el : element.select("li")) {
			System.out.println(el.text());
		}
		
		System.out.println("====================================");
		
		
	}
}
  • 출력 결과
====================================
헤더 제목 : 추천뉴스
====================================
벤투호 주전 공격수 3인 모두 EPL서 뛰나
토트넘 '폭풍영입'…오히려 위기될 수도?
세계에서 가장 아름다운 축구 선수 "호날두 광팬...첼시 입단이 꿈"
리버풀 마네 대체자 찾았다... 레알서 '커리어 하이' 찍은 공격수
램파드, 콘테 체제 '계륵 MF' 데려간다...토트넘, 320억 가격표 부착
'맨시티는 제2의 도르트문트' 레알, 2024년에 홀란드 영입한다...이적료 2059억
'나이스 원 쏘니' 손흥민, 1017억 원 'LW 세계 3위' 평가!
'이 정도면 복덩이' SON 위상 재확인 "토트넘에 무해할 존재 "
텐 하흐 감독이 가장 원하는 2명, 맨유 유니폼 입나?
맨체스터 지역지 '홀란드, 펩 과르디올라의 새로운 메시 될 것'
사생활 지적에 네이마르 "쉴 땐 쉬어야지" 하소연
나폴리·세비야 같은 명가들, 왜 ‘괴물 수비수’ 원할까
재계약 다섯 달 만에 '충격'…바르사 '계약해지' 초강수
'붉은색+푸른색' 심장 가진 '런던의 사나이', 새로운 도전에 나선다
'연봉 336억 끝내 불발…' 지단, PSG 안 간다 (佛 RMC)
레알, 이적료 2035억으로 홀란드 뺏어온다
'WC 끝으로 대표팀 은퇴?' 네이마르, 동료에게 말했다
'포그바-린가드?' 맨유 신입 CEO의 저격, "라커룸 밀고자 2명 팀 떠났다"
베일·아자르에 가렸던 '먹튀'... 결국 레알 떠나 '2번째 임대'
메시, 음바페에 이어 세 번째…파리 생제르맹 '골든보이 출신' MF 영입
====================================

 

반응형
반응형

# JSON API 활용 (네이버 클라우드 플랫폼 지도 API 이용 지도 GUI 생성)

## 네이버 클라우드 플랫폼 지도 API 활용 (위도, 경도 추출하여 지도 GUI 생성)

  • 주소 입력받은 후 버튼 클릭 시 입력된 주소에 대한 이미지 및 주소 표시.
  • 자바 스윙(javax swing) 이용 지도 GUI 생성.

1. AddressVO

package kr.inflearn;

public class AddressVO {
	private String roadAddress;
	private String jibunAddress;
	private String x;
	private String y;
	
	public AddressVO() {	}

	public AddressVO(String roadAddress, String jibunAddress, String x, String y) {
		super();
		this.roadAddress = roadAddress;
		this.jibunAddress = jibunAddress;
		this.x = x;
		this.y = y;
	}

	public String getRoadAddress() {
		return roadAddress;
	}

	public void setRoadAddress(String roadAddress) {
		this.roadAddress = roadAddress;
	}

	public String getJibunAddress() {
		return jibunAddress;
	}

	public void setJibunAddress(String jibunAddress) {
		this.jibunAddress = jibunAddress;
	}

	public String getX() {
		return x;
	}

	public void setX(String x) {
		this.x = x;
	}

	public String getY() {
		return y;
	}

	public void setY(String y) {
		this.y = y;
	}

	@Override
	public String toString() {
		return "AddressVO [roadAddress=" + roadAddress + ", jibunAddress=" + jibunAddress + ", x=" + x + ", y=" + y
				+ "]";
	}
	
	
}

2. 메인 소스

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.GridLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class Project01_F {
	JTextField address;
	JLabel resAddress, resX, resY, jibunAddress;
	JLabel imageLabel;
	
	public void initGUI() {
		JFrame frm = new JFrame("Map View");                    // 프레임 생성
		frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);     // 프레임의 X 클릭 시 종료.
		Container c = frm.getContentPane();                     // JFrame 안쪽 영역.
		
		imageLabel = new JLabel("지도보기");                    // JFrame 안쪽 영역 상단에 들어갈 지도보기
		JPanel pan = new JPanel();
		JLabel addressLbl = new JLabel("주소입력");             // JFrame 안쪽 영역 상단에 들어갈 주소입력
		address = new JTextField(50);
		JButton btn = new JButton("클릭");                      // JFrame 안쪽 영역에 들어갈 클릭 버튼
		pan.add(addressLbl);
		pan.add(address);
		pan.add(btn);	
		btn.addActionListener(new NaverMap(this));              // pan에 생성한 버튼(btn) 클릭 시 처리하는 이벤트 핸들러.
		
		JPanel pan1 = new JPanel();
		pan1.setLayout(new GridLayout(4, 1));                   // 지도 하단 그리드 4행 1열로 생성.
		resAddress = new JLabel("도로명");                      // 그리드 1행에 들어갈 도로명
		jibunAddress = new JLabel("지번주소");                  // 그리드 2행에 들어갈 지번주소
		resX = new JLabel("경도");                              // 그리드 3행에 들어갈 경도
		resY = new JLabel("위도");                              // 그리드 4행에 들어갈 위도
		pan1.add(resAddress);
		pan1.add(jibunAddress);
		pan1.add(resX);
		pan1.add(resY);
		
		c.add(BorderLayout.NORTH, pan);                         // 상단 pan 세팅
		c.add(BorderLayout.CENTER, imageLabel);                 // 센터 imageLabel 세팅
		c.add(BorderLayout.SOUTH, pan1);                        // 하단 pan1 세팅
		
		frm.setSize(730, 660);
		frm.setVisible(true);
		
	}
	
	public static void main(String[] args) {
		new Project01_F().initGUI();	
	}
}

3. NaverMap

  • 이벤트 발생 시 처리해주는 함수 생성.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Date;

import javax.swing.ImageIcon;

import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;

import kr.inflearn.AddressVO;

public class NaverMap implements ActionListener {

	Project01_F naverMap;
	public NaverMap(Project01_F naverMap) {
		this.naverMap = naverMap;
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		String clientId = "앱 등록 시 발급받은 Client ID";
		String clientSecret = "앱 등록 시 발급 받은 Client Secret";
		AddressVO vo = null;
		
		try {
			String address = naverMap.address.getText();
			String addr = URLEncoder.encode(address, "UTF-8");
			String apiURL = "https://naveropenapi.apigw.ntruss.com/map-geocode/v2/geocode?query=" + addr;
			URL url = new URL(apiURL);
			
			HttpURLConnection con = (HttpURLConnection) url.openConnection();
			con.setRequestMethod("GET");
			con.setRequestProperty("X-NCP-APIGW-API-KEY-ID", clientId);
			con.setRequestProperty("X-NCP-APIGW-API-KEY", clientSecret);
			
			int responseCode = con.getResponseCode();
			BufferedReader br;
			if (responseCode == 200) {
				br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
			} else {
				br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
			}
			
			String inputLine;
			StringBuffer response = new StringBuffer();
			while ((inputLine = br.readLine()) != null) {
				response.append(inputLine);
			}
			br.close();
			
			JSONTokener tokener = new JSONTokener(response.toString());
			JSONObject object = new JSONObject(tokener);
			System.out.println(object);
			
			JSONArray arr = object.getJSONArray("addresses");
			for (int i = 0; i < arr.length(); i++) {
				JSONObject temp = (JSONObject) arr.get(i);
				vo = new AddressVO();
				vo.setRoadAddress((String) temp.get("roadAddress"));
				vo.setJibunAddress((String)temp.get("jibunAddress"));
				vo.setX((String)temp.get("x"));
				vo.setY((String)temp.get("y"));
				System.out.println(vo);
			}
			
			map_service(vo);

		} catch (Exception err) {
			System.out.println(err);
		}
	}
	
	public void map_service(AddressVO vo) {
		String URL_STATICMAP = "https://naveropenapi.apigw.ntruss.com/map-static/v2/raster?";
		
		try {
			String pos = URLEncoder.encode(vo.getX() + " " + vo.getY(), "UTF-8");
			URL_STATICMAP += "center=" + vo.getX() + "," + vo.getY();
			URL_STATICMAP += "&level=16&w=700&h=500";
			URL_STATICMAP += "&markers=type:t|size:mid|pos:" + pos + "|label:" + URLEncoder.encode(vo.getRoadAddress(), "UTF-8");
			
			URL url = new URL(URL_STATICMAP);
			HttpURLConnection con = (HttpURLConnection) url.openConnection();
			con.setRequestMethod("GET");
			con.setRequestProperty("X-NCP-APIGW-API-KEY-ID", "앱 등록 시 발급받은 Client ID");
			con.setRequestProperty("X-NCP-APIGW-API-KEY", "앱 등록 시 발급 받은 Client Secret");
			
			int responseCode = con.getResponseCode();
			BufferedReader br;
			
			// 정상호출인 경우.
			if (responseCode == 200) {
				InputStream is = con.getInputStream();
				
				int read = 0;
				byte[] bytes = new byte[1024];
				
				// 랜덤 파일명으로 파일 생성
				String tempName = Long.valueOf(new Date().getTime()).toString();
				File file = new File(tempName + ".jpg");	// 파일 생성.
				
				file.createNewFile();
				
				OutputStream out = new FileOutputStream(file);
				
				while ((read = is.read(bytes)) != -1) {
					out.write(bytes, 0, read);	// 파일 작성
				}
				
				is.close();
				ImageIcon img = new ImageIcon(file.getName());
				naverMap.imageLabel.setIcon(img);
				naverMap.resAddress.setText(vo.getRoadAddress());
				naverMap.jibunAddress.setText(vo.getJibunAddress());
				naverMap.resX.setText(vo.getX());
				naverMap.resY.setText(vo.getY());
				
			} else {
				System.out.println(responseCode);
			}
			
		} catch(Exception e) {
			System.out.println(e);
		}
		
	}
}

## 결과물

  • 아래 화면에서 주소 입력 후 버튼 클릭.

  • 입력된 주소에 대한 이미지  생성, 하단에 주소 표시.

반응형
반응형

# JSON API 활용 (네이버 클라우드 플랫폼 지도 API 이용 지도 이미지 생성)

## 네이버 클라우드 플랫폼 지도 API 활용 (위도, 경도 추출하여 지도 이미지 생성)

1. Static Map OpenAPI

 

Static Map 개요 - Static Map

 

api.ncloud-docs.com

2. 구현 (Static Map OpenAPI 사용)

 

  • Geocoding OpenAPI 사용하여 구현했던 작업물에 Static Map OpenAPI 사용하여 구현 진행.
  • 파일로 생성하도록 작업.
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Date;

import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;

public class Project01_E {
	public static void main(String[] args) {
		// 주소 입력 -> 위도, 경도 좌표 추출.
		BufferedReader io = new BufferedReader(new InputStreamReader(System.in));	
		String clientId = "8nuzd8r4bi";
		String clientSecret = "gyCPtld0Wnpi2eYr6xsBi4ITu3OnD9trzLa5JM9p";
		
		try {
			System.out.println("주소를 입력해주세요 : ");
			
			String address = io.readLine();
			String addr = URLEncoder.encode(address, "UTF-8");
			
			// Geocoding 개요에 나와있는 API URL 입력.
			String apiURL = "https://naveropenapi.apigw.ntruss.com/map-geocode/v2/geocode?query=" + addr;	// JSON
			
			URL url = new URL(apiURL);
			HttpURLConnection con = (HttpURLConnection) url.openConnection();
			con.setRequestMethod("GET");
			
			// Geocoding 개요에 나와있는 요청 헤더 입력.
			con.setRequestProperty("X-NCP-APIGW-API-KEY-ID", clientId);
			con.setRequestProperty("X-NCP-APIGW-API-KEY", clientSecret);
			
			// 요청 결과 확인. 정상 호출인 경우 200
			int responseCode = con.getResponseCode();
			
			BufferedReader br;
			
			if (responseCode == 200) {
				br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
			} else {
				br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
			}
			
			String inputLine;
			
			StringBuffer response = new StringBuffer();
			
			String x = "";	// 경도
			String y = "";	// 위도
			String z = "";	// 주소
			
			while ((inputLine = br.readLine()) != null) {
				response.append(inputLine);
			}
			
			br.close();
			
			JSONTokener tokener = new JSONTokener(response.toString());
			JSONObject object = new JSONObject(tokener);			
			JSONArray arr = object.getJSONArray("addresses");
			
			for (int i = 0; i < arr.length(); i++) {
				JSONObject temp = (JSONObject) arr.get(i);
				System.out.println("address : " + temp.get("roadAddress"));
				System.out.println("jibunAddress : " + temp.get("jibunAddress"));
				System.out.println("위도 : " + temp.get("y"));
				System.out.println("경도 : " + temp.get("x"));
				
				x = (String) temp.get("x");				// 경도
				y = (String) temp.get("y");				// 위도
				z = (String) temp.get("roadAddress");	// 주소
			}
			
			// Static Map OpenAPI
			map_service(x, y, z);
		
		} catch (Exception  e) {
			System.out.println(e);
		}
	}

	// 지도이미지 생성 메서드.
	public static void map_service(String point_x, String point_y, String address) {
		String URL_STATICMAP = "https://naveropenapi.apigw.ntruss.com/map-static/v2/raster?";
		
		try {
			String pos = URLEncoder.encode(point_x + " " + point_y, "UTF-8");
			String url = URL_STATICMAP;
			
			url += "center=" + point_x + "," + point_y;
			url += "&level=16&w=700&h=500";
			url += "&markers=type:t|size:mid|pos:" + pos + "|label:" + URLEncoder.encode(address, "UTF-8");
			
			URL u = new URL(url);
			HttpURLConnection con = (HttpURLConnection) u.openConnection();
			con.setRequestMethod("GET");
			con.setRequestProperty("X-NCP-APIGW-API-KEY-ID", "앱 등록 시 발급받은 Client ID");
			con.setRequestProperty("X-NCP-APIGW-API-KEY", "앱 등록 시 발급 받은 Client Secret");
			
			int responseCode = con.getResponseCode();
			BufferedReader br;
			
			// 정상호출인 경우.
			if (responseCode == 200) {
				InputStream is = con.getInputStream();
				
				int read = 0;
				byte[] bytes = new byte[1024];
				
				// 랜덤 파일명으로 파일 생성
				String tempName = Long.valueOf(new Date().getTime()).toString();
				File file = new File(tempName + ".jpg");	// 파일 생성.
				
				file.createNewFile();
				
				OutputStream out = new FileOutputStream(file);
				
				while ((read = is.read(bytes)) != -1) {
					out.write(bytes, 0, read);	// 파일 작성
				}
				
				is.close();
				
			} else {	// 에러 발생
				br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
				String inputLine;
				StringBuffer response = new StringBuffer();
				
				while ((inputLine = br.readLine()) != null) {
					response.append(inputLine);
				}
				br.close();
			}
			
		} catch(Exception e) {
			System.out.println(e);
		}
		
	}
}

 

 

반응형
반응형

# JSON API 활용 (네이버 클라우드 플랫폼 지도 API 서비스 등록)

  • 네이버, 구글, 다음 등 위도와 경도 관련 서비스를 해주는 다양한 오픈 API 존재.

## 네이버 클라우드 플랫폼 지도 API 서비스 등록

1. 회원가입

 

NAVER CLOUD PLATFORM

cloud computing services for corporations, IaaS, PaaS, SaaS, with Global region and Security Technology Certification

www.ncloud.com

2. 네이버 지도 API 서비스 사용을 위한 등록방법

  • 우측 상단 콘솔 클릭.

  • Service > AI NAVER API 선택.

  • Application 등록 버튼 클릭.

  • Application 이름 설정.

  • 사용하고자 하는 서비스 선택

  • 서비스 환경 등록 관련 정보 입력. (별도로 정해진게 없어도 임의로 등록, 추후 변경)

  • 등록 완료 후 아래 화면에서 인증정보 버튼 클릭하여 정보 확인.

 

## 네이버 클라우드 플랫폼 지도 API 활용 (위도, 경도 추출)

1. Geocoding OpenAPI

 

Geocoding 개요 - Geocoding

 

api.ncloud-docs.com

2. 구현 (Geocoding OpenAPI 사용)

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;

import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.json.simple.parser.JSONParser;

public class Project01_D {
	public static void main(String[] args) {
		// 주소 입력 -> 위도, 경도 좌표 추출.
		BufferedReader io = new BufferedReader(new InputStreamReader(System.in));	
		String clientId = "등록한 네이버 지도 API 인증정보 중 clientId 입력";
		String clientSecret = "등록한 네이버 지도 API 인증정보 중 clientSecret 입력";
		
		try {
			System.out.println("주소를 입력해주세요 : ");
			
			String address = io.readLine();
			String addr = URLEncoder.encode(address, "UTF-8");
			
			// Geocoding 개요에 나와있는 API URL 입력.
			String apiURL = "https://naveropenapi.apigw.ntruss.com/map-geocode/v2/geocode?query=" + addr;	// JSON
			
			URL url = new URL(apiURL);
			HttpURLConnection con = (HttpURLConnection) url.openConnection();
			con.setRequestMethod("GET");
			
			// Geocoding 개요에 나와있는 요청 헤더 입력.
			con.setRequestProperty("X-NCP-APIGW-API-KEY-ID", clientId);
			con.setRequestProperty("X-NCP-APIGW-API-KEY", clientSecret);
			
			// 요청 결과 확인. 정상 호출인 경우 200
			int responseCode = con.getResponseCode();
			
			BufferedReader br;
			
			if (responseCode == 200) {
				br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
			} else {
				br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
			}
			
			String inputLine;
			
			StringBuffer response = new StringBuffer();
			
			while((inputLine = br.readLine()) != null) {
				response.append(inputLine);
			}
			
			br.close();
			
			JSONTokener tokener = new JSONTokener(response.toString());
			JSONObject object = new JSONObject(tokener);			
			JSONArray arr = object.getJSONArray("addresses");
			
			for (int i = 0; i < arr.length(); i++) {
				JSONObject temp = (JSONObject) arr.get(i);
				System.out.println("address : " + temp.get("roadAddress"));
				System.out.println("jibunAddress : " + temp.get("jibunAddress"));
				System.out.println("위도 : " + temp.get("y"));
				System.out.println("경도 : " + temp.get("x"));
			}
			
			// JSON.simple 사용한 경우 아래와 같이 진행.
			/*JSONParser jpr = new JSONParser();
			JSONObject jarr = (JSONObject) jpr.parse(response.toString());
			JSONArray arr2 = (JSONArray) jarr.get("addresses");
			
			for (int i = 0; i < arr2.length(); i++) {
				JSONObject temp = (JSONObject) arr.get(i);
				System.out.println("address : " + temp.get("roadAddress"));
				System.out.println("jibunAddress : " + temp.get("jibunAddress"));
				System.out.println("위도 : " + temp.get("y"));
				System.out.println("경도 : " + temp.get("x"));
			}*/
		
		} catch (Exception  e) {
			System.out.println(e);
		}
	}
}
반응형

+ Recent posts