반응형

** 웹 요청 시 필요한 데이터

=>url: 주소

=>parameter: 서버에게 넘겨주는 데이터 - dict로 만들어서 부착

=>header: 서버에게 넘겨주는 데이터(보이지 않습니다.) - dict로 만들어서 부착

=>method: 전송방식(GET, POST, DELETE, PUT)

 

**requests 패키지

=>웹에서 데이터를 가져올 때 많이 사용하는 패키지 - 정적인 데이터만 가져올 수 있습니다.

ajax를 이용하지 않는 데이터나 프레임을 사용하지 않는 데이터만 가져올 수 있습니다.

=>이 패키지는 python의 기본 패키지가 아닙니다.

=>pip install requests 로 설치

 

1.데이터를 가져오기 위한 구문

requests.전송방식(url)을 호출하면 Response 객체가 리턴됩니다.

 

2.Response 클래스

status_code 속성: 상태 정보

text: 가져온 데이터를 문자열로 저장

content: 가져온 데이터를 바이트 배열로 저장 - 이미지나 음성 데이터

 

3.parameter heade가 존재하는 경우

requests.전송방식(url, data={파라미터}, headers={헤더})

 

4.실습

http://httpbin.org/get 사이트에 get 방식 요청

get put delete 방식으로 요청

post는 파라미터를 설정해서 요청

Kakao Open API 데이터를 가져오기

 

1)requests 설치 - anaconda를 설치했으면 할 필요가 없습니다.

pip install requests

 

2)get 요청을 위한 코드를 작성

import requests

#requests가 가지고 있는 것들을 현재 커널에 requests 라는 이름으로 가져옴

 

#get 요청을 해서 텍스트를 확인

resp = requests.get('http://httpbin.org/get')

 

#help(requests.get) #함수의 도움말 확인

 

#print(type(resp)) #리턴된 결과의 자료형을 확인

#print(dir(requests.models.Response)) #Response 자료형은 어떤 속성들을 가졌는지 확인

 

print(resp.text) #가져온 문자열을 확인

 

3)put delete 요청을 수행

=>서버에서 지원을 해야 가능

#put delete 요청

 

4)post 방식으로 요청하는 파라미터와 함께 전송

#help(requests.post)

#requests 모듈을 사용하면 파라미터 인코딩을 할 필요가 없습니다.

 

 

5)Open API를 사용하다 보면 header cookie를 이용해야 하는 경우가 있습니다.

headers 옵션이나 cookies 옵션에 dict 형태로 만들어서 추가해주면 됩니다.

 

 

#Kakao Open API 도서 검색 사용

addr = 'https://dapi.kakao.com/v3/search/book'

params = {'query':'삼국지', 'target':'title'}

headers = {'Authorization': ''}

resp = requests.get(addr, params=params, headers=headers)

print(resp.text)

 

6)읽어온 텍스트가 현재 기본 인코딩과 맞지 않아서 텍스트가 깨지는 경우

=>받아온 Response 객체의 encoding 속성에 None을 대입해서 인코딩을 유추하게 만들거나 직접 문자열로 인코딩을 설정하면 됩니다.

utf-8: 전 세계 모든 글자를 인코딩하는 방식 - 3byte 1글자

euc-kr: 예전에 웹에서 한글만을 표현하기 위한 인코딩 방식

cp949(ms949): windows에서 한글만을 표현하기 위한 인코딩 방식

 

cp949 euc-kr은 거의 비슷합니다.

 

iso-8859-1: iso-latin-1 이라고도 하는데 서유럽 문자 표시를 위한 인코딩 방식 - 한글 안됨

 

5.이미지 파일 다운로드

=>Response text 속성 대신에 content 속성을 사용

=>파일 객체를 생성해서 write content 속성의 값을 기록하면 파일로 생성

 

#이미지를 다운로드 받아서 파일로 만들기

 

#이미지를 가져올 URL을 생성

imgurl = 'http://www.onlifezone.com/files/attach/images/962811/376/321/005/2.jpg'

 

resp = requests.get(imgurl)

 

#파일 객체를 만들고 이름은 f로 사용 - close를 할 필요가 없습니다.

with open('2.jpg', 'wb') as f:

    f.write(resp.content)

   

#현재 작업디렉토리 확인

import os

print(os.getcwd())

   

**JSON Parsing

1.JSON

=>속성과 값의 쌍으로 이루어진 데이터 오브젝트를 전달하기 위해 텍스트를 사용하는 개방형 표준 포맷

=>javascript python에서 객체(dictionary) 와 배열(list)의 표현 방법을 가져와서 사용

=>최근의 프로그래밍 언어들은 내장 또는 별도의 라이브러리를 이용해서 이 데이터를 객체로 변환해서 사용합니다.

javascript python은 내장

=>최근의 Open API 그리고 스마트 기기 들의 통신은 대부분 JSON 포맷을 사용

=>[ ]: list, { }: dict

 

2.Python에서의 JSON 파싱

json.loads(json 문자열)

=>문자열을 python 객체로 변환해 줍니다.

 

3.실습

=>카카오 카테고리 검색을 이용해서 음식점 이름과 주소를 list로 만들어서 출력

 

headers = {'Authorization': ''}

 

#웹에서 정적인 데이터를 가져오기 위한 라이브러리를 import

import requests

 

#다운로드 받을 URL 만들기

 

 

#header 만들기

headers = {'Authorization': ''}

 

#데이터 가져와서 출력

resp = requests.get(addr, headers=headers)

text = resp.text

#print(text)

 

#json 파싱 모듈을 가져오기 - 내장 모듈

import json

jsondata = json.loads(text)

#print(type(jsondata)) #맨 처음 시작이 {} 이므로 dict

 

#print(jsondata['documents']) #documents 키의 데이터 가져오기 - list

li = []

#가져온 배열을 행 단위로 읽어서

for imsi in jsondata['documents']:

    #print(imsi['address_name'], ':', imsi['place_name'])

    #place_name address_name을 가지고 dict를 생성

    d = {'장소':imsi['place_name'], '주소':imsi['address_name']}

    #dict list에 추가

    li.append(d)

 

#확인

for temp in li:

    print(temp)

 

 

**HTML Parsing

=>open api가 제공되면 json 이나 xml 형태의 데이터를 받아서 파싱해서 사용하면 됩니다.

=>web site에 보여는 주지만 open api 형태로 제공되지 않는 데이터의 경우 html을 수집해서 파싱을 해서 원하는 데이터를 가져오게 됩니다.

html을 무단 수집하는 것은 법적으로 문제가 되는 경우가 있습니다.

 

1.사용되는 패키지: beatifulsoup4

=>이 패키지는 python에는 없고 anaconda에는 존재

=>이 패키지의 bs4 라는 모듈을 이용

=>bs4.BeautifulSoup(html 텍스트, 'html.parser') 를 호출하면 BeautifulSoap 객체를 리턴

