본문 바로가기

웹_프론트_백엔드/JAVA프레임윅기반_풀스택

2020.04.02

1. API(Application Programming Interface)

 


2. 웹에서는 어떻게 response하고 어떻게 request하는 지 매우 중요

 


3. XML 데이터 담는 용도로 사용


4. json(JavaScript Object Notation)

 

 

5. Node란? 데이터가 가지고 있는 것 
 : Type(Element, Attribute, Text, ... ), name, value

 

6. HTML 코드를 DOM으로 표현

** HTML 문서 **

<!DOCTYPE html>
<html>
	<head>
		<title>hello</title>
	</head>
	<body>
		<a href="http://www.naver.com">text</a>
		<h1>My header</h1>
	</body>
</html>

 

** DOM : https://www.w3schools.com/js/js_htmldom.asp **

 

 

7. 들여쓰기, 공백도 Text 노드로 인식

   [그렇기 때문에...!!] 파싱하기전 꼭꼭 normalize()가 필요!! (필수 필수!!) * 100

 

[실습코드]

 

1. [과제] 크롤링을 이용하여 인터파크 도서 검색, 썸네일 이미지 다운로드

package com.lec.java.crawl07;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Scanner;

import javax.imageio.ImageIO;

import org.jsoup.Jsoup;
import org.jsoup.Connection.Response;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class Crawl07Main {

	// 썸네일 다운로드 추가
	private static final String PATH = "books";
	
	public static void main(String[] args) throws IOException {
		System.out.println("인터파크 도서 검색결과 페이지");
		
		Scanner sc = new Scanner(System.in);
		System.out.print("검색어를 입력하세요 : ");
		String search = sc.nextLine();
		sc.close();

		Crawl07Main app = new Crawl07Main();
		ArrayList<InfoBook> list = app.crawlInterPark(search);
		
		// 썸네일 이미지 다운로드 받기
		int fileIndex = 1;
		for(InfoBook e : list) {
			System.out.println(e);	// 크롤링 정보 출력
			
			// 썸네일 이미지 다운로드
			String fileName = String.format(PATH + File.separator + "thumb%03d.jpg", fileIndex);
			URL imgUrl = new URL(e.getImgUrl());
			
			BufferedImage imgData = ImageIO.read(imgUrl);
			File file = new File(fileName);
			ImageIO.write(imgData, "jpg", file);
			
			System.out.println(fileName + " 이 저장되었습니다");
			fileIndex++;
		}
		
		System.out.println("\n프로그램 종료");
	} // end main()
	
	private ArrayList<InfoBook> crawlInterPark(String search) throws IOException {
		ArrayList<InfoBook> list = new ArrayList<InfoBook>();
		
		String url;
		Document doc;
		Response response;
		Element elements;
		Elements rowElements;
		
        
		// http://mbook.interpark.com/main/
		
		url = "http://bsearch.interpark.com/dsearch/book.jsp?sch=all&sc.shopNo=&bookblockname=s_main&booklinkname=s_main&bid1=search_auto&bid2=product&bid3=000&bid4=001&query=" 
				+ URLEncoder.encode(search, "euc-kr");
		System.out.println(url);
		
		doc = Jsoup.connect(url).execute().parse();
		
		rowElements = doc.select("#bookresult > form").get(0).select("div.list_wrap");
		System.out.println(rowElements.size() + " 개");
		
		for(Element e : rowElements) {
			String imgUrl = e.selectFirst("div.bookImg > div.imgWrap > div.bimgWrap > a > img").attr("src").trim();
			//System.out.println(imgUrl);	// 확인 끄읏~>ㅡ<
			
			Element infoElement = e.selectFirst("div.info > p.tit > b > a");
			
			String bookTitle = infoElement.text().trim();
			String linkUrl = infoElement.attr("href").trim();
			
			//System.out.println(bookTitle + " : " + linkUrl);
			
			String price = e.selectFirst("p.FnowCoupon > span.nowMoney").text().replace(",", "").split("원")[0].trim();
			//System.out.println(price + "!!");	
			
			double prices = Double.parseDouble(e.selectFirst("p.FnowCoupon > span.nowMoney").text().replace(",", "").split("원")[0].trim());
			//System.out.println(price + "원");
			
			list.add(new InfoBook(bookTitle, prices, linkUrl, imgUrl));

		}
		
		return list;
	}

} // end class

 