이 객체는 html의 내용을 편리하게 찾을 수 있도록 메모리 트리 형태로 펼쳐놓은 객체 입니다.

 

2.태그로 찾는 경우는 find  findall 이용

find(tag, attributes, recursive, text, limit, keyword)

=>tag가 찾고자 하는 태그

=>attributes 는 태그 안에 속성이 있는 경우 속성명=값 의 형태로 대입해서 속성의 값까지 일치하는 것을 찾습니다.

 

<div id='1'></div>

<div id='2' align='center'></div>

<span id='3'></span>

 

div 다 찾기: find('div')

id 2번인 div 찾기: find('div', align='center')

=>find_all은 사용법은 같은데 find 1개만 찾고 find_all 은 전부 찾아옵니다.

 

3.선택자로 찾는 경우는 select()

=>Tag list로 리턴

 

4.찾은 데이터에서 정보를 추출

1)태그 안의 내용을 가져오기: getText()

2)속성의 값을 가져오기:get('속성명')

 

5.실습1 : https://ko.wikipedia.org/wiki/%EA%B8%B0%EA%B3%84_%ED%95%99%EC%8A%B5

에서 하이퍼링크 태그의 url과 텍스트를 수집

하이퍼링크가 /wiki/로 시작하는 것만 출력

 

 

#위키피디아에서 하이퍼링크(a) 태그의 내용 가져오기

import requests

 

addr = 'https://ko.wikipedia.org/wiki/%EA%B8%B0%EA%B3%84_%ED%95%99%EC%8A%B5'

resp = requests.get(addr)

#print(resp.text)

 

#html 파싱을 위한 라이브러리 가져오기

import bs4

 

#DOM 객체로 만들기

bs = bs4.BeautifulSoup(resp.text, 'html.parser')

#print(type(bs))

 

#a 태그의 내용 가져오기

li = bs.find_all('a')

#print(li)

 

#정규식(문자열 패턴을 조회하기 위한 식) 모듈 import

import re

for temp in li:

    #print(temp.getText()) #태그 안의 내용 가져오기

    #print(temp.attrs['href']) #key 에러 - href가 없는 경우도 있음

    if 'href' in temp.attrs: #href 속성이 temp.attrs에 있는 경우에만

        #href 속성에 /wiki/로 시작하는 링크의 텍스트와 링크만 출력

        href = temp.attrs['href']

        #정규식 생성 - /wiki/ 로 시작하는

        p = re.compile('^(/wiki/)')

        if p.search(href) != None:

            print(temp.getText(), ':', href)

   

6.실습2: https://tv.naver.com/에서 상위 항목의 제목과 링크 가져오기

=>선택자 이용

=>선택자를 찾는 방법은 소스 보기를 해서 직접 찾아도 되고 chrome의 검사 기능에서 필요한 부분을 선택하고 copy selector를 이용해서 찾아도 됩니다.

 

#네이버 tv 팟에서 하이퍼링크(a) 태그의 내용 가져오기

import requests

 

addr = 'https://tv.naver.com/'

resp = requests.get(addr)

#print(resp.text)

 

#html 파싱을 위한 라이브러리 가져오기

import bs4

 

#DOM 객체로 만들기

bs = bs4.BeautifulSoup(resp.text, 'html.parser')

#선택자를 이용해서 선택

tvlist = bs.select('dl > dt > a > tooltip')

for temp in tvlist:

    print(temp.getText())

 

7.태그 속성

태그(중복 가능 - 웹 브라우저에서의 모양) : 선택자로 사용할 때는 tag이름

클래스(중복 가능 - 태그들을 그룹화하기 위한 속성) : 선택자로 사용할 때는 .class이름

아이디(중복 불가능 - 태그를 다른 것과 구별하기 위한 속성) : 선택자로 사용할 때는 #id

 

name(중복 가능 - 서버에게 전송할 때 사용할 파라미터 이름)

xpath(중복 불가능 - 브라우저가 태그를 구분하기 위해서 사용하는 경로)

 

8.실습3

http://www.weather.go.kr/weather/observation/currentweather.jsp 에서 도시이름과 온도, 습도를 가져와서 꺽은선 그래프로 출력

=>찾고자 하는 데이터는 class 이름이 table_develop3

 

#오늘 날씨를 가져와서 그래프 그리기

import requests

 

#필요한 html 가져오기

resp = requests.get('http://www.weather.go.kr/weather/observation/currentweather.jsp')

text = resp.text

#print(text)

 

import bs4

bs = bs4.BeautifulSoup(text, 'html.parser')

#class 속성의 값이 table_develop3 인 데이터 찾아오기

table = bs.select('.table_develop3')

#print(table)

 

#도시이름, 온도, 습도를 저장할 list를 생성

loc = []

temp = []

hum = []

 

#가져온 테이블 중에서 첫번째 테이블로부터 줄(tr) 단위로 읽기

for tr in table[0].find_all('tr'):

    tds = tr.find_all('td') #tr 태그에서 td를 전부 찾아서 tds에 대입

    for td in tds:

        if td.find('a'): #a 태그가 있으면 도시이름이 있는 행입니다.

            #도시이름을 loc 추가

            loc.append(td.find('a').text)

            #온도를 temp에 추가

            temp.append(tds[5].text)

            #습도를 temp에 추가

            hum.append(tds[10].text)

 

#데이터 확인

#인덱싱은 번호1개만 작성해서 하나의 데이터만 추출

print(loc[0:5]) #0-4 번행 까지 확인 - 슬라이싱(범위를 가지고 추출)

print(temp[0:5])

print(hum[0:5])

 

#필요한 도시의 데이터만 추출

cities = ['서울', '부산', '인천', '대구', '대전', '광주', '울산', '창원', '흑산도']

#위 도시들의 온도와 습도를 저장할 list

temperatures = []

humidities = []

 

#cities에 있는 데이터만 추출해서 저장

for city in cities:

    j = 0

    for c in loc:

        if c == city:

            temperatures.append(temp[j])

            humidities.append(hum[j])

            break

        j = j + 1

 

print(cities)

print(temperatures)

print(humidities)

 

#파이썬에서 시각화를 하는 기본 패키지

import matplotlib.pyplot as plt

#한글 폰트 사용을 위한 패키지

from matplotlib import font_manager, rc, rcParams

import platform #운영체제 확인을 위한 패키지

 

#주피터 노트북에서 그래프를 셀 안에 출력해주는 설정

%matplotlib inline

 

#음수를 제대로 표현하기 위한 설정

rcParams['axes.unicode_minus'] = False #이 설정을 하지 않으면 음수가 네모로 출력

 

#한글 폰트 설정

if platform.system() == 'Windows': #윈도우즈라면

    font_name = font_manager.FontProperties(fname='c:/windows/Fonts/ahn_b.ttf').get_name()

    rc('font', family=font_name)

elif platform.system() == 'Darwin': #매킨토시라면

    rc('font', family='AppleGothic')

else:

    print('알 수 없는 운영체제')

   

   