package com.lec.java.crawl07;

public class InfoBook {
	
	private String bookTitle;	// 책제목
	private double price;		// 책가격
	private String url;		// 상세페이지 url
	private String imgUrl;		// 썸네일 url
	
	// 기본생성자
	public InfoBook() {}
	
	// 매개변수 생성자
	public InfoBook(String bookTitle, double price, String url, String imgUrl) {
		super();
		this.bookTitle = bookTitle;
		this.price = price;
		this.url = url;
		this.imgUrl = imgUrl;
	}
	
	// getter&setter
	public String getBookTitle() {return bookTitle;}
	public void setBookTitle(String bookTitle) {this.bookTitle = bookTitle;}
	public double getPrice() {return price;}
	public void setPrice(double price) {this.price = price;}
	public String getUrl() {return url;}
	public void setUrl(String url) {this.url = url;}
	public String getImgUrl() {return imgUrl;}
	public void setImgUrl(String imgUrl) {this.imgUrl = imgUrl;}
	
	@Override
	public String toString() {
		return bookTitle + ":" + price + "원, URL: " + url + ", img: " + imgUrl;
	}
}



2. Lec32_WebCrawl
1) com.lec.java.crawl08 패키지, Crawl08Main 클래스

package com.lec.java.crawl08;

import java.io.IOException;
import java.net.URLEncoder;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

/*
 * 크롤링 검색 페이징
 * 	- '첫 페이지' url
 * 	- '두번째 페이지'부터의 url 변화 확인 : 어떤 방식? 어떤 parameter 사용?
 * 	- 검색결과 페이징의 '마지막 페이지'는 어떻게 처리하는지 확인 
 */

public class Crawl08Main {

	public static void main(String[] args) throws IOException {
		System.out.println("페이징 : Pagination");
		
		for(int i = 1; i <= 10; i ++) {
			crawlDaumBlog("파이썬", i);
		}
		
		System.out.println("\n프로그램 종료");
	} // end main()

	
	/**
	 * 
	 * @param search 검색어
	 * @param page 검색할 결과 page 번호
	 */
	public static void crawlDaumBlog(String search, int page) throws IOException {
		
		// 목록에서 크롤링 할 내용
		// 	post title
		// 	post link url
		// 	blog title
		
		// 매개변수 검증
		if(search == null || search.trim().length() == 0 || page < 1) {return;}

		String url;
		Document doc;
		Elements elements;
		
		System.out.println(page + " 페이지]");
		
		url = String.format("https://search.daum.net/search?w=blog&DA=PGD&enc=utf8&q=%s&page=%d", 
				URLEncoder.encode(search, "utf-8"), page);
		//System.out.println(url); // 확인용
				
		doc = Jsoup.connect(url).execute().parse();
		
		elements = doc.select("#blogColl .list_info li .wrap_cont");
		//System.out.println(elements.size() + " 개");	// 확인용
		
		for(Element e : elements) {
			String postTitle = e.selectFirst("a").text().trim();
			String blogTitle = e.selectFirst(".info .f_nb").text().trim();
			String postUrl  = e.selectFirst("a").attr("href").trim();
			
			System.out.println(postTitle + " : " + blogTitle + " : " + postUrl);
		} // end for
		
		System.out.println();
		
	} // end crawlDaumBlog()
	
} // end class


2) com.lec.java.crawl09 패키지, Crawl09Main 클래스

package com.lec.java.crawl09;

import java.io.IOException;
import java.net.URLEncoder;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

// 연습
// 네이버 '검색어'
//	-post title
//	-post url
//	-blog title

// 페이징 구현

public class Crawl09Main {
	
	public static void main(String[] args) throws IOException {
		System.out.println("네이버 검색, 페이징");
		
		for(int i = 1; i <= 10; i++) {			
			crawlNaverBlog("파이썬", i);
		}
		
		System.out.println("\n프로그램 종료");
	} // end main()
	
	
	public static void crawlNaverBlog(String search, int page) throws IOException {
		
		// 매개변수 검증
		if(search == null || search.trim().length() == 0 || page < 1) {return;}
		
		String url;
		Document doc;
		Elements elements;
		
		System.out.println(page + "페이지]");
		
		url = String.format("https://search.naver.com/search.naver?date_from=&date_option=0&date_to=&dup_remove=1&nso=&post_blogurl=&post_blogurl_without=&query=%s&sm=tab_pge&srchby=all&st=sim&where=post&start=%d",
				URLEncoder.encode(search, "utf-8"), (page-1) * 10 + 1);
		//System.out.println(url);	// 확인용
		
		doc = Jsoup.connect(url).execute().parse();
		
		elements = doc.select("#elThumbnailResultArea > li.sh_blog_top > dl");
		//System.out.println(elements.size());  // 확인용
		
		for(Element e : elements) {
			String postTitle = e.selectFirst("a.sh_blog_title").text().trim();
			String blogTitle = e.selectFirst("dd.txt_block a.txt84").text().trim();
			String postUrl = e.selectFirst("a.sh_blog_title").attr("href").trim();
			
			System.out.println(postTitle + " : " + blogTitle + " : " + postUrl);
		} // end for
		
		System.out.println();
		
	} // end crawlNaverBlog()

} // end class


3) com.lec.java.crawl10 패키지, Crawl10Main 클래스

package com.lec.java.crawl10;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.json.JSONArray;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/* 
 * XML, Json 파싱1
 * 
 * ■서울시 지하철호선별 역별 승하차 인원 정보 
 * http://data.seoul.go.kr/dataList/datasetView.do?infId=OA-12914&srvType=A&serviceKind=1&currentPageNo=1
 * 
 * 샘플 url
 * XML 버젼 
 * http://openapi.seoul.go.kr:8088/키값을넣으세요/xml/CardSubwayStatsNew/1/5/20181001
 * 예) http://openapi.seoul.go.kr:8088/704c4a6d7262696e33396a544e7551/xml/CardSubwayStatsNew/1/5/20181001
 *   
 * JSON 버젼 
 * http://openapi.seoul.go.kr:8088/키값을넣으세요/json/CardSubwayStatsNew/1/5/20181001
 * 예) http://openapi.seoul.go.kr:8088/704c4a6d7262696e33396a544e7551/json/CardSubwayStatsNew/1/5/20181001 
 * */

/* 
 * JSON 파싱
 * java.io.Reader    프로그램이 '문자 단위' 데이터를 읽어들이는(read) 통로
 * 	├─ java.io.InputStreamReader    // 스트림 기반의 reader
 * 	└─ java.io.BufferedReader 	// 문자(character) 기반 reader
 */

public class Crawl10Main {
	
	public static final String REQ_SERVICE = "CardSubwayStatsNew";
	public static final String API_KEY = "704c4a6d7262696e33396a544e7551";