#그래프 그리기

plt.figure(figsize=(12,4), dpi=300) #그래프 크기 설정 - 가로 12inch 세로 4인치

#꺽은선 그래프 - plot

plt.plot(temperatures, label='온도', lw=3, color='r', linestyle='-', marker='s')

#plt.plot(humidities, label='습도', lw=3, color='g', linestyle='-', marker='s')

 

#x

plt.xticks(range(0,len(cities),1), cities, rotation='vertical')

#범례

plt.legend()

plt.savefig('graph.png', dpi=300)

#출력

plt.show()

 

**XML 파싱

=>XML: 데이터를 태그 형식으로 표현하는 표준 데이터 포맷

=>예전에 거의 모든 데이터 포맷이 XML

지금은 우리나라 공공기관 Open API 와 실시간 뉴스를 전송해주는 RSS 그리고 프로젝트 설정 파일에 주로 이용

=>BeautifulSoup xml 패키지를 이용해서 파싱 가능

=>BeautifulSoup를 사용하는 경우 html.parser 대신에 lxml-xml 을 사용하면 됩니다.

 

http://www.hani.co.kr/rss/ 에서 item 태그 안의 title 만 전부 조회

 

#XML 파싱

#http://www.hani.co.kr/rss/ 에서 item 태그의 title만 추출

 

#데이터 가져오기

import requests

resp = requests.get('http://www.hani.co.kr/rss/')

text = resp.text

#print(text)

 

import bs4

#트리로 펼쳐내기

bs = bs4.BeautifulSoup(text, 'lxml-xml')

 

items = bs.find_all('item')

 

for item in items:

    title = item.find('title')

    print(title.getText())

 

 

**Selenium

=>web에서 동적으로 생성되는 데이터는 requests 모듈을 가지고 가져올 수 없습니다.

requests 모듈은 처음 접속했을 때 출력되는 데이터만 가져옵니다.

ajax 처럼 비동기적으로 데이터를 가져오거나 로그인을 한 후 보여지는 데이터들은 requests 모듈로는 가져올 수 없습니다.

이처럼 동적으로 만들어지는 데이터는 브라우저를 직접 실행시켜서 동작시키는 Selenium 이라는 웹 앱 테스트 프레임워크를 이용해야 합니다.

=>웹 애플리케이션을 테스트하기 위한 프레임워크

=>기본 패키지가 아니므로 설치를 해야 합니다.

pip install selenium

 

1.브라우저 동작

=>동작시킬 브라우저의 드라이버를 다운로드

=>브라우저를 동작시키지 않고 가져오고자 하는 경우에는 pantom.js를 이용 - Deprecated

=>크롬을 이용할 것이라서 크롬 드라이버를 다운로드

1)chrome 에서 크롬 정보 확인 - chrome 79 버전

 

2)https://chromedriver.chromium.org/downloads 에서 자신의 버전에 맞는 드라이버를 다운로드

=>압축을 해제하고 exe 파일을 찾기 쉬운곳에 배치 : c:/chromedriver.exe

 

3)브라우저 실행

selenium.webdriver.Chrome("크롬 드라이버 경로")

 

4)실습

#크롬 실행하기

from selenium import webdriver

driver = webdriver.Chrome('c:/chromedriver')

 

2.webdriver 의 메소드

=>implicitly_wait(시간): 초 단위 대기 - 여러 사이트에 데이터를 크롤링 하는 경우 또는 첫 화면에 ajax로 데이터를 호출하는 경우 일정시간 대기시켜서 데이터를 읽어옵니다.

 

=>get(url): 브라우저가 url에 접속

 

=>페이지 내의 element에 접근하는 메소드

find_element_by_name(name을 가지고 접근)

find_element_by_id(id를 가지고 접근)

find_element_by_xpath(xpath를 가지고 접근)

 

find_element_by_css_selector(선택자를 가지고 접근)

find_element_by_class_name(class name을 가지고 접근)

find_element_by_tag_name(tag를 가지고 접근)

 

=>element를 찾으면 입력도구 인 경우는 send_keys() 을 호출하면 값을 입력

=>click()을 호출하면 클릭한 효과

 

앞의 3개는 1개의 데이터를 리턴하고 뒤의 3개는 list 형태로 리턴

 

=>quit(): 브라우저 종료

 

=>execute_script(자바스크립트 코드): 자바스크립트 코드 수행

 

=>page_source 속성: html 가져오기

3.실습

1)실습1. daum 카페 페이지에 접근

 

#다음 카페 목록에 접근하기

#크롬 실행하기

from selenium import webdriver

driver = webdriver.Chrome('c:/chromedriver')

#3초대기

driver.implicitly_wait(3)

 

#다음 카페 목록에 접근 - 로그인 되어 있지 않으면 로그인 페이지로 이동

driver.get('url 주소')

 

2)다음 웹 사이트에 로그인을 한 후에 카페 목록 페이지로 이동

다음 로그인 페이지: url주소

 

#다음에 로그인을 하고 카페 목록으로 이동

from selenium import webdriver

driver = webdriver.Chrome('c:/chromedriver')

#3초대기

driver.implicitly_wait(3)

 

#다음 로그인 페이지로 이동

driver.get('url 주소')

 

#아이디와 비밀번호 입력받기

username = input('아이디를 입력하세요')

userpw = input('비밀번호를 입력하세요')

 

#다음 로그인 페이지에 아이디와 비밀번호 입력

#driver.find_element_by_id('id').send_keys(username)

driver.find_element_by_xpath('//*[@id="id"]').send_keys(username)

driver.find_element_by_xpath('//*[@id="inputPwd"]').send_keys(userpw)

 

#로그인 버튼을 클릭한 후 카페 목록 페이지로 이동

driver.find_element_by_xpath('//*[@id="loginBtn"]').click()

driver.find_element_by_xpath('//*[@id="loginBtn"]').click()

 

#여러 페이지를 이동할 때는 중간에 잠시 대기 시간을 주어야 할 필요가 있습니다.

import time

time.sleep(3) #3초 대기

 

#카페 목록으로 이동

driver.get('http://top.cafe.daum.net/_c21_/my_cafe')

 

#접속한 사이트의 html 가져오기

html = driver.page_source

 

4.frame

=>frame html 페이지 내에서 다른 html 페이지의 내용을 출력하기 위해 사용하는 객체

=>스크래핑을 하다보면 화면에 출력이 되고 페이스 소스에서도 확인이 되는데 접근이 안되는 경우가 있습니다.

이런 경우는 ajax로 나중에 불려졌거나 아니면 프레임을 이용해서 다른 파일에서 출력한 경우입니다.

ajax 의 경우는 딜레이를 주고 데이터를 읽으면 가능합니다.

프레임의 경우는 프레임에 직접 접근해서 데이터를 읽어야 합니다.

 

1)현재 페이지에서 frame 조회

변수 = driver.find_element_by_css_selector('iframe')