	public static void main(String[] args) {
		System.out.println("서울시 지하철호선별 역별 승하차 인원 정보");
		
		int startIndex;	// 요청 시작 위치 정수 입력 (페이징 시작번호입니다 : 데이터행 시작번호)
		int endIndex;	// 요청 종료 위치 정수 입력 (페이징 끝번호 입니다 : 데이터 행 끝번호)
		String date;	// 날짜 yyyymmdd 형식
		
		String url_address;
		StringBuffer sb;	// response 받은 텍스트
		
		startIndex = 1;
		endIndex = 5;
		date = "20200329";
		
		System.out.println("--- XML 파싱 ---");
		url_address = buildUrlAddress("xml", startIndex, endIndex, date);
		//System.out.println(url_address);	// URL 확인
		sb = readFromUrl(url_address);
		parseXML(sb.toString());
		
		System.out.println();
		System.out.println("--- JSON 파싱 ---");
		url_address = buildUrlAddress("json", startIndex, endIndex, date);
		//System.out.println(url_address);	// URL 확인
		sb = readFromUrl(url_address);
		parseJSON(sb.toString());
		
		System.out.println("\n프로그램 종료");
	} // end main()
	
	
	public static String buildUrlAddress(String reqType, int startIndex, int endIndex, String date) {
		
		String url_address = String.format("http://openapi.seoul.go.kr:8088/%s/%s/CardSubwayStatsNew/%d/%d/%s", API_KEY, reqType, startIndex, endIndex, date);
		
		return url_address;
	} // end buildUrlAddress()
	
	
	/**
	 * 
	 * @param urlAddress : 주어진 url 주소
	 * @return 서버로부터 받은 텍스트데이터(HTML) 리턴
	 */
	public static StringBuffer readFromUrl(String urlAddress) {
		
		StringBuffer sb = new StringBuffer();	// response 받은 데이터 담을 객체
		
		URL url = null;	// java.net.URL
		HttpURLConnection conn = null;		// java.net.HttpURLConnectrion
		
		InputStream in = null;
		InputStreamReader reader = null;	// byte 스트림 --> 문자기반 Reader
		BufferedReader br = null;
		
		char[] buf = new char[512];		// 문자용 버퍼
		
		// BufferedReader <- InputStreamReader <- InputStream <- HttpURLConnection 
		
		try {
			url = new URL(urlAddress);
			conn = (HttpURLConnection)url.openConnection();  // Connection 객체 생성
			
			if(conn != null) {
				conn.setConnectTimeout(2000);	// 2초이내에 '연결'이 수립안되면
								// java.net.SocketTimeoutException 발생
				
				conn.setRequestMethod("GET");	// GET 방식	request
				// "GET", "POST", ...
				conn.setRequestProperty("Content-Type", 
					"application/x-www-form-urlencoded; charset=UTF-8");
				conn.setUseCaches(false);	// 캐시사용안함
				
				System.out.println("request 시작: " + urlAddress);
				conn.connect();	// request 발생 --> 이후 response 받을때까지 delay
				System.out.println("response 완료");
				
				// response 받은 후 가장 먼저 response code 값 확인
				int restponseCode = conn.getResponseCode();
				System.out.println("response code: " + restponseCode);
				// 참조 : https://developer.mozilla.org/ko/docs/Web/HTTP/Status
				if(restponseCode == HttpURLConnection.HTTP_OK) {
					
					in = conn.getInputStream();	// InputStream <- HttpURLConnection
					reader = new InputStreamReader(in, "utf-8");// InputStreamReader<-InputStream
					br = new BufferedReader(reader); // BufferedReader <- InputStreamReader
					
					int cnt;	// 읽은 글자 개수
					while((cnt = br.read(buf)) != -1) {
						sb.append(buf, 0, cnt);	// response 받은 텍스트를 StringBuffer에 추가
					}
					
				} else {
					System.out.println("response 실패");
					return null;
				}
				
			} else {
				System.out.println("conn null");
				return null;
			}
			
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				br.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			if(conn != null) {conn.disconnect();}	// 작업 끝나고 Connection 해제
		}
		
		return sb;
		
	} // end readFromUrl()

	
	public static void parseXML(String xmlText) {
		// XML 파싱
		DocumentBuilderFactory dbFactory;
		DocumentBuilder dBuilder;
		
		try {
			// DOM parser 객체 생성
			dbFactory = DocumentBuilderFactory.newInstance();
			dBuilder = dbFactory.newDocumentBuilder();
			
			// String -> InputStream 변환
			InputStream in = new ByteArrayInputStream(xmlText.getBytes("utf-8"));
			
			// InputStream -> DOM 객체 생성
			Document dom = dBuilder.parse(in);
			
			// DOM 최상위 document element 추출
			Element docElement = dom.getDocumentElement();	// DOM 의 최상위 element
			
			// 파싱하기전 normalize()
			docElement.normalize();		// 흩어진 text node 들을 정렬하는 등의 절차
							// XML 파싱하기 전에 꼭 normalize() 부터 해주자
			
			// DOM 내의 데이터 파싱.
			// <row> ... </row> element 들로 구성된 NodeList 리턴
			NodeList nList = docElement.getElementsByTagName("row");	
			
			System.out.println("<row> 개수 : " + nList.getLength());
			
			System.out.println();
			for (int i = 0; i < nList.getLength(); i++) {
				Node node = nList.item(i);
				
				//System.out.println("node type : " + node.getNodeType());	// node type 확인용
				// element node 인 경우만 파싱 진행
				if(node.getNodeType() != Node.ELEMENT_NODE) {continue;}
				
				// 오른쪽이 부모일 때, 형변환이 필요...!!
				Element rowElement = (Element)node;
				
				String LINE_NUM =
						rowElement.getElementsByTagName("LINE_NUM").item(0).getChildNodes().item(0).getNodeValue().trim();
				String SUB_STA_NM =
						rowElement.getElementsByTagName("SUB_STA_NM").item(0).getChildNodes().item(0).getNodeValue().trim();
				String RIDE_PASGR_NUM =
						rowElement.getElementsByTagName("RIDE_PASGR_NUM").item(0).getChildNodes().item(0).getNodeValue().trim();
				String ALIGHT_PASGR_NUM =
						rowElement.getElementsByTagName("ALIGHT_PASGR_NUM").item(0).getChildNodes().item(0).getNodeValue().trim();
				
				System.out.printf("%5s : %8s역 [승차:%6s 하차:%6s]\n", 
						LINE_NUM, SUB_STA_NM, RIDE_PASGR_NUM, ALIGHT_PASGR_NUM);
			}
				
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	} // end parseXML()
	
	public static void parseJSON(String jsonText) {
		// org.json  라이브러리 다운로드
		// https://mvnrepository.com/artifact/org.json/json
		// 최신버젼 클릭후, Files 항목 클릭해서 다운로드
		
		JSONObject jObj = new JSONObject(jsonText);  // JSON파싱 : JSONObject <- String 
		JSONArray row = jObj.getJSONObject("CardSubwayStatsNew").getJSONArray("row");
		
		System.out.println("<row> 개수: " + row.length());
		System.out.println();

		for(int i = 0; i < row.length(); i++) {
			JSONObject station = row.getJSONObject(i);
			
			String LINE_NUM = station.getString("LINE_NUM");
			String SUB_STA_NM = station.getString("SUB_STA_NM");
			int RIDE_PASGR_NUM = station.getInt("RIDE_PASGR_NUM");
			int ALIGHT_PASGR_NUM = station.getInt("ALIGHT_PASGR_NUM");
			
			System.out.printf("%5s : %8s역 [승차:%6s 하차:%6s]\n", 
					LINE_NUM, SUB_STA_NM, RIDE_PASGR_NUM, ALIGHT_PASGR_NUM);
		} // end for
		
	} // end parseJSON()
	
} // end class

 

4) com.lec.java.crawl11 패키지, Crawl11Main 클래스

package com.lec.java.crawl11;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.json.JSONArray;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/*
 * XML, JSON 파싱 연습
 * ■서울시 지하철 역사 정보
 * http://data.seoul.go.kr/dataList/datasetView.do?infId=OA-12753&srvType=A&serviceKind=1&currentPageNo=1
 * 
 * 샘플url
 * 
 * XML 버젼
 * http://swopenAPI.seoul.go.kr/api/subway/704c4a6d7262696e33396a544e7551/xml/stationInfo/1/5/서울
 * 
 * JSON 버젼
 * http://swopenAPI.seoul.go.kr/api/subway/704c4a6d7262696e33396a544e7551/json/stationInfo/1/5/서울
 * 
 */
public class Crawl11Main {
	
	public static final String REQ_SERVICE = "stationInfo";
	public static final String API_KEY = "704c4a6d7262696e33396a544e7551";	// 내 인증키

	public static void main(String[] args) throws IOException {
		System.out.println("서울시 지하철 역사(station) 정보");
		
		int startIndex;	// 요청 시작 위치 정수 입력 (페이징 시작번호입니다 : 데이터행 시작번호)
		int endIndex;	// 요청 종료 위치 정수 입력 (페이징 끝번호 입니다 : 데이터 행 끝번호)
		String place;	// 날짜 yyyymmdd 형식
		
		String url_address;
		StringBuffer sb;	// response 받은 텍스트
		
		startIndex = 1;
		endIndex = 5;
		place = "서울";
		
		System.out.println("--- XML 파싱 ---");
		url_address = buildUrlAddress("xml", startIndex, endIndex, place);
		//System.out.println(url_address);	// 확인용
		sb = readFromUrl(url_address);
		parseXML(sb.toString());
		
		System.out.println();
		System.out.println();
		System.out.println("--- JSON 파싱 ---");
		url_address = buildUrlAddress("json", startIndex, endIndex, place);
		//System.out.println(url_address);
		sb = readFromUrl(url_address);
		parseJSON(sb.toString());
		
		
		System.out.println("\n프로그램 종료");
	} // end main()
	
	
	public static String buildUrlAddress(String reqType, int startIndex, int endIndex, String place) throws IOException {
		
		String url_address = (String.format("http://swopenapi.seoul.go.kr/api/subway/%s/%s/%s/%d/%d/",
				API_KEY, reqType, REQ_SERVICE, startIndex, endIndex)) 
				+ URLEncoder.encode(place, "utf-8");
		
		return url_address;
	}
	