for 임시변수 in 변수:

           print(임시변수.get_attribute('name')

 

=>현재 페이지의 모든 iframe의 이름을 조회

 

2)프레임 이동

=>driver.switch_to_frame('프레임이름') : 프레임이름에 해당하는 곳으로 이동

=>driver.switch_to_default_content() :  상위 프레임으로 전환

 

5. 프레임 사용 실습

=>이전 것에 이어서 작성

 

#카페 목록 중에서 첫번째 페이지로 이동

#driver.find_element_by_xpath('//*[@id="mArticle"]/div/div[1]/div/div[2]/ul/li/a/div[1]/div[2]/div/div/strong').click()

 

#직접 카페로 이동 - 카페 글쓰기 페이지로 이동

driver.get('http://cafe.11111daum.net/samhak7/_memo')

 

#특정 프레임으로 이동

driver.switch_to_frame('down')

 

#글작성 란에 텍스트를 입력

driver.find_element_by_xpath('//*[@id="memoForm"]/div/table/tbody/tr[1]/td[1]/div/textarea').send_keys('파이썬에서의 매크로')

driver.find_element_by_xpath('//*[@id="memoForm"]/div/table/tbody/tr[1]/td[2]/a[1]/span[2]').click()

 

6.크롬을 화면에서 출력시키지 않고 데이터 가져오기

=>웹 드라이버를 옵션을 추가해서 생성

#크롬을 화면에 출력하지 않고 실행하기

options = webdriver.ChromeOptions()

options.add_argument('headless')

options.add_argument('window-size=1920x1080')

options.add_argument("disable-gpu")

# 혹은 options.add_argument("--disable-gpu")

 

driver = webdriver.Chrome('c:/chromedriver', chrome_options=options)

 

 

7.20번 스크롤 한 데이터 가져오기

#20번 스크롤 하기

from selenium import webdriver

import time

from selenium.webdriver.common.keys import Keys

import bs4

 

driver = webdriver.Chrome('c:/chromedriver')

 

driver.get('')

time.sleep(5)

 

body = driver.find_element_by_tag_name('body')#스크롤하기 위해 소스 추출

num_of_pagedowns = 20

#10번 밑으로 내리는 것

while num_of_pagedowns:

    body.send_keys(Keys.PAGE_DOWN)

    time.sleep(2)

    num_of_pagedowns -= 1

   

html = bs4.BeautifulSoup(driver.page_source,'html.parser')

print(html)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형

'Study > 데이터 분석' 카테고리의 다른 글

데이터분석-6  (0) 2020.11.10
데이터분석-5  (0) 2020.11.09
데이터분석-4  (0) 2020.11.08
데이터분석-3  (0) 2020.11.08
데이터 분석-1  (0) 2020.11.08
반응형

HTML

1.     Tag: 브라우저가 해석해서 랜더링하기 위한 명령어

A.     하나의 페이지에서 중복될 수 있다.

2.     class: 동일한 디자인을 적용하기 위해서 태그에 적용하는 속성

A.     하나의 페이지에서 중복될 수 있다.

3.     id: 자바스크립트에서 하나의 태그를 구분하기 위해서 적용하는 속성

A.     하나의 페이지에서는 절대로 중복될 수 없다.

4.     name: 서버에서 처리하기 위해 붙이는 이름

A.     중복될 수 있다.

5.     attribute: 태그 내에서 설정하는 옵션으로 key – value 형태로 설정

A.     <태그 옵션이름 = ‘’> : 스크래핑을 할 때는 a 태그의 href 속성이 가장 중요

6.     selector: 별도로 설정하는 것이 아니고 css에서 태그들을 선택하기 위해 만든 문법

A.     태그

B.     .클래스이름

C.     #id

7.     xpath: 별도로 설정하는 것이 아니고 브라우저가 태그의 경로를 나타내기 위해서 사용하는 문법

A.     태그의 경로를 구분해서 나타내기 때문에 중복될 수 없다.

 

 

Java가 실행을 할 때 클래스를 찾는 방법

1.     자신의 애플리케이션에서 찾는다.

2.     1번에서 없으면 jvm이 제공하는 라이브러리에서 찾는다.

3.     자바 실행을 할 때 자신의 build path에 추가된 라이브러리를 jvm에 로드 한다.

4.     2번에서도 없으면 build path에 추가된 라이브러리에서 찾는다.

A.     Build path에 추가될 때는 링크가 설정된다.

B.     외부 라이브러리를 사용할 때는 프로젝트에서 포함해서 배포 하던가 다운로드 링크를 같이 제공해야 한다.

 

 

HTML Parsing

×         Java에서는 PythonBeautifulSoup 과 유사한 JSoup 이라는 라이브러리를 이용

1.     https://www.naver.com에서 원하는 항목의 값 가져오기

A.     프로젝트의 build pathjsoup 라이브러리를 추가

                       i.        www.mvnrepository.com 에서 jsoup을 검색해서 다운로드

                      ii.        다운로드 받은 파일을 프로젝트에 복사

                     iii.        복사한 파일을 선택해서 마우스 오른쪽을 클릭하고 [Build Path] – [Add To Build Path]를 실행

B.     코드를 작성

 

       public static void main(String[] args) {

               //필요한 HTML 다운로드 : https://www.naver.com에서 다운로드

               String html = null;

               try {

                      //다운로드 받을 URL 생성

                      //URL 한글이 있으면 URLEncoder.encode 이용해서 인코딩을 해야 한다.

                      String addr = "https://www.naver.com";

                      URL url = new URL(addr);

                     

                      //연결

                      HttpURLConnection con = (HttpURLConnection)url.openConnection();

                      con.setConnectTimeout(30000);

                      con.setUseCaches(false);

                     

                      //데이터를 다운로드

                      StringBuilder sb = new StringBuilder();

                      BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));

                      while(true) {

                             String line = br.readLine();

                             if(line == null) {

                                    break;

                             }

                             sb.append(line + "\n");

                      }

                     

                     

                      //사용한 스트림 정리

                      br.close();

                      con.disconnect();

                     

                      //데이터 확인

                      html = sb.toString();

                      //System.out.println(html);

                     

                     

                     

               }catch(Exception e) {

                      System.out.println("다운로드 예외:" + e.getMessage());

                      e.printStackTrace();

               }

              

               if(html == null) {

                      System.out.println("다운로드 받은 문자열이 없습니다.");

                      return;

               }

              

               //HTML 파싱을 해서 원하는 자료구조를 만들기

               try {

                      //문자열을 메모리에 DOM(Document Object Model)으로 펼치기

                      Document document = Jsoup.parse(html);

                     

                     

                      //span 태그 가져오기 - 태그는 중복될 있으므로 여러 리턴

              

                      /*

                      Elements span = document.getElementsByTag("span");

                      //가져온 데이터를 순회하면서 출력

                      for(int i=0 ; i < span.size() ; i+=1) {

                             Element element = span.get(i);

                             System.out.println(element.text());

                      }

                     

                     

                     

                      //클래스 이름을 이용해서 찾아오기

                      Elements span = document.getElementsByClass("an_txt");

                      //가져온 데이터를 순회하면서 출력

                      for(int i=0 ; i < span.size() ; i+=1) {

                             Element element = span.get(i);

                             System.out.println(element.text());

                      }

                      */

                     

                      //선택자 이용

                      Elements span = document.select("#PM_ID_serviceNavi > li:nth-child(9) > a > span.an_txt");

                      //가져온 데이터를 순회하면서 출력

                      for(int i=0 ; i < span.size() ; i+=1) {

                             Element element = span.get(i);

                             System.out.println(element.text());

                      }

                     

                     

               }catch(Exception e) {

                      System.out.println("파싱 예외:" + e.getMessage());

                      e.printStackTrace();

               }

       }

 