	/**
	 * 
	 * @param urlAddress : 주어진 url 주소
	 * @return 서버로부터 받은 텍스트데이터(HTML) 리턴
	 */
	public static StringBuffer readFromUrl(String urlAddress) {
		
		StringBuffer sb = new StringBuffer();	// response 받은 데이터 담을 객체
		
		URL url = null;	// java.net.URL
		HttpURLConnection conn = null;	// java.net.HttpURLConnectrion
		
		InputStream in = null;
		InputStreamReader reader = null;	// byte 스트림 --> 문자기반 Reader
		BufferedReader br = null;
		
		char[] buf = new char[512];	// 문자용 버퍼
		
		// BufferedReader <- InputStreamReader <- InputStream <- HttpURLConnection 
		
		try {
			url = new URL(urlAddress);
			conn = (HttpURLConnection)url.openConnection();  // Connection 객체 생성
			
			if(conn != null) {
				conn.setConnectTimeout(2000);	// 2초이내에 '연결'이 수립안되면
								// java.net.SocketTimeoutException 발생
				
				conn.setRequestMethod("GET");	// GET 방식	request
				// "GET", "POST", ...
				conn.setRequestProperty("Content-Type", 
					"application/x-www-form-urlencoded; charset=UTF-8");
				conn.setUseCaches(false);	// 캐시사용안함
				
				System.out.println("request 시작: " + urlAddress);
				conn.connect();	// request 발생 --> 이후 response 받을때까지 delay
				System.out.println("response 완료");
				
				// response 받은 후 가장 먼저 response code 값 확인
				int restponseCode = conn.getResponseCode();
				System.out.println("response code: " + restponseCode);
				// 참조 : https://developer.mozilla.org/ko/docs/Web/HTTP/Status
				if(restponseCode == HttpURLConnection.HTTP_OK) {
					
					in = conn.getInputStream();	// InputStream <- HttpURLConnection
					reader = new InputStreamReader(in, "utf-8");// InputStreamReader<-InputStream
					br = new BufferedReader(reader); // BufferedReader <- InputStreamReader
					
					int cnt;	// 읽은 글자 개수
					while((cnt = br.read(buf)) != -1) {
						sb.append(buf, 0, cnt);	// response 받은 텍스트를 StringBuffer에 추가
						
					}
					
				} else {
					System.out.println("response 실패");
					return null;
				}
				
			} else {
				System.out.println("conn null");
				return null;
			}
			
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				br.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			if(conn != null) {conn.disconnect();}	// 작업 끝나고 Connection 해제
		}
		
		return sb;
		
	}