2.     한겨레 신문사에서 검색을 해서 실제 기사를 전부 읽어서 파일에 저장하기

A.     검색을 이용해서 데이터를 읽어올 때는 주소 패턴을 정확하게 이해

 

 

keyword가 검색어

datefrom 이 시작날짜 dateto가 종료날짜

pageseq 가 페이지 번호 – 0부터 시작

 

 

B.     기사 개수를 읽어오는 것이 먼저반복문을 언제까지 돌려야 하는지 설정

C.     기사 검색이나 게시판, sns 검색의 경우 검색의 결과로 나온 것은 대부분 제목과 본문의 링크이다.

                       i.        검색의 결과에서 링크를 전부 찾아 실제 기사나 본문의 내용을 읽어와야 한다.

   public static void main(String[] args) {

           //한겨레 신문사 페이지에서 코로나 검색된 기사 내용을 전부 파일에 저장하기

          

           //1. 코로나로 검색된 기사 개수 파악하기

           //기사 개수를 저장할 변수

           int cnt = 0;

           try {

                  //한글로 검색어를 인코딩

                  String keyword = URLEncoder.encode("코로나", "utf-8");

                  //한겨레 신문사 뉴스 검색 URL 만들기

                  String addr = "http://search.hani.co.kr/Search?command=query&keyword="+keyword+"&media=news&submedia=&sort=d&period=all&datefrom=2000.01.01&dateto=2020.01.28&pageseq=0";

                  URL url = new URL(addr);

                  //연결 옵션과 연결

                  HttpURLConnection con = (HttpURLConnection)url.openConnection();

                  con.setConnectTimeout(20000);

                  con.setUseCaches(false);

                 

                  //문자열을 전부 읽어서 sb 저장하기

                  StringBuilder sb = new StringBuilder();

                  BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));

                  while(true) {

                         String line = br.readLine();

                         if(line == null) {

                                 break;

                         }

                         sb.append(line + "\n");

                  }

                 

                  String html = sb.toString();

                  br.close();

                  con.disconnect();

                  //데이터 확인 - 확인되면 주석 처리

                  //System.out.println(html);

                 

                 

                 

                 

                  //html DOM으로 펼피기

                  Document document = Jsoup.parse(html);

                  //태그이름으로 찾기

                  //Elements spans = document.getElementsByTag("span");

                  //클래스 이름으로 찾기

                  //Elements spans = document.getElementsByClass("total");

                  //System.out.println(spans);

                  //선택자를 이용해서 찾기

                  Elements spans = document.select("#contents > div.search-result-section.first-child > div > span");

                 

                  String temp = spans.get(0).text();

                 

                  //240건이라고 temp 저장 240 추출해서 정수로 변환해서 cnt 저장

                  String [] ar = temp.split(" ");

                  cnt = Integer.parseInt(ar[0]);

                  //System.out.println(cnt);

                 

           }catch(Exception e) {

                  System.out.println("기사 개수 파악 예외:" + e.getMessage());

                  e.printStackTrace();

           }

          

          

          

           //검색된 데이터의 링크를 전부 찾아서 list 삽입

           ArrayList <String> list = new ArrayList<String>();

           try {

                  //페이지 개수 구하기

                  int pagesu = cnt / 10;

                  if(pagesu % 10 != 0) {

                         pagesu+=1;

                  }

                 

                  //페이지 단위로 순회

                  for(int i=0 ; i<pagesu ; i+=1) {

                         //한글로 검색어를 인코딩

                         String keyword = URLEncoder.encode("코로나", "utf-8");

                         //한겨레 신문사 뉴스 검색 URL 만들기

                         String addr = "http://search.hani.co.kr/Search?command=query&keyword="+keyword+"&media=news&submedia=&sort=d&period=all&datefrom=2000.01.01&dateto=2020.01.28&pageseq="+i;

                         URL url = new URL(addr);

 

                        

                         //연결 객체 만들기

                         HttpURLConnection con = (HttpURLConnection)url.openConnection();

                         con.setConnectTimeout(10000);

                         con.setUseCaches(false);

                        

                        

                         //특정 페이지의 데이터를 읽지 못하더라도 다음 페이지의 데이터를 읽기 위해서 박복문 안에 예외처리 문장 삽입

                         try {

                                 StringBuilder sb = new StringBuilder();

                                 BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));

                                 while(true) {

                                        String line = br.readLine();

                                        if(line == null) {

                                               break;

                                        }

                                     sb.append(line+"\n");

                                 }

                                 String html = sb.toString();

                                 br.close();

                                 con.disconnect();

                                

                                 Document document = Jsoup.parse(html);

                                 Elements links = document.select("dl > dt > a");

                                 for(int j=0 ; j<links.size() ; j+=1) {

                                        //a 태그 안에 있는 문자열을 가져오기

                                     //System.out.println(links.get(j).text());

                                       

                                        //a 태그의 href 속성의 가져오기

                                     //System.out.println(links.get(j).attr("href"));

                                     list.add(links.get(j).attr("href"));

                                 }

                             //System.out.println(list.size());

                         }catch(Exception e){

                                 System.out.println("링크 수집 예외:" + e.getMessage());

                                 e.printStackTrace();

                         }

                        

                         //반복문 안에 try catch 하는 경우는 권장하지않지만 해야 하는 경우도 있다.

                  }

           }catch(Exception e){

                  System.out.println("링크 수집 예외:" + e.getMessage());

                  e.printStackTrace();

           }

          

           //list 저장된 링크의 기사 데이터를 전부 읽어서 파일에 저장하기

           try {

                  for(String addr : list) {

                         try {

                                 URL url = new URL(addr);

                                 HttpURLConnection con = (HttpURLConnection)url.openConnection();

                                 con.setUseCaches(false);

                             con.setConnectTimeout(10000);

                                

                                 StringBuilder sb = new StringBuilder();

                                 BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));

                                

                                 while(true) {

                                        String line = br.readLine();

                                        if(line == null){

                                               break;

                                        }

                                     sb.append(line+"\n");

                                 }

                                 String html = sb.toString();

                                 br.close();

                                 con.disconnect();

                             //System.out.println(html);

                                 //파일에 기록

 

                                 Document document = Jsoup.parse(html);

                                 //class title 태그만 찾아오기

                                 Elements articles = document.getElementsByClass("title");

                                 //찾아온 데이터를 파일에 기록

                                 for(int i=0 ; i<articles.size(); i+=1) {

                                        PrintWriter pw = new PrintWriter(new FileOutputStream("./코로나.txt", true)); //true 써야 append모드

                                 pw.println(html);

                                 pw.flush();

                                 pw.close();

                                 }

                                

                                

                                

                                

                                 //실제 여러 개의 페이지에서 스크래핑할 딜레이를 주는 것이 좋다

                                 //Thread.sleep(1000);

                         }catch(Exception e) {

                                 System.out.println("기사 읽기 예외:" + e.getMessage());

                         }

                  }

                 

           }catch(Exception e) {

                  System.out.println("링크 읽기 예외:" + e.getMessage());

                 

           }

 

    }

 

 

 

**일반적인 방법으로 web 의 데이터를 못 읽는 경우

1.ajax를 이용해서 동적으로 데이터를 가져와서 출력하는 경우

=>ajax: 현재 페이지를 다시 호출하지 않고 동적으로 데이터를 가져오는 기술

javahttpURLConnectoin이나 pythonrequests 모듈은 접속햇을 때 존재하는 데이터 읽어 올 수 있다.

 

2.로그인을 해야만 사용가능한 데이터

 

**selenium

=>웹 페이지를 테스트 하기 위한 라이브러리로 출발

=>브라우저를 실행시켜 직접 제어 가능한 라이브러리

=>브라우저로 URL에 접속한 후 일정 시간 대기한 후 페이지의 데이터를 읽어내면 ajax형태로 읽어오는 데이터도 사용이 가능

=>자바스크립트를 이용해서 로그인과 같은 폼에 데이터 입력이 가능하기 때문에 로그인 한 후 접근 가능한 데이터도 사용이 가능

=>자바 이외 파이썬에서도 사용이 가능

 

1.준비

1)selenium라이브러리를 다운로드 받아서 프로젝트에 포함

- www.seleniumhq.org에서 다운로드받아도 되고 www.mvnrepository.com 에서 selenium검색 후 다운로드

- 다운로드 받은 파일을 프로젝트에 복사하고 선택한 후 [build path] -[Add To Build Path]

www.mvnrepository.com여기서 다운로드 실패

 

2) 동작시키고자 하는 브라우저의 드라이버 파일을 다운로드

=>브라우저 없이 하고자 하면 pantom.js를 다운로드 받으면 되는데 deprecated

=>chrome의 경우는 버전에 맞는 드라이버를 다운로드

chrome버전 확인

https://chromedriver.chromium.org/downloads 에서 다운로드 한 후 압축해제

 

2.크롬을 실행시켜 사이트에 접속

1) 크롬드라이버 이름과 드라이버 위치를 시스템 프로퍼티에 추가

System.setProperty("webdriver.chrome.driver",String 드라이브 파일의 경로);

 

2)크롬 실행

WebDriver driver = new ChromeDriver();

 

3)사이트 접속

driver.get("사이트 URL")

 

 

4)사이트의 HTML

driver.getPageSource();

 

5)크롬을 실행시켜 naver에 접속하고 html가져오기

public class ChromeRun {

       public static void main(String[] args) {

               //크롬 드라이버의 위치를 프로퍼티에 추가

               System.setProperty("webdriver.chrome.driver", "C:\\project\\JAVA_PROJECT\\java\\src\\java\\chromedriver.exe");

               //크롬실행

               WebDriver driver = new ChromeDriver();

               //크롬에서 사이트에 접속

               driver.get("https://www.naver.com");

               //접속한 사이트의 html 가져오기

               System.out.println(driver.getPageSource());

       }

}

 

3.Element선택

driver.findElement(By.id, "실제id"); //하나만 나온다.

driver.findElement(By.xpath, " xpath"); //하나만 나온다.

 

driver.findElements(By.tagName, "tag");

driver.findElements(By.class, "class");

 

선택한 요소가 폼의 입력도구 인 경우 .send_keys(String value)를 호출하면 value폼의 입력도구가 채워짐

선택한 요소가 폼의 버튼이나 링크 인 경우 .click()를 호출하면 버튼이나 링크를 클릭한 효과

폼의 submit이면 submit()을 호출하면 폼의 데이터를 전송

 

 

4.페이지 접속과 해제

get(String url): url에 접속

 

close(): 종료

 

5.프레임(페이지를 나누어서 다른 html을 불러온다던가 다른 dom 객체를 가져와서 출력) 전환

switchTo().frame(프레임 Element)

 

6.크롬을 실행시키지 않고 작업

ChromeOptions options = new ChromeOptions();

options.addArguments("headless");

WebDriver driver = new ChromeDriver(options);

 

7.다음 로그인을 해서 카페에 글 쓰기

public class DaumLogin {

       public static void main(String[] args) {

               // 크롬 드라이버의 위치를 프로퍼티에 추가

               // 맥에서는 아래것 필요없다.

               System.setProperty("webdriver.chrome.driver",

                      "C:\\project\\JAVA_PROJECT\\java\\src\\java\\chromedriver.exe");

               // 크롬실행

               WebDriver driver = new ChromeDriver();

               // 크롬에서 사이트에 접속

          driver.get("https://logins.daum.net/accounts/signinform.do?url=https%3A%2F%2Fwww.daum.net%2F");

               // https://accounts.kakao.com/login?continue=https%3A%2F%2Flogins.daum.net%2Faccounts%2Fksso.do%3Frescue%3Dtrue%26url%3Dhttps%253A%252F%252Fwww.daum.net%252F

               // driver.get("https://accounts.kakao.com/login?continue=https%3A%2F%2Flogins.daum.net%2Faccounts%2Fksso.do%3Frescue%3Dtrue%26url%3Dhttps%253A%252F%252Fwww.daum.net%252F");

               // 아이디와 비밀번호 입력받기

               Scanner sc = new Scanner(System.in);

               System.out.print("아이디를 입력하세요:");

               String id = sc.nextLine();

               System.out.print("비밀번호를 입력하세요:");

               String pwd = sc.nextLine();

               // 아이디란과 비밀번호 입력란에 입력받은 내용을 입력하기

       driver.findElement(By.xpath("//*[@id=\"id\"]")).sendKeys(id);

       driver.findElement(By.xpath("//*[@id=\"inputPwd\"]")).sendKeys(pwd);

               //// *[@id="id_email_2"]

               //// *[@id="id_password_3"]

               // driver.findElement(By.xpath("//*[@id=\"id_email_2\"]")).sendKeys(id);

               // driver.findElement(By.xpath("//*[@id=\"id_password_3\"]")).sendKeys(pwd);

 

               //// *[@id="login-form"]/fieldset/div[8]/button

       driver.findElement(By.xpath("//*[@id=\"loginBtn\"]")).click();

               // driver.findElement(By.xpath("//*[@id=\"login-form\"]/fieldset/div[8]/button")).click();

 

              

               try {

                      Thread.sleep(5000);

               } catch (InterruptedException e) {

                      // TODO Auto-generated catch block

                      e.printStackTrace();

               }

              

               // 카페에 접속

              driver.get("http://cafe.daum.net/samhak7/_memo");// 카페주소

               //// *[@id="memoForm__memo"]/div/table/tbody/tr[1]/td[1]/div/textarea

               // 이것이 안된다. 프레임 보기에서 봐야 하기 때문이다.

               // driver.findElement(By.xpath("//

       ////*[@id="memoForm__memo"]/div/table/tbody/tr[1]/td[1]/div/textarea")).sendKeys("내용");

               // 프레임을 전환: down이라는 프레임으로 전환

          driver.switchTo().frame(driver.findElement(By.id("down")));

               System.out.print("입력할 모드:");

               String memo = sc.nextLine();

               //입력받은 내용ㅇ을 입력란에 추가

               // driver.findElement(By.name("memo_content")).sendKeys("메코로 연습");;

       driver.findElement(By.xpath("//*[@id=\"memoForm\"]/div/table/tbody/tr[1]/td[1]/div/textarea")).sendKeys(memo);

       ////*[@id="memoForm"]/div/table/tbody/tr[1]/td[2]/a[1]/span[2]

               //등록 버튼 클릭

       driver.findElement(By.xpath("//*[@id=\"memoForm\"]/div/table/tbody/tr[1]/td[2]/a[1]/span[2]")).click();

              

               sc.close();

       }

}

 