	public static void parseXML(String xmlText) {
		// XML 파싱
		DocumentBuilderFactory dbFactory;
		DocumentBuilder dBuiler;
		
		try {
			// DOM parser 객체 생성
			dbFactory = DocumentBuilderFactory.newInstance();
			dBuiler = dbFactory.newDocumentBuilder();
			
			// String -> InputStream 변환
			InputStream in = new ByteArrayInputStream(xmlText.getBytes("utf-8"));
			
			// InputStream -> DOM 객체 생성
			Document dom = dBuiler.parse(in);
			
			// DOM 최상위 document element 추출
			Element docElement = dom.getDocumentElement();	// DOM 의 최상위 element
			
			// 파싱하기전 꼭꼭 normalize()!!!
			docElement.normalize();	// 흩어진 text node 들을 정렬하는 등의 절차
			
			// DOM 내의 데이터 파싱.
			// <row> ... </row> element 들로 구성된 NodeList 리턴
			NodeList nList = docElement.getElementsByTagName("row");	
			
			System.out.println("<row> 개수 : " + nList.getLength());
			
			//statnNm     subwayId subwayNm
			//역이름	호선 id	이름
			
			System.out.println();
			for (int i = 0; i < nList.getLength(); i++) {
				Node node = nList.item(i);
				
				//System.out.println("node type : " + node.getNodeType());
				// element node 인 경우만 파싱 진행
				if(node.getNodeType() != Node.ELEMENT_NODE) {continue;}
				
				// 오른쪽이 부모일 때, 형변환이 필요...!!
				Element rowElement = (Element)node;
				
				String statnNm =
						rowElement.getElementsByTagName("statnNm").item(0).getChildNodes().item(0).getNodeValue().trim();
				String subwayId =
						rowElement.getElementsByTagName("subwayId").item(0).getChildNodes().item(0).getNodeValue().trim();
				String subwayNm =
						rowElement.getElementsByTagName("subwayNm").item(0).getChildNodes().item(0).getNodeValue().trim();
				
				System.out.println((i + 1) + " "+ statnNm + "역 " + subwayId + " " + subwayNm);
			}
			
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	} // end parseXML()
	
	public static void parseJSON(String jsonText) {

		JSONObject jObj = new JSONObject(jsonText);	// JSON 파싱 <- String
		JSONArray row = jObj.getJSONArray("stationList");
		
		System.out.println("<row> 의 개수 : " + row.length());
		System.out.println();
		
		for(int i = 0; i < row.length(); i++) {
			JSONObject station = row.getJSONObject(i);
			
			String statnNm = station.getString("statnNm");
			String subwayId = station.getString("subwayId");
			String subwayNm = station.getString("subwayNm");
			
			System.out.println((i + 1) + " "+ statnNm + "역 " + subwayId + " " + subwayNm);

		} // end for
		
	} // end parseJSON()
	
} // end class


5) com.lec.java.crawl12 패키지, Crawl12Main 클래스

package com.lec.java.crawl12;

import java.io.IOException;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.parser.Parser;
import org.jsoup.select.Elements;

/*
 * Jsoup 를 사용한 XML 파싱
 */

public class Crawl12Main {
	
	public static final String REQ_SERVICE = "CardSubwayStatsNew";
	public static final String API_KEY = "704c4a6d7262696e33396a544e7551";

	public static void main(String[] args) throws IOException {
		System.out.println("서울시 지하철호선별 역별 승하차 인원 정보");
		String url = buildUrlAddress("xml", 1, 5, "2020.03.29");
		
		// XML 파싱할 때는 xml parser를 사용한다.
		Document doc = Jsoup.connect(url).parser(Parser.xmlParser()).get();
		Elements elements = doc.select("row");
		
		for(Element e : elements) {
			String LINE_NUM =
					e.selectFirst("LINE_NUM").text().trim();
			String SUB_STA_NM = 
					e.select("SUB_STA_NM").text().trim();
			String RIDE_PASGR_NUM = 
					e.select("RIDE_PASGR_NUM").text().trim();
			String ALIGHT_PASGR_NUM = 
					e.select("ALIGHT_PASGR_NUM").text().trim();
			
			System.out.printf("%5s : %8s역 [승차:%6s 하차:%6s]\n", 
					LINE_NUM, SUB_STA_NM, RIDE_PASGR_NUM, ALIGHT_PASGR_NUM);
		}
		
	} // end main()

	
	public static String buildUrlAddress(String reqType, int startIndex, int endIndex, String date) {
		
		String url_address = String.format("http://openapi.seoul.go.kr:8088/%s/%s/CardSubwayStatsNew/%d/%d/%s", API_KEY, reqType, startIndex, endIndex, date);
		
		return url_address;
	} // end buildUrlAddress()


} // end class

'웹_프론트_백엔드 > JAVA프레임윅기반_풀스택' 카테고리의 다른 글

2020.04.06  (0) 2020.04.06
2020.04.03  (0) 2020.04.03
2020.04.01  (0) 2020.04.01
2020.03.31  (0) 2020.03.31
2020.03.30  (0) 2020.03.30