8.네이브 로그인

public class NaverLogin {

       public static void main(String[] args) {

               // 크롬 드라이버의 위치를 프로퍼티에 추가

               // 맥에서는 아래것 필요없다.

               System.setProperty("webdriver.chrome.driver",

                      "C:\\project\\JAVA_PROJECT\\java\\src\\java\\chromedriver.exe");

               // 크롬실행

               WebDriver driver = new ChromeDriver();

               // 크롬에서 네이브 로그인 사이트에 접속

              driver.get("https://nid.naver.com/nidlogin.login?mode=form&url=https%3A%2F%2Fwww.naver.com");

              

               // 아이디와 비밀번호 입력받기

               Scanner sc = new Scanner(System.in);

               System.out.print("아이디를 입력하세요:");

               String id = sc.nextLine();

               System.out.print("비밀번호를 입력하세요:");

               String pwd = sc.nextLine();

               // 아이디란과 비밀번호 입력란에 입력받은 내용을 입력하기

              

               //아이디가 있으면 xpath 필요 없다.

               driver.findElement(By.id("id")).sendKeys(id);

               driver.findElement(By.id("pw")).sendKeys(pwd);

              

           driver.findElement(By.id("log.login")).click();//click으로 안되면 submit으로 하기

               //자동입력 방지 문자를 입력하는데 나중에 스크립트를 배우면 있다.

              

               //로그인해서 가져오는 것은 이렇게 하면 된다.

               String html = driver.getPageSource();

               Document document = Jsoup.parse(html);

              

               sc.close();

       }

}

 

 

**람다(Lambda)

부르는 언어마다 용도가 조금 다르다.

=>자바에서의 람다는 함수형 프로그래밍을 지원하기 위해서 1.7에서 부터 지원하기 시작한 이름없는 함수

=>메소드가 하나 뿐인 인터페이스를 구현해서 사용할 때 람다를 이용해서 대입하는 것이 가능

=>Intelli J Android Studio의 경우 메소드가 하나 뿐인 인터페이스를 anonymous를 이용해서 작성하면 람다로 자동 수정됩니다.

=>이전의 자바는 완전한 객체 지향 언어로서 메소드의 매개변수로 함수를 대입할 수 없었습니다.

누군가에게 작업만을 수행해달라고 요청을 해야 하는 경우 자바는 객체를 만들어서 메소드 형태로 대입한 후 요청을 했습니다.

이런 이유로 자바로 작업을 요청하는 경우 시스템이 무거워졌습니다.

이런함 문제를 해결하기 위해서 등장했던 언어들이 jvm을 사용하는 scala, Closure, Kotlin같은 언어들입니다.

위의 언어들은 마지막에는 java로 번역되서 jvm위에서 실행됩니다.

scala에서는 python을 쓸 수 있다. 자바에서는 아직 변환이 안됬다.

 

=>자바에서도 이러한 함수형 프로그래밍을 지원하기 위해서 등장시킨 개념이 람다와 스트림입니다.

1.8 이상에서만 사용이 가능

 

1.메소드가 하나뿐인 인터페이스의 구현

=>public void run이라는 메소드를 소유한 Runnable이라는 인터페이스가 있습니다.

이 인터페이스는 스레드를 만들어주는 인터페이스

1)인터페이스를 구현한 클래스를 생성하고 인스턴스를 만들어서 사용

public class RunnableImpl implements Runnable {

 

       @Override

       public void run() {

               // 클래스를 만들어서 사용한다고 출력

               try {

                      for (int i = 0; i < 10; i++) {

                             Thread.sleep(1000);

                             System.out.println("킆래스를 만들어서 사용");

                      }

               } catch (InterruptedException e) {

                      System.out.println("예외 발생:" +e.getMessage());

               }

       }

}

 

2)Main 메소드

public class ThreadMain {

       public static void main(String[] args) {

               //Runnable인터페이스를 구현한  클래스를 이용해서 스레드 생성 실행

               //인스턴스를 1개만 만들어서 사용한다면 메모리 낭비 - 클래스를 만들었기 때문에 클래스는 멤모리에서 삭제가 안됨

               Thread th1 = new Thread(new RunnableImpl());

               th1.start();

              

               //클래스를 만들지 않고 사용 -  anonymous class

               Thread th2 = new Thread(new Runnable() {

                      @Override

                      public void run() {

                             try {

                                    Thread.sleep(1000);

                                    System.out.println("anonymous class 이용");

                             } catch (InterruptedException e) {

                                    System.out.println("예외 발생:" +e.getMessage());

                             }

                            

                      }

               });

               th2.start();

              

               //람다 이용

               //인스턴스를 만드는 과정도 없고 메소드 이름도 없지만 위와 동일한 기능을 수행

               Thread th3 = new Thread(()-> {

                      try {

                             Thread.sleep(1000);

                             System.out.println("람다 이용");

                      } catch (InterruptedException e) {

                             System.out.println("예외 발생:" +e.getMessage());

                      }

                     

               });

               th3.start();

       }

}

 

2.자바에서 람다

1) 직접 호출해서 메소드를 실행할 때는

인퍼페이스 변수 = 람다식 ;

변수 . 메소드 ()

 

2)1.8이상의 api를 사용하는 경우에는 람다식만 대입해서 메소드를 사용

대부분이 스트림 api

 

3.람다식 작성 요령

(타입 매개변수 , 타입 매개변수 ..) ->{메소드 내용 작성 : return 데이터}

=>매개변수의 자료형은 생략 가능: 호출할 때 대입되는 데이터를 가지고 자료형을 유추

=>매개변수가 없을 때는 ()을 해야 하지만 매개변수가 1개인 경우는 ()을 생략 가능

=>메소드 내용이 할 줄이면 {} 도 생략가능

=>리턴 타입은 작성할 필요없고 return을 해야하면 return 테이터 ; 만 해주면 됩니다.

 

4. 람다식을 사용할 수 있는 인터페이스는 메소드가 반드시 1개만 존재해야 합니다.

이러한 인터페이스는 @FunctionallInterface라는 어노페이션을 이용해서 생성

comparable는 사용할 수 없다.

 

5.매개변수가 없고 리턴 타입이 없는 메소드를 소유한 인터페이스의 경우

() -> {메소드 내용}

=>매개변수도 없고 리턴 타입도 없는 경우는 굉장히 드문 경우

=>이런 메소드는 출력하는 메소드 정도에서만 가능

메소드() python등에서도 줄 바꿈  준것도 없고 리턴도 없다.

 

 

5.람다 작성

//매개 변수가 없고 리턴 타입이 없는 메소드를 소유한 인터페이스

interface NoArgNoReturn{

       public void method1();

}

 

//매개변수가 있고 리턴 타입이 없는 경우 : 원본에 작업을 해서 원본을 변환시키는 인터페이스

interface ArgNoReturn{

       public void method2(int x);

}

 

//매개변수는 없고 리턴 타입만 있는 경우 : 거의 없는 경우

interface NoArgReturn{

       public double method3();

}

 

//재일 많은 형태 매개변수가 있고 리턴타입이 있는 경우 - 가장 많은 경우

interface ArgReturn{

       //문자열 주면 정수로 변환

       public int method4(String str);

}

 

public class LambdaMain {

       public static void main(String[] args) {

               //NoArgNoReturn ob1= 람다식;

               //매개변수가 없고 리턴도 없는 메소드를 활용

               NoArgNoReturn ob1= () -> {System.out.println("매개변수가 없고 리턴도 없는 람다");};

               //메소드 1 내용이 자동으로 들어간다.

               ob1.method1();

              

               //매개변수가 있는 경우 - 매개변수의 자료형은 생략이 가능 , 매개변수가 1개인 경우는 () 감싸지 않아도 됩니다.

               ArgNoReturn ob2= (int x)->{System.out.println(x+10);};

               ob2.method2(100);

              

               NoArgReturn ob3 = ()->{return 10.3;};

               double d = ob3.method3();

               System.out.println(d);

              

               //매개변수가 있고 리턴에 있는 경우 -데이터를 가공해서 리턴하는 함수

               ArgReturn ob4= (String str)->{return Integer.parseInt(str);};

               int d1 = ob4.method4("1343");

               System.out.println(d1);

       }

}

 

6.람다식을 사용할 있는 인터페이스

=>1.7 부터 사용했고 1.8버전 이상에서는 java.util.function패키지에서 기본적인 람다식을 사용할 수 있는 인터페이스를 제공

Consumer:매개변수는 있고 리턴 값은 없는 메소드를 소유한 인터페이스

Supplier:.매개변수는 없고 리턴 값만 있는 메소드를 소유한 인터페이스

Function: 매개변수가 있고 리턴 값도 있는 메소드를 소유한 인터페이스 - 변환

Operator : 매개변수가 있고 리턴 값도 있는 메소드를 소유한 인터페이스

            매개변수를 누적해서 연산해서 리턴하는 메소드를 소유한 인터페이스 - 연산(합계, 평균, 최대값, ..)

Predicate: 매개변수가 있는 리턴 값도 있는 메소드를 소유한 인터페이스

리턴 값이 boolean

조건에 맞는 데이터만 골라내는 메소드를 소유한 인터페이스

=>기본적으로 제너릭을 적용 - 매개변수의 자료형은 Generic으로 설정

//매개 변수가 없고 리턴 타입이 없는 메소드를 소유한 인터페이스

interface NoArgNoReturn{

       public void method1();

}

 

//매개변수가 있고 리턴 타입이 없는 경우 : 원본에 작업을 해서 원본을 변환시키는 인터페이스

interface ArgNoReturn{

       public void method2(int x);

}

 

//매개변수는 없고 리턴 타입만 있는 경우 : 거의 없는 경우

interface NoArgReturn{

       public double method3();

}

 

//재일 많은 형태 매개변수가 있고 리턴타입이 있는 경우 - 가장 많은 경우

interface ArgReturn{

       //문자열 주면 정수로 변환

       public int method4(String str);

}

 

public class LambdaMain {

       public static void main(String[] args) {

               //NoArgNoReturn ob1= 람다식;

               //매개변수가 없고 리턴도 없는 메소드를 활용

               NoArgNoReturn ob1= () -> {System.out.println("매개변수가 없고 리턴도 없는 람다");};

               //메소드 1 내용이 자동으로 들어간다.

               ob1.method1();

              

               //매개변수가 있는 경우 - 매개변수의 자료형은 생략이 가능 , 매개변수가 1개인 경우는 () 감싸지 않아도 됩니다.

               ArgNoReturn ob2= (int x)->{System.out.println(x+10);};

               ob2.method2(100);

              

               NoArgReturn ob3 = ()->{return 10.3;};

               double d = ob3.method3();

               System.out.println(d);

              

               //매개변수가 있고 리턴에 있는 경우 -데이터를 가공해서 리턴하는 함수

               ArgReturn ob4= (String str)->{return Integer.parseInt(str);};

               int d1 = ob4.method4("1343");

               System.out.println(d1);

              

               //consumer 인터페이스는 매개변수가 1개이고 리턴타입이 없는 메소드를 소유

               Consumer<String> consumer = (t)->{System.out.println(t);};

               consumer.accept("Java Lambda");

              

               //fUNCTION 인터페이스는 매개변수가 1개이고 리턴타입이 있는 메소드를 소유

               //제너릭에서 앞의 자료형은 매개변수의 자료형이고 뒤의 자료형은 리턴타입의 자료형

               //데이터를 받아서 변환한 리턴해주는 메소드

               //빅데이터 처리 할려고 하는데 반복문 쓰고 함수 적용할려고

               Function<String,String> function = (str)->{

                      if(str.length() <= 3)return str;

                      else return str.substring(0,3)+"...";};

               String r = function.apply("hi");

               System.out.println(r);

               r = function.apply("Hello World");

               System.out.println(r);

       }

}

 

 

 

 

반응형

'Study > Java' 카테고리의 다른 글

java-18  (0) 2020.10.10
java-17  (0) 2020.10.10
java-15  (1) 2020.10.05
java-14  (0) 2020.10.04
java-13  (0) 2020.10.03

+ Recent posts